Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97296934ab | ||
|
|
83dbe5fa3e | ||
|
|
b566b8b45a | ||
|
|
ecdfda56c2 | ||
|
|
166c4a244a | ||
|
|
be7bfbac39 | ||
|
|
3c8953672d | ||
|
|
045b196eeb | ||
|
|
d763fce8ed | ||
|
|
15c8ba5d3f | ||
|
|
1b75017c3c | ||
|
|
3ffe5e958f | ||
|
|
4f6a78cde8 | ||
|
|
3081d0766b | ||
|
|
c1e34cb9b5 | ||
|
|
dedf67fb52 | ||
|
|
a74fb940aa | ||
|
|
09275ae4ca | ||
|
|
657717d0fb | ||
|
|
4493d35d26 | ||
|
|
0d26ce9bcc | ||
|
|
fe77075996 | ||
|
|
4d6b126b9d | ||
|
|
7b1900d547 | ||
|
|
5a8c56e784 | ||
|
|
8c4cfc8101 | ||
|
|
5f1f5ffffd | ||
|
|
603c4b7672 | ||
|
|
4b49c63344 | ||
|
|
9bdc910327 | ||
|
|
730f50f770 | ||
|
|
91606a9e3f | ||
|
|
22b52f831b | ||
|
|
071b3f558f | ||
|
|
59cd4004ac | ||
|
|
7f7c1ff6c2 | ||
|
|
ad3acf355e | ||
|
|
4dcc4e3308 | ||
|
|
a9902b55d8 | ||
|
|
d46798c2a7 | ||
|
|
90623492b7 | ||
|
|
ddf3ba8a15 | ||
|
|
0c4d33d558 | ||
|
|
1c3b6ad59b | ||
|
|
473a12d700 | ||
|
|
774cfc4bdc | ||
|
|
509fbcc4f8 | ||
|
|
00862344f7 | ||
|
|
5ad2b0531a | ||
|
|
be8dbb0dc7 | ||
|
|
bdfa0b302b | ||
|
|
7541304a9a | ||
|
|
395a51eeca | ||
|
|
17e2d49c43 | ||
|
|
ac71c320cd | ||
|
|
0356bf6092 | ||
|
|
8bc1edd027 | ||
|
|
403f0dc8a5 | ||
|
|
dffa198ebd | ||
|
|
7028417d88 | ||
|
|
2d4ebba3ed | ||
|
|
aa3fda9c33 | ||
|
|
0f9f0b545e | ||
|
|
9fcc398540 | ||
|
|
61f4ab61cb | ||
|
|
1f481cbe54 | ||
|
|
f4ee10a96a | ||
|
|
9974be3fdc | ||
|
|
793171e9e0 | ||
|
|
cee7087d54 | ||
|
|
f9bcffcbd5 | ||
|
|
8fd7e87333 | ||
|
|
c436194d43 | ||
|
|
fcd160cc8c | ||
|
|
5adbadc901 | ||
|
|
5084279d81 | ||
|
|
bd21d0d0cf | ||
|
|
a3fd81540a | ||
|
|
ba3f6a5e76 | ||
|
|
25c56e86c9 | ||
|
|
0897b0969d | ||
|
|
6cb1c3c0e9 | ||
|
|
df257a8e8a | ||
|
|
71abdc1bda | ||
|
|
22de1dc0f2 | ||
|
|
6357b30712 | ||
|
|
b0e18d5e8a | ||
|
|
be58d73a0a | ||
|
|
c1f630f5ed | ||
|
|
ab75bfa6e7 | ||
|
|
a4e0225c69 | ||
|
|
6d3d6c3601 | ||
|
|
2872de75a0 | ||
|
|
70936e3738 | ||
|
|
c272883ec1 | ||
|
|
d9619a8fa4 | ||
|
|
9ec2022447 | ||
|
|
10f56c55e6 | ||
|
|
69682d6d97 | ||
|
|
b61575eb2b | ||
|
|
6942de4f57 | ||
|
|
8085e21a05 | ||
|
|
0061fe02e6 | ||
|
|
6bb40e6ec9 | ||
|
|
94efcc83a1 | ||
|
|
03402cf359 | ||
|
|
a473cf99b5 | ||
|
|
c26bd2ffe8 | ||
|
|
9dc3d09981 | ||
|
|
76b4c9a6ff | ||
|
|
41add69294 | ||
|
|
c911c9ad19 | ||
|
|
dd883c0563 | ||
|
|
16a0c89d5f | ||
|
|
ac0e6f3377 | ||
|
|
68f7be7a1a | ||
|
|
b796e33ede | ||
|
|
1051ba77c0 | ||
|
|
cb5b6b972a | ||
|
|
925f21aca4 | ||
|
|
dc09851ac8 | ||
|
|
323ba9d90c | ||
|
|
c6ff8ab6dc | ||
|
|
b5443f10c5 | ||
|
|
3ae1a0f82a | ||
|
|
81f0f8a7c2 | ||
|
|
50963df42f | ||
|
|
b316989378 | ||
|
|
23c68e2677 | ||
|
|
b46bee0540 | ||
|
|
4c6c27d8f6 | ||
|
|
3c531897b6 | ||
|
|
6c7672f4af | ||
|
|
2def6e867d | ||
|
|
573f13c1ed | ||
|
|
b7f9e5c947 | ||
|
|
da85affe5c | ||
|
|
3168a2aca0 | ||
|
|
1f5feaa103 | ||
|
|
4be3dfd52b | ||
|
|
1e26983263 | ||
|
|
a620419b59 | ||
|
|
ffdc9b0d3a | ||
|
|
379e047289 | ||
|
|
8e420406b9 | ||
|
|
fc0364b321 | ||
|
|
ea4986dec5 | ||
|
|
2be30a3193 | ||
|
|
81f90c7b51 | ||
|
|
205a564482 | ||
|
|
497df68de1 | ||
|
|
eaf8e24d4c | ||
|
|
1721fb0484 | ||
|
|
fe0b144b84 | ||
|
|
d391bca2d3 | ||
|
|
a0b6e70ff8 | ||
|
|
4f15392440 | ||
|
|
959fcfdf1d | ||
|
|
57f90d200d | ||
|
|
663c645cf1 | ||
|
|
972b255a48 | ||
|
|
8c5dfa4227 | ||
|
|
290d48e1aa | ||
|
|
4eb3a1c978 | ||
|
|
b4a36a8303 | ||
|
|
d08ee4e63a | ||
|
|
42f5802e47 | ||
|
|
120ffb0b1f | ||
|
|
d3a3ba0a32 | ||
|
|
79eebc14bb | ||
|
|
6fc41e2a3c | ||
|
|
4843323f87 | ||
|
|
04c6f3e6ef | ||
|
|
5345c7260e | ||
|
|
71a48ccde0 | ||
|
|
41e24d7733 | ||
|
|
f888b30863 | ||
|
|
10029d6a8d | ||
|
|
6697a2cfaa | ||
|
|
59020e0d5d | ||
|
|
70abd1f98d | ||
|
|
312ca8e978 | ||
|
|
e1ccdc0570 | ||
|
|
c7f9fe4a03 | ||
|
|
89aaf1c30c | ||
|
|
601af780c9 | ||
|
|
93477c8db4 | ||
|
|
ec5531dbf4 | ||
|
|
157f87f01a | ||
|
|
0f4ca8d010 | ||
|
|
0a168b6791 | ||
|
|
a025577b30 | ||
|
|
ef61d6ea48 | ||
|
|
e6bf658271 | ||
|
|
9cccb9839b | ||
|
|
2bd188f3d6 | ||
|
|
9fa840c1c7 | ||
|
|
e0e599ffa1 | ||
|
|
e93d18d200 | ||
|
|
34150f3f71 | ||
|
|
db6730c8a3 | ||
|
|
08cac802a4 | ||
|
|
af6a52e060 | ||
|
|
1c63645254 | ||
|
|
be5d8b1d4f | ||
|
|
2ac3552e6e | ||
|
|
3c3c775213 | ||
|
|
a24b7043ed | ||
|
|
7b621d7b5b | ||
|
|
8a335a8cea | ||
|
|
355c292dbf | ||
|
|
2511d747ae | ||
|
|
03c326a04e | ||
|
|
b3312f3761 | ||
|
|
2e250ee7aa | ||
|
|
924984dde1 | ||
|
|
33b7bb91d9 | ||
|
|
f68fe0fb5c | ||
|
|
e6663ec186 | ||
|
|
6ff0f9ccd8 | ||
|
|
48830aa9a9 | ||
|
|
9276f764e0 | ||
|
|
7876d464f2 | ||
|
|
5d0d01c2c1 | ||
|
|
393418d50d | ||
|
|
23bb912eb5 | ||
|
|
1d5b5296da | ||
|
|
655f5db996 | ||
|
|
c20cc4ae09 | ||
|
|
7581229bbf | ||
|
|
d094e090ff | ||
|
|
c7a13025e4 | ||
|
|
e4cd6bd824 | ||
|
|
f3ad0572e2 | ||
|
|
406d6cc305 | ||
|
|
d042697b10 | ||
|
|
ba678b9ad1 | ||
|
|
7a5cf118e9 | ||
|
|
e9a2da61ef | ||
|
|
d3fe1ef681 | ||
|
|
9725bca966 | ||
|
|
1f627e4263 | ||
|
|
7ac0c5fc2a | ||
|
|
091ebd8a98 | ||
|
|
d9a6e85b65 | ||
|
|
7cc3d89980 | ||
|
|
f58b90f7ea | ||
|
|
fd84109c1d | ||
|
|
626f605835 | ||
|
|
943a8a2708 | ||
|
|
d7b2b3f42e | ||
|
|
fafc5c8348 | ||
|
|
15bd8b4fe9 | ||
|
|
928aed4342 | ||
|
|
98782e44c2 | ||
|
|
65b23777b2 | ||
|
|
c8fd3d6d25 | ||
|
|
01e7cd5f13 | ||
|
|
3ac9bd0468 | ||
|
|
9f498d2eea | ||
|
|
2d2d9ad277 | ||
|
|
2cc18a8ea3 | ||
|
|
25036d5f48 | ||
|
|
defee39ef9 | ||
|
|
c78afb12a3 | ||
|
|
f72b0b5056 | ||
|
|
d46e505a80 | ||
|
|
4027bcf7ea | ||
|
|
2905392665 | ||
|
|
98db3360df | ||
|
|
f26c713482 | ||
|
|
05e55334fc | ||
|
|
01fe61276e | ||
|
|
219253ad71 | ||
|
|
7b125558cb | ||
|
|
02120e24b6 | ||
|
|
91bc79c14c | ||
|
|
5ca552cf1c | ||
|
|
2066304b14 | ||
|
|
1c6f8b95eb | ||
|
|
5384591f5b | ||
|
|
309668ccbc | ||
|
|
06a9fb3f53 | ||
|
|
00db56f7d7 | ||
|
|
cec06eb25c | ||
|
|
73a3897e1b | ||
|
|
100c4c15ce | ||
|
|
c59bf6613a | ||
|
|
ac435bcb91 | ||
|
|
5d0bfccbc7 | ||
|
|
813489dc2f | ||
|
|
828f31d5e6 | ||
|
|
8130f7f25f | ||
|
|
943e1c5f77 | ||
|
|
ecb3301bcb | ||
|
|
a0f33aebf7 | ||
|
|
6862981640 | ||
|
|
f61f2d2e9f | ||
|
|
1743e175cd | ||
|
|
a027f58744 | ||
|
|
c98886402b | ||
|
|
112a1e908a | ||
|
|
01ae80ecd1 | ||
|
|
52997c6c51 | ||
|
|
1c114a279e | ||
|
|
93148e3223 | ||
|
|
f01807ef17 | ||
|
|
a4ed740518 | ||
|
|
0e2f3de154 | ||
|
|
d128d2146a | ||
|
|
c683e1e988 | ||
|
|
0b7038d44d | ||
|
|
55698b91c0 | ||
|
|
eff54827b2 | ||
|
|
2c2c7f6894 | ||
|
|
5baa4d969e | ||
|
|
d745c41d5b | ||
|
|
a86bde7b3f | ||
|
|
4ab2309a5d | ||
|
|
9172f62970 | ||
|
|
daa47e8272 | ||
|
|
2419f02766 | ||
|
|
c8d45c9ff1 | ||
|
|
0b667ca869 | ||
|
|
1a5ea930ab | ||
|
|
e4bfb2b5b0 | ||
|
|
936e7bbc88 | ||
|
|
93b5063251 | ||
|
|
e0668bc1c0 | ||
|
|
fa5aa308bc | ||
|
|
cbfa57a955 | ||
|
|
f8898b016e | ||
|
|
8a9630485f | ||
|
|
066e4ac332 | ||
|
|
f231760395 | ||
|
|
ebfa5f0ba7 | ||
|
|
d7754516f0 | ||
|
|
00fd1884ff | ||
|
|
b828be4873 | ||
|
|
4045a541ef | ||
|
|
f7557c9e48 | ||
|
|
7c62b5005e | ||
|
|
b804217501 | ||
|
|
c6128094b6 | ||
|
|
0fc0230364 | ||
|
|
dd6458262d | ||
|
|
eb68bb2ce1 | ||
|
|
8dc62c25ed | ||
|
|
d8fec13d2c | ||
|
|
922d148ab5 | ||
|
|
08f05d6f8c | ||
|
|
7bec3b4954 | ||
|
|
4d3fba57d4 | ||
|
|
1a8a144726 | ||
|
|
00ea3830a7 | ||
|
|
3880300cd9 | ||
|
|
6b0e4a425d | ||
|
|
f883504d2d | ||
|
|
a1c5995967 | ||
|
|
8500afbbd4 | ||
|
|
13cb94cf2b | ||
|
|
f26a79d75c | ||
|
|
68e2cd9b29 | ||
|
|
6e44bab3d5 | ||
|
|
677fea7bfa | ||
|
|
0d2ae10bd9 | ||
|
|
faa582040b | ||
|
|
0ad4002569 | ||
|
|
dfc2e97d5e | ||
|
|
57159dc5c0 | ||
|
|
77ff1511ff | ||
|
|
124ab99995 | ||
|
|
8ea08306b8 | ||
|
|
3e0d20a335 | ||
|
|
727b3d4f19 | ||
|
|
80782b289f | ||
|
|
72127a4bed | ||
|
|
d4a49e00e7 | ||
|
|
5826d0e41c | ||
|
|
68cb7ce8d9 | ||
|
|
514699fc41 | ||
|
|
deca1aaf46 | ||
|
|
b8bfa5565b | ||
|
|
50c7844031 | ||
|
|
cba0d1b2f9 | ||
|
|
5735ee3269 | ||
|
|
ee3593b887 | ||
|
|
9bebe7cf68 | ||
|
|
bd5e4dba26 | ||
|
|
2427c40a4c | ||
|
|
744df7b244 | ||
|
|
3965aecfd4 | ||
|
|
93bcde0176 | ||
|
|
4b3884a49d | ||
|
|
768908ae4a | ||
|
|
1a965d5c43 | ||
|
|
01b612cff5 | ||
|
|
176db1aedb | ||
|
|
06f8238107 | ||
|
|
97127a57da | ||
|
|
61825b2390 | ||
|
|
669ffe2c74 | ||
|
|
a50b8ff5d7 | ||
|
|
aae2954c14 | ||
|
|
abab569778 | ||
|
|
365a731574 | ||
|
|
285dc63c5c | ||
|
|
24d9fbffae | ||
|
|
04178ad0f7 | ||
|
|
a0e66fb9e6 | ||
|
|
df3c216315 | ||
|
|
e9a6bad751 | ||
|
|
4b7d871048 | ||
|
|
2528dd6425 | ||
|
|
b3fcd9c420 | ||
|
|
9270fc0b15 | ||
|
|
33aa021e96 | ||
|
|
1c78ed1fed | ||
|
|
562c318648 | ||
|
|
65cb894f0d | ||
|
|
bbd27a0a9c | ||
|
|
79e138ef28 | ||
|
|
387334c8c2 | ||
|
|
cd021daf79 | ||
|
|
536aa1fb62 | ||
|
|
a14a838dab | ||
|
|
ad57731ae1 | ||
|
|
ad90b0b7b1 | ||
|
|
18325cb216 | ||
|
|
8df70ba58b | ||
|
|
ee43a5389f | ||
|
|
6192573eb8 | ||
|
|
92ecef7bd3 | ||
|
|
45d7f4ca7e | ||
|
|
144c2f443e | ||
|
|
98d877c5f0 | ||
|
|
9de31ba816 | ||
|
|
560561c5b7 | ||
|
|
ed2d4c1c2b | ||
|
|
e70628cbdc | ||
|
|
161edec195 | ||
|
|
2ba4a74762 | ||
|
|
693316de44 | ||
|
|
6e68124405 | ||
|
|
c8105cffba | ||
|
|
21f6944fc7 | ||
|
|
5adcba7ba1 | ||
|
|
fc8ba744dc | ||
|
|
4fc43cfbf7 | ||
|
|
22837f93c8 | ||
|
|
b03ececbbb | ||
|
|
708908dce5 | ||
|
|
f33302acc9 | ||
|
|
7f8cdf1e79 | ||
|
|
dbc7b5e70b | ||
|
|
4c445453d3 | ||
|
|
4b8fb23def | ||
|
|
253bc64c9e | ||
|
|
32d3fc6803 | ||
|
|
920875ecc9 | ||
|
|
85d3e7f375 | ||
|
|
4ceb50d485 | ||
|
|
7d2fca9574 | ||
|
|
d88e60a525 | ||
|
|
4b4dcb20ca | ||
|
|
d4ab0aa7fd | ||
|
|
c02c1130ed | ||
|
|
f9bbb37721 | ||
|
|
57837f285f | ||
|
|
3379f11b23 | ||
|
|
c74534cf5e | ||
|
|
64ca1ad787 | ||
|
|
8022635c04 | ||
|
|
1f37595200 | ||
|
|
30738f6638 | ||
|
|
bd53e46873 | ||
|
|
122115dbea | ||
|
|
28162f8034 | ||
|
|
9cfd3124ef | ||
|
|
36748ee406 | ||
|
|
2a25e449a2 | ||
|
|
f2f60a7b3b | ||
|
|
82916a1cef | ||
|
|
f86c14abb3 | ||
|
|
fa76312313 | ||
|
|
46687f6fe3 | ||
|
|
6386cdff50 | ||
|
|
7c25c0d6f3 | ||
|
|
8ed57f57cb | ||
|
|
c8f207c277 | ||
|
|
d70d9aff11 | ||
|
|
1118c997b5 | ||
|
|
b999275550 | ||
|
|
f549646ddd | ||
|
|
5ee8552e6c | ||
|
|
b0eb7b6dec | ||
|
|
a546d360d0 | ||
|
|
3cc8a98b9d | ||
|
|
1032f0ade7 | ||
|
|
eb65d269eb | ||
|
|
b379f81004 | ||
|
|
d1b0342a18 | ||
|
|
b815e6bc04 | ||
|
|
81bf65954c | ||
|
|
9cfe72af4a | ||
|
|
7c2e1e1339 | ||
|
|
817115cb6c | ||
|
|
7a3734e54d | ||
|
|
79c3341f74 | ||
|
|
abdd14b0a1 | ||
|
|
1f77e53b23 | ||
|
|
a619de0508 | ||
|
|
8faa11585c | ||
|
|
13259f8902 | ||
|
|
bb5aba2e19 | ||
|
|
22fc01d5f2 | ||
|
|
3b4672c109 | ||
|
|
351bd42bc4 | ||
|
|
e418da4bd8 | ||
|
|
18d13f9848 | ||
|
|
ee792db6a3 | ||
|
|
129bf93b30 | ||
|
|
1dda8b9e60 | ||
|
|
107e303282 | ||
|
|
22f76091a2 | ||
|
|
376e5ccaae | ||
|
|
b792304cf8 | ||
|
|
b357485523 | ||
|
|
07936343c8 | ||
|
|
1b93ca0fb2 | ||
|
|
18cd18d1e5 | ||
|
|
deab6772e8 | ||
|
|
d6d2d7575a | ||
|
|
d63ec65663 | ||
|
|
f0a927831e | ||
|
|
ef16a733d2 | ||
|
|
9044c02edc | ||
|
|
2fa98b00f2 | ||
|
|
15b4d566e7 | ||
|
|
6dabbe237d | ||
|
|
2caff93f83 | ||
|
|
2903937cba | ||
|
|
c33fd6a7fb | ||
|
|
64180e8fe8 | ||
|
|
001134af89 | ||
|
|
b91044dea7 | ||
|
|
34639f86b0 | ||
|
|
32559f15ea | ||
|
|
b10eef1e32 | ||
|
|
7c4911598c | ||
|
|
efacb20bdc | ||
|
|
2e6188205f | ||
|
|
83fec2cf45 | ||
|
|
9be36eb9cb | ||
|
|
a51802ecaf | ||
|
|
b1c220e610 | ||
|
|
36f6b805e3 | ||
|
|
64efad9e46 | ||
|
|
8a8d5ce151 | ||
|
|
907417f9ec | ||
|
|
0965177e72 | ||
|
|
7d07ca8427 | ||
|
|
d18b2b390a | ||
|
|
fefe8b1c15 | ||
|
|
ea2ff010a9 | ||
|
|
e357cb3185 | ||
|
|
293ee2162c | ||
|
|
c29ee769bc | ||
|
|
82399f1561 | ||
|
|
9255ceaf8a | ||
|
|
bb9c7c0eb3 | ||
|
|
8ec327f9c7 | ||
|
|
c9b982eaff | ||
|
|
248e7b6e29 | ||
|
|
cb1ae312a1 | ||
|
|
aec25cf547 | ||
|
|
4db3fc2515 | ||
|
|
79d6017c56 | ||
|
|
d4c122b17a | ||
|
|
57fd93eeda | ||
|
|
19cac05747 | ||
|
|
5ebede5096 | ||
|
|
46ecb07fc8 | ||
|
|
a628a05efb | ||
|
|
fc626bb57f | ||
|
|
1291839182 | ||
|
|
736e7a2cf9 | ||
|
|
7884a2f3c7 | ||
|
|
dde699ffda | ||
|
|
fa54a22aed | ||
|
|
822b0c011a | ||
|
|
a0f8a197c9 | ||
|
|
7e75e51332 | ||
|
|
b37efbe891 | ||
|
|
6e648c90b0 | ||
|
|
377d6acc74 | ||
|
|
f552d15fe4 | ||
|
|
d1204e8a66 | ||
|
|
9ec48e41f7 | ||
|
|
9055a83b4f | ||
|
|
dd047b2613 | ||
|
|
b7a32069b1 | ||
|
|
00d475bc7e | ||
|
|
33ab44430c | ||
|
|
b355da32b9 | ||
|
|
3f0366a514 | ||
|
|
7ecbbc517d | ||
|
|
a04c94444e | ||
|
|
42b9ac1145 | ||
|
|
7be4925c70 | ||
|
|
7b19568683 | ||
|
|
8f56779855 | ||
|
|
fdfad8462c | ||
|
|
3773ef45e7 | ||
|
|
c0ca3cacb4 | ||
|
|
bed0630698 | ||
|
|
53baa18836 | ||
|
|
32a2144426 | ||
|
|
264026acde | ||
|
|
43503ef73a | ||
|
|
7f52717e9d | ||
|
|
bd59185ef1 | ||
|
|
310ffcd4eb | ||
|
|
d23664a457 | ||
|
|
a1e316ddcf | ||
|
|
e328758fc7 | ||
|
|
dbf49255a3 | ||
|
|
1391bdcf8b | ||
|
|
d8106a8ffe | ||
|
|
ae55789c4b | ||
|
|
ec02ccf5b2 | ||
|
|
f970cd78d7 | ||
|
|
8140ea16a7 | ||
|
|
2883709756 | ||
|
|
ca4c2c6c41 | ||
|
|
fbc56f4adf | ||
|
|
2f014237b2 | ||
|
|
f33e3a7752 | ||
|
|
d5b5cec797 | ||
|
|
f8e1f17651 | ||
|
|
be58bfe22b | ||
|
|
995a63dc39 | ||
|
|
e8d57ac4e1 | ||
|
|
eab3a83548 | ||
|
|
3fb9e5fd56 | ||
|
|
41448278cf | ||
|
|
48516b43c5 | ||
|
|
80b7be0568 | ||
|
|
4183552aee | ||
|
|
527e89754e | ||
|
|
30e0f42c97 | ||
|
|
39b40daf5d | ||
|
|
94636f4d30 | ||
|
|
fd53548c5e | ||
|
|
354ea30797 | ||
|
|
11303e0dc1 | ||
|
|
b4c645f703 | ||
|
|
3256218fd2 | ||
|
|
a4f14b0ddf | ||
|
|
e7459d91f9 | ||
|
|
b32d1c15f0 | ||
|
|
1e0d57a832 | ||
|
|
f3617a1cf3 | ||
|
|
89a9a50b96 | ||
|
|
69d2ba7316 | ||
|
|
3ea5f8dbde | ||
|
|
d56152875d | ||
|
|
7459d30a28 | ||
|
|
16bf9101aa | ||
|
|
2b20af36a7 | ||
|
|
f5e87cceec | ||
|
|
36fcb7ed21 | ||
|
|
9fe7807b02 | ||
|
|
88e3017ee5 | ||
|
|
17f3738192 | ||
|
|
6cfdc39005 | ||
|
|
58886a9693 | ||
|
|
66e022c454 | ||
|
|
ea3968601e | ||
|
|
54be13d1d8 | ||
|
|
22ea825d46 | ||
|
|
8c03aa2801 | ||
|
|
5bb952260a | ||
|
|
face6c44c6 | ||
|
|
66c2bfe822 | ||
|
|
3721bcc790 | ||
|
|
cacab6fe4c | ||
|
|
6ad8674cd4 | ||
|
|
847990ce49 | ||
|
|
1bfdc1f138 | ||
|
|
58367fe23e | ||
|
|
a8712e2307 | ||
|
|
8acfae1111 | ||
|
|
70fc71c6f7 | ||
|
|
dd5118cab0 | ||
|
|
2d75a6ccd4 | ||
|
|
e004ab1693 | ||
|
|
acddfc3bf4 | ||
|
|
519d4b0286 | ||
|
|
8005a5e687 | ||
|
|
f5943fe591 | ||
|
|
cea7fcdb37 | ||
|
|
b5213c13dd | ||
|
|
3a06b4833c | ||
|
|
5cdf6c1d05 | ||
|
|
5754e5dd59 | ||
|
|
e5ab1c454b | ||
|
|
697576b63c | ||
|
|
2db41aef09 | ||
|
|
7f4ad3cade | ||
|
|
74c4c32082 | ||
|
|
30d545443c | ||
|
|
dedba52315 | ||
|
|
481f7b5cff | ||
|
|
6ce4f4930c | ||
|
|
e33a10db75 | ||
|
|
ef17055145 | ||
|
|
6a2fa10a4e | ||
|
|
6b81a5846d | ||
|
|
b54d086fde | ||
|
|
5ee9d22263 | ||
|
|
7dcb097a5d | ||
|
|
29a30239ab | ||
|
|
ed54b60ea3 | ||
|
|
199af33b30 | ||
|
|
adfa1d0e20 | ||
|
|
ef25c42e86 | ||
|
|
91a638156c | ||
|
|
26ce666938 | ||
|
|
7548af895b | ||
|
|
9548437a9e | ||
|
|
5e50b7104c | ||
|
|
d824cf7dbd | ||
|
|
0613cc62f4 | ||
|
|
d9cbcb5fa8 | ||
|
|
a4f5355161 | ||
|
|
a24b6c1909 | ||
|
|
fd7dc72410 | ||
|
|
e4f4dfab3b | ||
|
|
66010be5a6 | ||
|
|
852c42a8f3 | ||
|
|
132725de7b | ||
|
|
0a761c09e3 | ||
|
|
09ce6ae1c5 | ||
|
|
85e60ed858 | ||
|
|
86fd18324b | ||
|
|
fdf82e5d6c | ||
|
|
eb0b1580d1 | ||
|
|
2d33c545b8 | ||
|
|
cdaf523aa8 | ||
|
|
3195f2cec2 | ||
|
|
ea89a4afab | ||
|
|
3415b62d2d | ||
|
|
ee80822564 | ||
|
|
3c9e218d07 | ||
|
|
387a602885 | ||
|
|
ef0ff43975 | ||
|
|
ae37407369 | ||
|
|
e1c91b5763 | ||
|
|
c49b472f92 | ||
|
|
0a6b1b9418 | ||
|
|
ac40673a9e | ||
|
|
818f99b286 | ||
|
|
320da5e84c | ||
|
|
6957c379d5 | ||
|
|
88e880f107 | ||
|
|
bf8c4dfc83 | ||
|
|
5dff282132 | ||
|
|
1148ac0ae4 | ||
|
|
59c46fc594 | ||
|
|
03a94e3a6a | ||
|
|
5c8e05a4fc | ||
|
|
d791ce393b | ||
|
|
a452231086 | ||
|
|
a392a19c9c | ||
|
|
a864c04702 | ||
|
|
8d2f7296a1 | ||
|
|
040936eb47 | ||
|
|
101beec3ae | ||
|
|
2f1a836bf0 | ||
|
|
62f5e0a1a9 | ||
|
|
cca771e70e | ||
|
|
0c7e6b548f | ||
|
|
8b87e8aa92 | ||
|
|
415bbf2932 | ||
|
|
48df4f18cd | ||
|
|
dc0f9aca4a | ||
|
|
1b9b8e3f6c | ||
|
|
5d10e9dbee | ||
|
|
0adc858c85 | ||
|
|
eda1e8a402 | ||
|
|
4b0e34cdf4 | ||
|
|
c688687ff8 | ||
|
|
d56e5bea62 | ||
|
|
aed7b6b37a | ||
|
|
8114443e97 | ||
|
|
8ba0a33f84 | ||
|
|
661ed61779 | ||
|
|
427f95337f | ||
|
|
fa8490fb4e | ||
|
|
5be1c6381b | ||
|
|
6794a89f79 | ||
|
|
8f19ee7b97 | ||
|
|
c63135ec7f | ||
|
|
5c87f2f22c | ||
|
|
6e6e34c423 | ||
|
|
bb983fb4b2 | ||
|
|
285bbf50e9 | ||
|
|
c2ad2e1151 | ||
|
|
46e796ffaa | ||
|
|
3bf25d86f2 | ||
|
|
2dca4805b0 | ||
|
|
54aa4678d1 | ||
|
|
3ab0e6cade | ||
|
|
41e3b23253 | ||
|
|
b00d780a50 | ||
|
|
71b3e26232 | ||
|
|
40f28c02b9 | ||
|
|
362b22a673 | ||
|
|
d6be9a2bba | ||
|
|
6bfd113a87 | ||
|
|
b7f86ba743 | ||
|
|
2bab274056 | ||
|
|
dd6bffdd0d | ||
|
|
bcc044eb92 | ||
|
|
a7f1982d03 | ||
|
|
d013e0fc78 | ||
|
|
6f69ad93c1 | ||
|
|
7ea2093a91 | ||
|
|
dd32deb2ad | ||
|
|
ad71fb321c | ||
|
|
cc6c28a7ff | ||
|
|
c763087462 | ||
|
|
63ff4ddea0 | ||
|
|
4178fc125d | ||
|
|
dcfa7ad657 | ||
|
|
c061e60664 | ||
|
|
a0dd3ecd68 | ||
|
|
0168a312f2 | ||
|
|
92fe5a5b58 | ||
|
|
7f3d450b32 | ||
|
|
8166339920 | ||
|
|
57424d4a26 | ||
|
|
6511b6dd5d | ||
|
|
0625b97246 | ||
|
|
9f8ce82825 | ||
|
|
c3c925dc84 | ||
|
|
36f3703499 | ||
|
|
6ae59c3711 | ||
|
|
c8f5f85635 | ||
|
|
4e5e186784 | ||
|
|
828f7a513c | ||
|
|
6085998d57 | ||
|
|
71e44d5b65 | ||
|
|
e762bbdbf8 | ||
|
|
fe0d2272f6 | ||
|
|
e017b88adf | ||
|
|
5f76d9cf33 | ||
|
|
85a5bdf4dc | ||
|
|
4abc34ffd1 | ||
|
|
250b1d511b | ||
|
|
59e3b0285a | ||
|
|
f961f993c8 | ||
|
|
adf124c00c | ||
|
|
f8579131e8 | ||
|
|
1dde754724 | ||
|
|
771696fda8 | ||
|
|
dd5f469c83 | ||
|
|
6d3fda12cd | ||
|
|
dc32480563 | ||
|
|
06ac9e18cb | ||
|
|
0648943220 | ||
|
|
7a4a82e872 | ||
|
|
6c0c05cf7f | ||
|
|
efd2db129f | ||
|
|
f4f276f370 | ||
|
|
bff1462e9e | ||
|
|
4d06f33089 | ||
|
|
a433d9ef03 | ||
|
|
58606e1702 | ||
|
|
1ccc9aa72e | ||
|
|
49a9bb5a8b | ||
|
|
380d6ac5c2 | ||
|
|
7d9f76df05 | ||
|
|
96707acb4e | ||
|
|
4e504823c0 | ||
|
|
82faa2e9c9 | ||
|
|
1df9cd8071 | ||
|
|
a8d5e4dd28 | ||
|
|
e59ea39a33 | ||
|
|
62d1dc1eea | ||
|
|
379af7dec2 | ||
|
|
68a45adac7 | ||
|
|
9ea8e29cb0 | ||
|
|
90092c0762 | ||
|
|
b379816178 | ||
|
|
e4353255ca | ||
|
|
923f2c7635 | ||
|
|
a8309ef705 | ||
|
|
bad05485d0 | ||
|
|
38d7799ffa | ||
|
|
6e6696ccd4 | ||
|
|
feb546920e | ||
|
|
81b05b9de4 | ||
|
|
ab10b042be | ||
|
|
26699914cc | ||
|
|
45e4b3c423 | ||
|
|
6a5a139e33 | ||
|
|
1908d3200e | ||
|
|
f4cf40d38f | ||
|
|
514de84b97 | ||
|
|
7e7d0bb354 | ||
|
|
e468b90442 | ||
|
|
926959ab47 | ||
|
|
4663090a8f | ||
|
|
b0868a4d0b | ||
|
|
9088b00006 | ||
|
|
9c0fe8999d | ||
|
|
901aa5f7c1 | ||
|
|
3ee28c035b | ||
|
|
1e31b90905 | ||
|
|
48333041f4 | ||
|
|
717c9dbe89 | ||
|
|
fd86eb7aa7 | ||
|
|
9b4b35eff5 | ||
|
|
ac528caf2b | ||
|
|
fbe626e791 | ||
|
|
9ca37d30d8 | ||
|
|
84986898c8 | ||
|
|
5cebce3f4b | ||
|
|
bb344b14a8 | ||
|
|
20e613b444 | ||
|
|
a0952e0012 | ||
|
|
49e66f809e | ||
|
|
5152ed8731 | ||
|
|
33811a826f | ||
|
|
d33aebfd31 | ||
|
|
7d53c52a6b | ||
|
|
f015a8686e | ||
|
|
ab791d2a2d | ||
|
|
a303858da7 | ||
|
|
4c58c62cfe | ||
|
|
4593332204 | ||
|
|
9f5d8c4280 | ||
|
|
b0d44bf0ba | ||
|
|
59b8434e36 | ||
|
|
e6f27cbaf3 | ||
|
|
6c13df1aff | ||
|
|
44bf059b2f | ||
|
|
9ade464c2e | ||
|
|
aed5d4e05b | ||
|
|
b57648df14 | ||
|
|
7bce887077 | ||
|
|
cacd9c7f95 | ||
|
|
cd64bfe84b | ||
|
|
52ed68ed24 | ||
|
|
20577021a6 | ||
|
|
838a2236a1 | ||
|
|
d03941b792 | ||
|
|
92299c3079 | ||
|
|
d9f05532cd | ||
|
|
2fd2dff126 | ||
|
|
8e14ad0536 | ||
|
|
2b325102f3 | ||
|
|
1f2be606fa | ||
|
|
6b29a2a724 | ||
|
|
f79edeb053 | ||
|
|
84b92096d4 | ||
|
|
70f4814cb1 | ||
|
|
49579eb2b4 | ||
|
|
cc6caeeca9 | ||
|
|
90af22eba1 | ||
|
|
f4b4b41264 | ||
|
|
9918b03c11 | ||
|
|
95f44246bf | ||
|
|
b098723f78 | ||
|
|
a819513a92 | ||
|
|
7531b28b4c | ||
|
|
2b8586d1b7 | ||
|
|
8167291ffc | ||
|
|
0dfcf9607a | ||
|
|
4827831107 | ||
|
|
0ebb6d5d30 | ||
|
|
f4ed5062f6 | ||
|
|
434b129746 | ||
|
|
2f5041ac7d | ||
|
|
24f9766b39 | ||
|
|
ba872217d7 | ||
|
|
b2ae517dac | ||
|
|
32b52dc0c8 | ||
|
|
33a3fe9bbd | ||
|
|
245dc76503 | ||
|
|
21dbfd79d8 | ||
|
|
b9f2250278 | ||
|
|
a0601f1891 | ||
|
|
70403ee433 | ||
|
|
f3cde58c8f | ||
|
|
71c267776a | ||
|
|
359ff94a8c | ||
|
|
efe1c1492f | ||
|
|
2aaaf7c358 | ||
|
|
cefaffa0f0 | ||
|
|
a22d56dc41 | ||
|
|
51eca94504 | ||
|
|
2b6d24d328 | ||
|
|
4932025423 | ||
|
|
c466abf4d0 | ||
|
|
2ece3a8b4c | ||
|
|
3f760e1875 | ||
|
|
1da134c38c | ||
|
|
0bf96e9864 | ||
|
|
1f5c19306e | ||
|
|
db10b3821c | ||
|
|
4245a6d04d | ||
|
|
6920c1159b | ||
|
|
3801e1eade | ||
|
|
3e419303a7 | ||
|
|
0de1e6a3af | ||
|
|
99c415f898 | ||
|
|
f68d83dbf0 | ||
|
|
6e97905bce | ||
|
|
572a10d5a0 | ||
|
|
eaa6199de0 | ||
|
|
70799101e4 | ||
|
|
9cc70d0323 | ||
|
|
20c5da6e55 | ||
|
|
4c356bc368 | ||
|
|
aeb04deae4 | ||
|
|
873e4d6547 | ||
|
|
9ba20304c2 | ||
|
|
252619b1a0 | ||
|
|
38b129de66 | ||
|
|
da028d1af9 | ||
|
|
bba361016d | ||
|
|
c362af1f81 | ||
|
|
520507afd9 | ||
|
|
4e7584167b | ||
|
|
112bd61a25 | ||
|
|
1df8bc0dfe | ||
|
|
f2076fe309 | ||
|
|
67dea15bf2 | ||
|
|
910f19fe55 | ||
|
|
290bf0b6d2 | ||
|
|
4c87a776e6 | ||
|
|
4436093816 | ||
|
|
b85aa7b084 | ||
|
|
99e28b639d | ||
|
|
9b94b4da26 | ||
|
|
5b46986628 | ||
|
|
d0e5690bfd | ||
|
|
ddbfa06bcc | ||
|
|
2c6fc99c68 | ||
|
|
d8ad0ac72c | ||
|
|
9de50d7981 | ||
|
|
2c5c46dc48 | ||
|
|
6423b4cbb9 | ||
|
|
2566aa725a | ||
|
|
eb463bbb2b | ||
|
|
1a8a559d84 | ||
|
|
57c1d787e3 | ||
|
|
999a32424f | ||
|
|
c2ed20ba23 | ||
|
|
01cbb37359 | ||
|
|
3e205e9536 | ||
|
|
b29d6b4478 | ||
|
|
b9424e4c21 | ||
|
|
87fe912d8d | ||
|
|
59343c2f82 | ||
|
|
700fc64383 | ||
|
|
ca256b9949 | ||
|
|
68750f3455 | ||
|
|
906fc417c8 | ||
|
|
ac203c56df | ||
|
|
734ad45f1c | ||
|
|
4a1f2e0dd3 | ||
|
|
24e3514640 | ||
|
|
dadb05e022 | ||
|
|
ca3dfb3c07 | ||
|
|
cf452942fa | ||
|
|
28ee40bebe | ||
|
|
6267752a2a | ||
|
|
2ece24e077 | ||
|
|
59013e62d3 | ||
|
|
824763aae9 | ||
|
|
a8c5b04feb | ||
|
|
64f069ec24 | ||
|
|
515e438d4f | ||
|
|
9ec064f9d9 | ||
|
|
60c6b04a01 | ||
|
|
9deaa81a72 | ||
|
|
ae703db6ee | ||
|
|
267f54bc0e | ||
|
|
8aa26fb2cd | ||
|
|
e7667f2537 | ||
|
|
bac15d2ecf | ||
|
|
ae27e07903 | ||
|
|
605dfa7366 | ||
|
|
85db19e33f | ||
|
|
052bc6b356 | ||
|
|
24985e2bca | ||
|
|
8e3eb8b3d2 | ||
|
|
2be44dbd94 | ||
|
|
7c6b26faa2 | ||
|
|
cfc42512ed | ||
|
|
50f5834296 | ||
|
|
07e91bb73a | ||
|
|
3c547eeed8 | ||
|
|
6f011fce3b | ||
|
|
5aebed95a4 | ||
|
|
8321f9f6e9 | ||
|
|
bf9d69ab56 | ||
|
|
faaff57d2b | ||
|
|
40667ef1c1 | ||
|
|
04b4e3298b | ||
|
|
43cbd3a61e | ||
|
|
bfb091f2f4 | ||
|
|
4974303e6b | ||
|
|
664bb0a663 | ||
|
|
491596d03d | ||
|
|
75538be235 | ||
|
|
1cb99ea2fc | ||
|
|
c0f4bde5fc | ||
|
|
a4430dd49d | ||
|
|
b513d40bd6 | ||
|
|
fbaaf89a21 | ||
|
|
7625a0154e | ||
|
|
396ee803b2 | ||
|
|
5a42319a07 | ||
|
|
61b9820f78 | ||
|
|
a383a45269 | ||
|
|
7bd4869ae6 | ||
|
|
49a6559453 | ||
|
|
2e16a10720 | ||
|
|
cd973b50ff | ||
|
|
b6fc67fff2 | ||
|
|
12f00d785d | ||
|
|
de1ff6ed49 | ||
|
|
d0a6cbe5dd | ||
|
|
35924ce550 | ||
|
|
ad1d8cbedd | ||
|
|
6294ce59f7 | ||
|
|
d445ff40c2 | ||
|
|
c6010c3ab4 | ||
|
|
9da80d7b7d | ||
|
|
2c62e58dbd | ||
|
|
efc54375dd | ||
|
|
0c3946033b | ||
|
|
9dc86aa77d | ||
|
|
0cbe320a5f | ||
|
|
1c749a5310 | ||
|
|
a647a69791 | ||
|
|
12db089c73 | ||
|
|
f5ff7cfcf1 | ||
|
|
2ddf71ec46 | ||
|
|
9017374292 | ||
|
|
633f50cf5b | ||
|
|
1993e9c65b | ||
|
|
8edc8610dc | ||
|
|
6700b373cd | ||
|
|
8d824799a0 | ||
|
|
dc86c62d8b | ||
|
|
4ae4ff72e3 | ||
|
|
958eebb16c | ||
|
|
43e48d2ba6 | ||
|
|
b6d8099c74 | ||
|
|
25bac7c5ce | ||
|
|
5d7a080e39 | ||
|
|
b2a76dba98 | ||
|
|
15ad69c8cb | ||
|
|
e3ca006265 | ||
|
|
961cc13948 | ||
|
|
50da233258 | ||
|
|
15ad58b5cc | ||
|
|
61a27ff430 | ||
|
|
befdb0a708 | ||
|
|
06b79600ac | ||
|
|
b9e633ad06 | ||
|
|
736a78faed | ||
|
|
d76e69f9a7 | ||
|
|
1612e1d142 | ||
|
|
56a33fd4c5 | ||
|
|
1ca3244868 | ||
|
|
8f358f09b8 | ||
|
|
d903de6526 | ||
|
|
c41ade2983 | ||
|
|
99dbbc7f39 | ||
|
|
4dd51cc889 | ||
|
|
54c651f7e2 | ||
|
|
d1c9d7ffdc | ||
|
|
052b40680d | ||
|
|
b0d2519192 | ||
|
|
997da11cc5 | ||
|
|
476232ea22 | ||
|
|
4c83f4e2de | ||
|
|
4bf39e18d9 | ||
|
|
edfa533a4d | ||
|
|
28262145ab | ||
|
|
51136ce982 | ||
|
|
84893ec582 | ||
|
|
4236405b90 | ||
|
|
292c66e25c | ||
|
|
5aa6c15c76 | ||
|
|
1f89dc47cb | ||
|
|
31393128c8 | ||
|
|
232a18425a | ||
|
|
88e2eb2a49 | ||
|
|
e635d5f748 | ||
|
|
08a23cdb2f | ||
|
|
1ead940623 | ||
|
|
382362668e | ||
|
|
987f8bc949 | ||
|
|
6f096333d3 | ||
|
|
5a25111b20 | ||
|
|
c7cb16cafa | ||
|
|
a746a698b6 | ||
|
|
9a7f7255ff | ||
|
|
d3df6b8f4f | ||
|
|
fcffd17b11 | ||
|
|
7fc6be9f39 | ||
|
|
7362744ff8 | ||
|
|
f4d058155a | ||
|
|
b04612e80d | ||
|
|
5f00e4d34d | ||
|
|
e967feb091 | ||
|
|
0445b18bb9 | ||
|
|
99f1f749cf | ||
|
|
f4d16f1c47 | ||
|
|
68071d6caf | ||
|
|
44975da7db | ||
|
|
e4566518b2 | ||
|
|
c038cb5b96 | ||
|
|
d7eb3db60b | ||
|
|
44e781d7da | ||
|
|
0951d58c8f | ||
|
|
37c0ed0b49 | ||
|
|
556bf7b888 | ||
|
|
280be2eaea | ||
|
|
13f9357f8e | ||
|
|
56e015db0e | ||
|
|
1068fbf079 | ||
|
|
45f7afb3e1 | ||
|
|
0d3fc2b656 | ||
|
|
2dc66b2e3b | ||
|
|
0b9129d8f5 | ||
|
|
82d702fedc | ||
|
|
197be75677 | ||
|
|
3f9aff1b10 | ||
|
|
f5ed50fa88 | ||
|
|
645b52602f | ||
|
|
27a8e60e9a | ||
|
|
201ffa108b | ||
|
|
1661bd6691 | ||
|
|
d431f4bbc5 | ||
|
|
2b8e92a70d | ||
|
|
d70ab3cfa8 | ||
|
|
9402c6ad28 | ||
|
|
da5e8e9778 | ||
|
|
feedfdf810 | ||
|
|
6db0a502bf | ||
|
|
f07957d45e | ||
|
|
3d75d71767 | ||
|
|
b259bdeddd | ||
|
|
042465387f | ||
|
|
d09e4d648c | ||
|
|
754910ad5f | ||
|
|
977e080215 | ||
|
|
a9ac947c96 | ||
|
|
28e6ef1d63 | ||
|
|
b0f273157d | ||
|
|
49add531c4 | ||
|
|
8a1d2a5dca | ||
|
|
31c5883f5f | ||
|
|
c625fbb43d | ||
|
|
0f474e8d2a | ||
|
|
73813a8383 | ||
|
|
d8fb110b56 | ||
|
|
77e62626a9 | ||
|
|
24ee83f13d | ||
|
|
6791a36d85 | ||
|
|
c6a5a64e64 | ||
|
|
311062dc41 | ||
|
|
391ce1f009 | ||
|
|
9f6d99352a | ||
|
|
02b1d6260a | ||
|
|
e8ade14259 | ||
|
|
f0804dfed4 | ||
|
|
f506344ada | ||
|
|
ddca518cca | ||
|
|
21d3678fa7 | ||
|
|
3dd8d7d8e5 | ||
|
|
92aa538a84 | ||
|
|
557a5583e8 | ||
|
|
b00ddff7dd | ||
|
|
cc3b311ab0 | ||
|
|
6cedca5d76 | ||
|
|
d82452e00f | ||
|
|
57a5c0ba38 | ||
|
|
28c8519e5b | ||
|
|
cfcb7191ea | ||
|
|
6921227ec8 | ||
|
|
1c9991ee83 | ||
|
|
fd475fcfff | ||
|
|
f47f995e90 | ||
|
|
d93e943326 | ||
|
|
7ca9f2d5cd | ||
|
|
ff1d45a008 | ||
|
|
53f0a72362 | ||
|
|
3a47242219 | ||
|
|
5556568feb | ||
|
|
6011a15cd4 | ||
|
|
2c014778d9 | ||
|
|
0b2712f52f | ||
|
|
69f1acd823 | ||
|
|
c0f15d50d6 | ||
|
|
1d3fe51e8b | ||
|
|
d364d50c05 | ||
|
|
615d324b11 | ||
|
|
eb36b6755f | ||
|
|
40c28d3b21 | ||
|
|
e726282023 | ||
|
|
327f734e4f | ||
|
|
b361f64d4f | ||
|
|
b38d215b3d | ||
|
|
99aa498bc4 | ||
|
|
f14798dec9 | ||
|
|
65873f3dee | ||
|
|
fc98c88358 | ||
|
|
7c0440c148 | ||
|
|
ad051269ed | ||
|
|
497d8f25a1 | ||
|
|
eb142f26f2 | ||
|
|
b01989f041 | ||
|
|
84d89e80cd | ||
|
|
d059d2cda4 | ||
|
|
751413f050 | ||
|
|
ce5e28554f | ||
|
|
860be3f96c | ||
|
|
89fb3a3d6e | ||
|
|
474a07564c | ||
|
|
59b69a3b3b | ||
|
|
2553392e42 | ||
|
|
fcd6901558 | ||
|
|
716ffbb945 | ||
|
|
cd4b9aeafe | ||
|
|
5d712b6f54 | ||
|
|
754c68fccc | ||
|
|
858f4da0d1 | ||
|
|
90910a7a4f | ||
|
|
cd218b59f9 | ||
|
|
9625c49c95 | ||
|
|
2dfed10d2e | ||
|
|
a74d3737dc | ||
|
|
6c82a34aa0 | ||
|
|
320d5656ac | ||
|
|
a4a5778001 | ||
|
|
a80a003865 | ||
|
|
4607e46c6f | ||
|
|
0aa3e2e49c | ||
|
|
595bb36956 | ||
|
|
afdf7e6df3 | ||
|
|
3e1c7d7ef2 | ||
|
|
7ce7c3deb7 | ||
|
|
c9b390ec60 | ||
|
|
cc2b826356 | ||
|
|
0b2c493731 | ||
|
|
0d7bbc51e7 | ||
|
|
db81c30d24 | ||
|
|
41ea8de0d6 | ||
|
|
c4b5b37568 | ||
|
|
76e6b23a4f | ||
|
|
283e295a98 | ||
|
|
606009afb0 | ||
|
|
da303b8b4f | ||
|
|
d4048661ae | ||
|
|
47853547ca | ||
|
|
6ae9188af4 | ||
|
|
d958ec2ac8 | ||
|
|
07aac8e6e9 | ||
|
|
9a341c9032 | ||
|
|
21e8b08ed9 | ||
|
|
c41d477adc | ||
|
|
f8445a4c85 | ||
|
|
71f5be011b | ||
|
|
a39b7ddbac | ||
|
|
cab5c822c5 | ||
|
|
4056bd3c2d | ||
|
|
a985ae9c0a | ||
|
|
804a3bf380 | ||
|
|
a8bef96463 | ||
|
|
5e43a3f695 | ||
|
|
8e46e05e1b | ||
|
|
ec0e27dbb4 | ||
|
|
3f55d93b41 | ||
|
|
5418a8c28a | ||
|
|
e180192379 | ||
|
|
f498d69b7d | ||
|
|
dfae1b3f70 | ||
|
|
a9ebb55f95 | ||
|
|
abfac8aa40 | ||
|
|
78956ccf83 | ||
|
|
eed25f23f6 | ||
|
|
134ce56f80 | ||
|
|
28a4778187 | ||
|
|
c654c2e5e8 | ||
|
|
e580d4e637 | ||
|
|
2192914cbb | ||
|
|
ca6dee1777 | ||
|
|
6f3bdc5dca | ||
|
|
095cdcd69e | ||
|
|
f022633f29 | ||
|
|
1f85fcc9b0 | ||
|
|
a3ede75842 | ||
|
|
0defce37f0 | ||
|
|
4355b39b1e | ||
|
|
efec738c89 | ||
|
|
10c09a361b | ||
|
|
e3d1a69223 | ||
|
|
4b82253ae9 | ||
|
|
47a12c30ca | ||
|
|
613655767b | ||
|
|
1182027f1c | ||
|
|
e9421d557a | ||
|
|
bbc0c0df94 | ||
|
|
610e32714c | ||
|
|
7ab81d3805 | ||
|
|
9a1e41e1fa | ||
|
|
ae71d12f06 | ||
|
|
c25234df83 | ||
|
|
03284ba046 | ||
|
|
5fa433ecca | ||
|
|
ac2a4c700a | ||
|
|
eeb7b00f60 | ||
|
|
c8c540b453 | ||
|
|
a0585f75f7 | ||
|
|
637af1d392 | ||
|
|
fe6c31acc1 | ||
|
|
04cfcf751e | ||
|
|
51c51d49ad | ||
|
|
4271aa5b1f | ||
|
|
17ada1c894 | ||
|
|
2e14d125ba | ||
|
|
ce8fa4c24b | ||
|
|
cfe2e83e6b | ||
|
|
b17c62618d | ||
|
|
6b162a1193 | ||
|
|
6653530b63 | ||
|
|
aacae6444e | ||
|
|
b91fe12258 | ||
|
|
ae7ca00e69 | ||
|
|
0103f1f080 | ||
|
|
e8d29d54d6 | ||
|
|
092f2ce0b3 | ||
|
|
d89233276b | ||
|
|
7d797187e8 | ||
|
|
6edcc72364 | ||
|
|
250dfc1377 | ||
|
|
45489c1c87 | ||
|
|
09b250f189 | ||
|
|
a84465ddba | ||
|
|
3b95671442 | ||
|
|
52e66077a7 | ||
|
|
84bf4d21a3 | ||
|
|
04cfc510d0 | ||
|
|
d846e67ec1 | ||
|
|
9c60a1bc10 | ||
|
|
f06ac52a43 | ||
|
|
9e5fd43a2d | ||
|
|
8d50e7dc82 | ||
|
|
1e6b7bd2a6 | ||
|
|
8346be7a81 | ||
|
|
9dc5683fc2 | ||
|
|
e7cb82175a | ||
|
|
1ef0aa14c0 | ||
|
|
0b3f6d6aab | ||
|
|
0beef1d770 | ||
|
|
b944db30fd | ||
|
|
6cf3a3feaf | ||
|
|
9680b8ccb3 | ||
|
|
a88a11c243 | ||
|
|
7ff76f69a1 | ||
|
|
c2e4e6d221 | ||
|
|
60edc456a9 | ||
|
|
625f804130 | ||
|
|
7100aaedec | ||
|
|
c867dbc7b2 | ||
|
|
88097f1829 | ||
|
|
7cf4834336 | ||
|
|
b5355307a3 | ||
|
|
76f693e5d7 | ||
|
|
fb3b0ca6e3 | ||
|
|
3c71977e2e | ||
|
|
5574a2663a | ||
|
|
41960b4212 | ||
|
|
6a500b8d40 | ||
|
|
dcede59379 | ||
|
|
695153c527 | ||
|
|
c409cca20e | ||
|
|
a5a9204f83 | ||
|
|
25d42ad345 | ||
|
|
f70a407611 | ||
|
|
89f2e66c80 | ||
|
|
4562be52d4 | ||
|
|
ebd931f7af | ||
|
|
6a47ff6422 | ||
|
|
1237185bb4 | ||
|
|
d7fe819699 | ||
|
|
770ffd1483 | ||
|
|
9373e77636 | ||
|
|
cb5034548d | ||
|
|
f9ad870ff0 | ||
|
|
b538bc3871 | ||
|
|
e5b0528aca | ||
|
|
a12bd2271e | ||
|
|
15c5858732 | ||
|
|
dd4227f444 | ||
|
|
fe8a7d8db9 | ||
|
|
ec79ca71b2 | ||
|
|
7a1544e76a | ||
|
|
27ffc23664 | ||
|
|
8ef8ee91e9 | ||
|
|
571625f0c3 | ||
|
|
fc2d6eb6bb | ||
|
|
48800504be | ||
|
|
f94a019733 | ||
|
|
535d8b9e02 | ||
|
|
161d44ee04 | ||
|
|
7ea155b943 | ||
|
|
30acef2452 | ||
|
|
82b50fd3a5 | ||
|
|
9e5503dd04 | ||
|
|
2ec2ed62c8 | ||
|
|
274c11c3ec | ||
|
|
76c4bb556f | ||
|
|
40f484cc54 | ||
|
|
85b701b8c2 | ||
|
|
7e875ba89d | ||
|
|
c718d7999f | ||
|
|
d1472992da | ||
|
|
995f90aa49 | ||
|
|
a4c27618b4 | ||
|
|
05019529f1 | ||
|
|
1b5ab3261c | ||
|
|
6033555ac0 | ||
|
|
fd4e1975a3 | ||
|
|
124ac12150 | ||
|
|
8c1ffa3f5d | ||
|
|
f76a7e36e8 | ||
|
|
6484c4bc8b | ||
|
|
bba2421ba9 | ||
|
|
3c69c7feaf | ||
|
|
45b2ffe1af | ||
|
|
a57c0f4700 | ||
|
|
c33116166f | ||
|
|
50a2063e45 | ||
|
|
cd30cf2d6c | ||
|
|
419126652e | ||
|
|
06ab83dca6 | ||
|
|
313fddf722 | ||
|
|
f4def36ccb | ||
|
|
4be8f2ba93 | ||
|
|
881b282604 | ||
|
|
9675bfe07d | ||
|
|
443351e95a | ||
|
|
d4cd1c61ee | ||
|
|
75892cb523 | ||
|
|
63e0041644 | ||
|
|
70e2d8dd4e | ||
|
|
b2624f6055 | ||
|
|
0bb8144677 | ||
|
|
ad50447ec6 | ||
|
|
84de7437c6 | ||
|
|
419dd50255 | ||
|
|
9dea02e578 | ||
|
|
1c181e091e | ||
|
|
32782bab0e | ||
|
|
330783cb5a | ||
|
|
504b004e01 | ||
|
|
edb861da70 | ||
|
|
64ad15895f | ||
|
|
44b4944334 | ||
|
|
f9272d0959 | ||
|
|
a113e344a1 | ||
|
|
2d80f03f01 | ||
|
|
542fe9f029 | ||
|
|
a1992f5910 | ||
|
|
45a057b0c6 | ||
|
|
4a1a26e8b7 | ||
|
|
db35e6a427 | ||
|
|
7358ed25a5 | ||
|
|
0d385c29a3 | ||
|
|
51076e68c8 | ||
|
|
3270f1252b | ||
|
|
d8ee105e1e | ||
|
|
567fccd7ee | ||
|
|
f7f7319698 | ||
|
|
62a6b61fc9 | ||
|
|
1a87d9fa77 | ||
|
|
8131e30002 | ||
|
|
83c76bdafc | ||
|
|
cf1566e116 | ||
|
|
5d2c977029 | ||
|
|
823c0ef5fb | ||
|
|
aefc588e6e | ||
|
|
1949439d69 | ||
|
|
c131b8daf1 | ||
|
|
8a61969c8f | ||
|
|
3cf85770c7 | ||
|
|
310b339f0d | ||
|
|
229b7810df | ||
|
|
a686beb9a7 | ||
|
|
42c1bee8ea | ||
|
|
c289556775 | ||
|
|
941d2f2a3e |
No files matched your search
@@ -10,3 +10,4 @@
|
|||||||
- Compiler/IDE and SDK: ZZZ version _X.Y_
|
- Compiler/IDE and SDK: ZZZ version _X.Y_
|
||||||
- Target hardware/board: _?_
|
- Target hardware/board: _?_
|
||||||
- Connectivity chip/module: _?_
|
- Connectivity chip/module: _?_
|
||||||
|
- Target RTOS/OS (if applicable): _?_
|
||||||
@@ -1,17 +1,27 @@
|
|||||||
name: CIFuzz
|
name: CIFuzz
|
||||||
on: [pull_request]
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 2 * * *' # run at 2 AM UTC
|
||||||
|
# Allow manual runs
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Fuzzing:
|
Fuzzing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^src/' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- name: Build Fuzzers
|
- name: Build Fuzzers
|
||||||
id: build
|
id: build
|
||||||
|
if: ${{ env.GO == 1 }}
|
||||||
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
|
||||||
with:
|
with:
|
||||||
oss-fuzz-project-name: 'mongoose'
|
oss-fuzz-project-name: 'mongoose'
|
||||||
dry-run: false
|
dry-run: false
|
||||||
language: c++
|
language: c++
|
||||||
- name: Run Fuzzers
|
- name: Run Fuzzers
|
||||||
|
if: ${{ env.GO == 1 }}
|
||||||
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
|
||||||
with:
|
with:
|
||||||
oss-fuzz-project-name: 'mongoose'
|
oss-fuzz-project-name: 'mongoose'
|
||||||
@@ -20,7 +30,7 @@ jobs:
|
|||||||
language: c++
|
language: c++
|
||||||
- name: Upload Crash
|
- name: Upload Crash
|
||||||
uses: actions/upload-artifact@v1
|
uses: actions/upload-artifact@v1
|
||||||
if: failure() && steps.build.outcome == 'success'
|
if: env.GO == 1 && failure() && steps.build.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
path: ./out/artifacts
|
path: ./out/artifacts
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
name: "CodeQL Scanning"
|
||||||
|
# https://github.com/github/codeql-action
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 2 * * *' # run at 2:30 AM UTC
|
||||||
|
# Allow manual runs
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
IPV6: 0
|
||||||
|
jobs:
|
||||||
|
CodeQL-Build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
permissions:
|
||||||
|
security-events: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: cpp
|
||||||
|
- run: |
|
||||||
|
make -C test test CC=gcc ASAN= ASAN_OPTIONS=
|
||||||
|
./test/setup_ga_network.sh && make -C test mip_test CC=gcc ASAN= ASAN_OPTIONS=
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
@@ -0,0 +1,641 @@
|
|||||||
|
name: Full build and test
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 1 * * *' # run at 1 AM UTC
|
||||||
|
# Allow manual runs
|
||||||
|
workflow_dispatch:
|
||||||
|
env:
|
||||||
|
IPV6: 0
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
cc: [gcc, clang, g++, clang++]
|
||||||
|
target: [test]
|
||||||
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||||
|
select: ["-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0", "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0", "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=1"]
|
||||||
|
exclude:
|
||||||
|
- ssl: MBEDTLS
|
||||||
|
select: "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: MBEDTLS
|
||||||
|
select: "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: OPENSSL
|
||||||
|
select: "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: OPENSSL
|
||||||
|
select: "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: WOLFSSL
|
||||||
|
select: "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: WOLFSSL
|
||||||
|
select: "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0"
|
||||||
|
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||||
|
env:
|
||||||
|
CC: ${{ matrix.cc }}
|
||||||
|
SSL: ${{ matrix.ssl }}
|
||||||
|
TFLAGS: ${{ matrix.select }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }}
|
||||||
|
mip:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
cc: [gcc, clang, g++, clang++]
|
||||||
|
target: [mip_test, mip_tap_test]
|
||||||
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||||
|
name: ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
||||||
|
env:
|
||||||
|
CC: ${{ matrix.cc }}
|
||||||
|
SSL: ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if [ "${{ matrix.target }}" == "mip_tap_test" ]; then ./test/setup_ga_network.sh ; fi && sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }} IPV6=0
|
||||||
|
s390:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN]
|
||||||
|
name: S390 SSL=${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update ; sudo apt -y install qemu binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390 SSL=${{ matrix.ssl }}
|
||||||
|
armhf:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN]
|
||||||
|
name: ArmHF SSL=${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update ; sudo apt -y install qemu binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf SSL=${{ matrix.ssl }}
|
||||||
|
unamalgamated-mg_prefix:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||||
|
name: unamalgamated-mg_prefix SSL=${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev
|
||||||
|
- run: make -C test unamalgamated && make -C test mg_prefix
|
||||||
|
valgrind:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||||
|
name: Valgrind SSL=${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev valgrind
|
||||||
|
- run: make -C test valgrind SSL=${{ matrix.ssl }}
|
||||||
|
macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||||
|
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
|
||||||
|
exclude:
|
||||||
|
- ssl: MBEDTLS
|
||||||
|
select: -DMG_ENABLE_POLL=0
|
||||||
|
- ssl: OPENSSL
|
||||||
|
select: -DMG_ENABLE_POLL=0
|
||||||
|
- ssl: WOLFSSL
|
||||||
|
select: -DMG_ENABLE_POLL=0
|
||||||
|
name: macos SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||||
|
env:
|
||||||
|
SSL: ${{ matrix.ssl }}
|
||||||
|
TFLAGS: ${{ matrix.select }} -DNO_SNTP_CHECK -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
|
||||||
|
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: brew install mbedtls wolfssl # jq openssl already pre-installed
|
||||||
|
- run: make -C test test ASAN_OPTIONS= MBEDTLS=$(echo $(brew --cellar)/mbedtls*/*) OPENSSL=$(echo $(brew --cellar)/openssl*/*) WOLFSSL=$(echo $(brew --cellar)/wolfssl*/*)
|
||||||
|
windows:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
max-parallel: 1 # no parallel runs, to minimize MQTT errors
|
||||||
|
matrix:
|
||||||
|
target: [vc98, vc17, vc22, mingw, mingw++]
|
||||||
|
ssl: ["", BUILTIN]
|
||||||
|
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
|
||||||
|
exclude:
|
||||||
|
- target: vc98
|
||||||
|
select: -DMG_ENABLE_POLL=1
|
||||||
|
name: windows ${{ matrix.target }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||||
|
env:
|
||||||
|
SSL: SSL=${{ matrix.ssl }}
|
||||||
|
TFLAGS: ${{ matrix.select }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: make -C test ${{ matrix.target }}
|
||||||
|
arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN]
|
||||||
|
name: Arm SSL=${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test arm SSL=${{ matrix.ssl }}
|
||||||
|
riscv:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN]
|
||||||
|
name: RISC-V SSL=${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test riscv SSL=${{ matrix.ssl }}
|
||||||
|
|
||||||
|
examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: examples ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: sudo apt -y install libpcap-dev
|
||||||
|
- run: make -C test examples CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
- run: make -C test clean_examples
|
||||||
|
examples_win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: examples_win ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# - uses: egor-tensin/setup-mingw@v2
|
||||||
|
# with:
|
||||||
|
# platform: x64
|
||||||
|
- name: test they build
|
||||||
|
run: make -C test examples_win CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
shell: cmd
|
||||||
|
- name: test they clean
|
||||||
|
run: make -C test clean_examples_win
|
||||||
|
shell: cmd
|
||||||
|
examples_mac:
|
||||||
|
runs-on: macos-latest
|
||||||
|
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: examples_mac ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test examples_mac CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
- run: make -C test clean_examples_mac
|
||||||
|
|
||||||
|
refprojs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: reference-projects ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test refprojs CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
- run: make -C test clean_refprojs
|
||||||
|
refprojs_win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: reference-projects_win ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# - uses: egor-tensin/setup-mingw@v2
|
||||||
|
# with:
|
||||||
|
# platform: x64
|
||||||
|
- name: test they build
|
||||||
|
run: make -C test refprojs_win CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
shell: cmd
|
||||||
|
- name: test they clean
|
||||||
|
run: make -C test clean_refprojs_win
|
||||||
|
shell: cmd
|
||||||
|
refprojs_mac:
|
||||||
|
runs-on: macos-latest
|
||||||
|
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: reference-projects_mac ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test refprojs CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
- run: make -C test clean_refprojs
|
||||||
|
|
||||||
|
tutorials:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: tutorials ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: sudo apt -y install libpcap-dev
|
||||||
|
- run: make -C test tutorials CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
- run: make -C test clean_tutorials
|
||||||
|
tutorials_win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: tutorials_win ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# - uses: egor-tensin/setup-mingw@v2
|
||||||
|
# with:
|
||||||
|
# platform: x64
|
||||||
|
- name: test they build
|
||||||
|
run: make -C test tutorials_win CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
shell: cmd
|
||||||
|
- name: test they clean
|
||||||
|
run: make -C test clean_tutorials_win
|
||||||
|
shell: cmd
|
||||||
|
tutorials_mac:
|
||||||
|
runs-on: macos-latest
|
||||||
|
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
name: tutorials_mac ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test tutorials_mac CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
- run: make -C test clean_tutorials_mac
|
||||||
|
|
||||||
|
|
||||||
|
arduino:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: echo # nothing specific to install or do
|
||||||
|
- run: make -C examples/arduino arduino-xiao
|
||||||
|
# - run: make -C examples/arduino arduino-nano
|
||||||
|
- run: make -C examples/arduino clean
|
||||||
|
|
||||||
|
|
||||||
|
generic_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: esp32/uart-bridge
|
||||||
|
- path: esp32/micropython
|
||||||
|
- path: esp8266/http-client-server
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- run: echo # nothing specific to install or do
|
||||||
|
- run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
generic_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: microchip/same54-xpro/mqtt-client
|
||||||
|
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
||||||
|
- path: nxp/nxp-mimxrt1020-azurertos
|
||||||
|
- path: nxp/nxp-frdmk66f-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54s018m-freertos
|
||||||
|
- path: nxp/nxp-mimxrt1020-freertos
|
||||||
|
- path: nxp/nxp-evkbimxrt1050-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1020-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1024-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1060-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1064-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1160-cm7-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1170-cm7-lwip-freertos
|
||||||
|
- path: nxp/nxp-frdmk64f-lwip-freertos
|
||||||
|
- path: nxp/nxp-frdmk66f-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54018-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54608-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54618-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54628-lwip-freertos
|
||||||
|
- path: nxp/nxp-twrk65f180m-lwip-freertos
|
||||||
|
- path: nxp/nxp-twrkv58f220m-lwip-freertos
|
||||||
|
- path: rp2040/pico-rmii
|
||||||
|
- path: stm32/nucleo-f429zi-make-baremetal-builtin-rndis
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin-rndis
|
||||||
|
- path: stm32/nucleo-g031-make-baremetal-builtin
|
||||||
|
- path: ti/ti-ek-tm4c1294xl-http-server
|
||||||
|
- path: ti/ek-tm4c1294xl-make-baremetal-builtin-rndis
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
device_dashboard_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: esp32/device-dashboard
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: echo # nothing specific to install or do
|
||||||
|
- run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
device_dashboard_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
|
example:
|
||||||
|
- path: infineon/infineon-xmc7200
|
||||||
|
- path: microchip/same54-xpro/device-dashboard
|
||||||
|
- path: nxp/rt1020-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1020-evk-make-freertos-builtin
|
||||||
|
- path: nxp/frdm-mcxn947-make-baremetal-builtin
|
||||||
|
- path: nxp/frdm-mcxn947-make-freertos-builtin
|
||||||
|
- path: nxp/rt1060-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1060-evk-make-freertos-builtin
|
||||||
|
- path: nxp/rt1170-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1170-evk-make-freertos-builtin
|
||||||
|
- path: renesas/ek-ra6m4-make-baremetal-builtin
|
||||||
|
- path: rp2040/pico-rndis-dashboard
|
||||||
|
- path: rp2040/pico-w
|
||||||
|
- path: rp2040/pico-w5500
|
||||||
|
- path: stm32/nucleo-f429zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-f429zi-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-freertos-tcp
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin-cmsis_driver
|
||||||
|
- path: stm32/nucleo-h563zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-h563zi-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-h723zg-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-h743zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-h743zi-make-freertos-builtin
|
||||||
|
- path: stm32/stm32h573i-dk-make-baremetal-builtin
|
||||||
|
- path: stm32/stm32h573i-dk-make-freertos-builtin
|
||||||
|
- path: ti/ek-tm4c1294xl-make-baremetal-builtin
|
||||||
|
- path: ti/ek-tm4c1294xl-make-freertos-builtin
|
||||||
|
name: ${{ matrix.example.path }} ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/${{ matrix.example.path }} build CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
|
||||||
|
# mqtt_dashboard_examples:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# strategy:
|
||||||
|
# fail-fast: false
|
||||||
|
# matrix:
|
||||||
|
# example:
|
||||||
|
# - path:
|
||||||
|
# name: ${{ matrix.example.path }}
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v4
|
||||||
|
# with: { fetch-depth: 2 }
|
||||||
|
# - run: echo # nothing specific to install or do
|
||||||
|
# - run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
mqtt_dashboard_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: rp2040/pico-rndis-device
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
# dual_examples:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# strategy:
|
||||||
|
# fail-fast: false
|
||||||
|
# matrix:
|
||||||
|
# example:
|
||||||
|
# - path:
|
||||||
|
# name: ${{ matrix.example.path }}
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v4
|
||||||
|
# with: { fetch-depth: 2 }
|
||||||
|
# - run: echo # nothing specific to install or do
|
||||||
|
# - run: make -C examples/${{ matrix.example.path }} device_dashboard
|
||||||
|
# - run: make -C examples/${{ matrix.example.path }} mqtt_dashboard
|
||||||
|
|
||||||
|
dual_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: stm32/nucleo-h723zg-make-baremetal-builtin
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/${{ matrix.example.path }} device_dashboard
|
||||||
|
- run: make -C examples/${{ matrix.example.path }} mqtt_dashboard
|
||||||
|
|
||||||
|
cube_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: echo # nothing specific to install or do
|
||||||
|
- run: cd test/cube && make
|
||||||
|
|
||||||
|
zephyr_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/zephyr init
|
||||||
|
- name: minify manifest
|
||||||
|
uses: mikefarah/yq@master
|
||||||
|
with:
|
||||||
|
cmd: yq -i eval '(.manifest.defaults, .manifest.remotes, .manifest.projects[] | select(.name == "cmsis" or .name == "hal_stm32" or .name == "mbedtls" or .name == "mcuboot" or .name == "picolibc" | del(.null) ), .manifest.self) as $i ireduce({};setpath($i | path; $i)) | del(.manifest.projects.[].null) | del(..|select(length==0))' examples/zephyr/zephyrproject/zephyr/west.yml
|
||||||
|
- run: make -C examples/zephyr update
|
||||||
|
- run: make -C examples/zephyr/device-dashboard build
|
||||||
|
- run: make -C examples/zephyr/http-client build
|
||||||
|
- run: make -C examples/zephyr/http-server build
|
||||||
|
- run: make -C examples/zephyr/mqtt-aws-client build
|
||||||
|
- run: make -C examples/zephyr/websocket-server build
|
||||||
|
|
||||||
|
test_f7:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- name: Cube
|
||||||
|
run: echo # nothing specific to install or do
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
|
||||||
|
test_f4:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- name: Cube
|
||||||
|
run: echo # nothing specific to install or do
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
|
||||||
|
test_h743:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- name: Cube
|
||||||
|
run: echo # nothing specific to install or do
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
|
- run: make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
|
|
||||||
|
test_h723:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_h5:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_rt1020:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_rt1060:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_rt1170:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_ra6m4:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
# - run: make -C examples/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_tm4c:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_same54:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/microchip/same54-xpro/device-dashboard test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- run: make -C examples/microchip/same54-xpro/mqtt-client test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_pico_w5500:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: SDK
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- run: make -C examples/rp2040/pico-w5500 test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
@@ -0,0 +1,758 @@
|
|||||||
|
name: Build and test - essentials
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "**Makefile"
|
||||||
|
- "**.c"
|
||||||
|
- "**.h"
|
||||||
|
env:
|
||||||
|
IPV6: 0
|
||||||
|
jobs:
|
||||||
|
linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
cc: [gcc, clang++]
|
||||||
|
target: [test, mip_test]
|
||||||
|
ssl: ["", BUILTIN]
|
||||||
|
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
||||||
|
env:
|
||||||
|
CC: ${{ matrix.cc }}
|
||||||
|
SSL: ${{ matrix.ssl }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C test ${{ matrix.target }}
|
||||||
|
s390:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: sudo apt -y update ; sudo apt -y install qemu binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390
|
||||||
|
armhf:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: sudo apt -y update ; sudo apt -y install qemu binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf
|
||||||
|
unamalgamated-mg_prefix:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C test unamalgamated && make -C test mg_prefix
|
||||||
|
macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", BUILTIN]
|
||||||
|
name: macos SSL=${{ matrix.ssl }}
|
||||||
|
env:
|
||||||
|
SSL: ${{ matrix.ssl }}
|
||||||
|
TFLAGS: -DNO_SNTP_CHECK
|
||||||
|
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C test test ASAN_OPTIONS=
|
||||||
|
windows:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target: [vc98, vc22, mingw++]
|
||||||
|
name: windows ${{ matrix.target }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C test ${{ matrix.target }}
|
||||||
|
arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test arm
|
||||||
|
riscv:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test riscv
|
||||||
|
|
||||||
|
examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test examples_essential
|
||||||
|
- run: make -C test clean_examples_essential
|
||||||
|
examples_win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# - uses: egor-tensin/setup-mingw@v2
|
||||||
|
# with:
|
||||||
|
# platform: x64
|
||||||
|
- name: test they build
|
||||||
|
run: make -C test examples_win
|
||||||
|
shell: cmd
|
||||||
|
- name: test they clean
|
||||||
|
run: make -C test clean_examples_win
|
||||||
|
shell: cmd
|
||||||
|
examples_mac:
|
||||||
|
runs-on: macos-latest
|
||||||
|
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test examples_mac
|
||||||
|
- run: make -C test clean_examples_mac
|
||||||
|
|
||||||
|
refprojs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test refprojs
|
||||||
|
- run: make -C test clean_refprojs
|
||||||
|
refprojs_win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# - uses: egor-tensin/setup-mingw@v2
|
||||||
|
# with:
|
||||||
|
# platform: x64
|
||||||
|
- name: test they build
|
||||||
|
run: make -C test refprojs_win
|
||||||
|
shell: cmd
|
||||||
|
- name: test they clean
|
||||||
|
run: make -C test clean_refprojs_win
|
||||||
|
shell: cmd
|
||||||
|
refprojs_mac:
|
||||||
|
runs-on: macos-latest
|
||||||
|
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test refprojs
|
||||||
|
- run: make -C test clean_refprojs
|
||||||
|
|
||||||
|
tutorials:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test tutorials_essential
|
||||||
|
- run: make -C test clean_tutorials_essential
|
||||||
|
tutorials_win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
# - uses: egor-tensin/setup-mingw@v2
|
||||||
|
# with:
|
||||||
|
# platform: x64
|
||||||
|
- name: test they build
|
||||||
|
run: make -C test tutorials_win
|
||||||
|
shell: cmd
|
||||||
|
- name: test they clean
|
||||||
|
run: make -C test clean_tutorials_win
|
||||||
|
shell: cmd
|
||||||
|
tutorials_mac:
|
||||||
|
runs-on: macos-latest
|
||||||
|
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: make -C test tutorials_mac
|
||||||
|
- run: make -C test clean_tutorials_mac
|
||||||
|
|
||||||
|
|
||||||
|
generic_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: esp32/uart-bridge
|
||||||
|
- path: esp8266/http-client-server
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
# nothing specific to install or do
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
generic_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
||||||
|
- path: stm32/nucleo-g031-make-baremetal-builtin
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
device_dashboard_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: esp32/device-dashboard
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
device_dashboard_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: infineon/infineon-xmc7200
|
||||||
|
- path: microchip/same54-xpro/device-dashboard
|
||||||
|
- path: nxp/frdm-mcxn947-make-baremetal-builtin
|
||||||
|
- path: nxp/frdm-mcxn947-make-freertos-builtin
|
||||||
|
- path: nxp/rt1020-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1020-evk-make-freertos-builtin
|
||||||
|
- path: nxp/rt1060-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1060-evk-make-freertos-builtin
|
||||||
|
- path: nxp/rt1170-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1170-evk-make-freertos-builtin
|
||||||
|
- path: renesas/ek-ra6m4-make-baremetal-builtin
|
||||||
|
- path: rp2040/pico-rndis-dashboard
|
||||||
|
- path: rp2040/pico-w
|
||||||
|
- path: rp2040/pico-w5500
|
||||||
|
- path: stm32/nucleo-f429zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-f429zi-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-freertos-tcp
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin-cmsis_driver
|
||||||
|
- path: stm32/nucleo-h563zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-h563zi-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-h723zg-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-h743zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-h743zi-make-freertos-builtin
|
||||||
|
- path: stm32/stm32h573i-dk-make-baremetal-builtin
|
||||||
|
- path: stm32/stm32h573i-dk-make-freertos-builtin
|
||||||
|
- path: ti/ek-tm4c1294xl-make-baremetal-builtin
|
||||||
|
- path: ti/ek-tm4c1294xl-make-freertos-builtin
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
# mqtt_dashboard_examples:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# strategy:
|
||||||
|
# fail-fast: false
|
||||||
|
# matrix:
|
||||||
|
# example:
|
||||||
|
# - path:
|
||||||
|
# name: ${{ matrix.example.path }}
|
||||||
|
# env:
|
||||||
|
# GO: 0
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v4
|
||||||
|
# with: { fetch-depth: 2 }
|
||||||
|
# - run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
|
# # nothing specific to install or do
|
||||||
|
# fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
mqtt_dashboard_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: rp2040/pico-rndis-device
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
# dual_examples:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# strategy:
|
||||||
|
# fail-fast: false
|
||||||
|
# matrix:
|
||||||
|
# example:
|
||||||
|
# - path:
|
||||||
|
# name: ${{ matrix.example.path }}
|
||||||
|
# env:
|
||||||
|
# GO: 0
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v4
|
||||||
|
# with: { fetch-depth: 2 }
|
||||||
|
# - run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
|
# # nothing specific to install or do
|
||||||
|
# fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# make -C examples/${{ matrix.example.path }} device_dashboard
|
||||||
|
# fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# make -C examples/${{ matrix.example.path }} mqtt_dashboard
|
||||||
|
# fi
|
||||||
|
|
||||||
|
dual_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: stm32/nucleo-h723zg-make-baremetal-builtin
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
make -C examples/${{ matrix.example.path }} device_dashboard
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
make -C examples/${{ matrix.example.path }} mqtt_dashboard
|
||||||
|
fi
|
||||||
|
|
||||||
|
cube_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/stm32/nucleo-*-cube-*'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: cd test/cube && make
|
||||||
|
|
||||||
|
test_f7:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32|examples/nxp|examples/ti|examples/microchip/same" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
# always run baremetal on core or dashboard or specific example changes; other examples only on specific example changes
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true # continue so next test has a chance to re-flash and exit from collisions and flash failures
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-make-freertos-tcp'; then
|
||||||
|
make -C examples/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- name: Cube
|
||||||
|
run: |
|
||||||
|
echo GO=0 >> $GITHUB_ENV
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f7.*-cube-'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-freertos-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-freertos-lwip'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
test_f4:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f4.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f429zi-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- name: Cube
|
||||||
|
run: |
|
||||||
|
echo GO=0 >> $GITHUB_ENV
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f4.*-cube-'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-cube-freertos-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-cube-freertos-lwip'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_h743:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h74.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h743zi-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- name: Cube
|
||||||
|
run: |
|
||||||
|
echo GO=0 >> $GITHUB_ENV
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h74.*-cube-'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-cube-freertos-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_h723:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h72.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h723zg-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h723zg-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_h5:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h5.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h563zi-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/stm32/nucleo-h563zi-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_rt1020:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1020.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1020-evk-make-baremetal-builtin'; then
|
||||||
|
make -C examples/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/nxp/rt1020-evk-make-freertos-builtin'; then
|
||||||
|
make -C examples/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_rt1060:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1060.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1060-evk-make-baremetal-builtin'; then
|
||||||
|
make -C examples/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/nxp/rt1060-evk-make-freertos-builtin'; then
|
||||||
|
make -C examples/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_rt1170:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1170.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1170-evk-make-baremetal-builtin'; then
|
||||||
|
make -C examples/nxp/rt1170-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/nxp/rt1170-evk-make-freertos-builtin'; then
|
||||||
|
make -C examples/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_ra6m4:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/renesas/ek-ra6m4.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
continue-on-error: true
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/renesas/ek-ra6m4-make-baremetal-builtin'; then
|
||||||
|
make -C examples/renesas/ek-ra6m4-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh 'examples/renesas/ek-ra6m4-make-freertos-builtin'; then
|
||||||
|
# make -C examples/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
# fi
|
||||||
|
|
||||||
|
test_tm4c:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/ti/ek-tm4c.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
|
||||||
|
make -C examples/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/ti/ek-tm4c1294xl-make-freertos-builtin'; then
|
||||||
|
make -C examples/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_same54:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/microchip/same54-xpro" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/microchip/same54-xpro/device-dashboard'; then
|
||||||
|
make -C examples/microchip/same54-xpro/device-dashboard test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh 'examples/microchip/same54-xpro/mqtt-client'; then
|
||||||
|
make -C examples/microchip/same54-xpro/mqtt-client test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_pico_w5500:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: SDK
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/rp2040/pico-w5500" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/rp2040/pico-w5500 test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
@@ -1,128 +1,740 @@
|
|||||||
name: build
|
name: original workflow, outdated # *** YES, OUTDATED *** kept for hystorical/reference purposes, attachment, etc.
|
||||||
on: [push, pull_request]
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
env:
|
||||||
|
IPV6: 0
|
||||||
jobs:
|
jobs:
|
||||||
linux:
|
linux:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
cc: [gcc, clang]
|
cc: [gcc, clang, g++, clang++]
|
||||||
target: [test, test++, valgrind]
|
target: [test, mip_test]
|
||||||
ssl: [MBEDTLS, OPENSSL]
|
ssl: ["", MBEDTLS, OPENSSL]
|
||||||
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
select: ["-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0", "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0", "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=1"]
|
||||||
|
exclude:
|
||||||
|
- ssl: MBEDTLS
|
||||||
|
select: "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: MBEDTLS
|
||||||
|
select: "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: OPENSSL
|
||||||
|
select: "-DMG_ENABLE_POLL=0 -DMG_ENABLE_EPOLL=0"
|
||||||
|
- ssl: OPENSSL
|
||||||
|
select: "-DMG_ENABLE_POLL=1 -DMG_ENABLE_EPOLL=0"
|
||||||
|
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||||
env:
|
env:
|
||||||
IPV6: 0
|
|
||||||
CC: ${{ matrix.cc }}
|
CC: ${{ matrix.cc }}
|
||||||
SSL: ${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
|
TFLAGS: ${{ matrix.select }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install packages
|
with: { fetch-depth: 2 }
|
||||||
run: sudo apt-get update ; sudo apt-get install libmbedtls-dev valgrind
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- name: test
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make ${{ matrix.target }}
|
run: ./test/setup_ga_network.sh && sudo apt -y update ; sudo apt -y install libmbedtls-dev && make ${{ matrix.target }}
|
||||||
- name: unamalgamated
|
s390:
|
||||||
run: make unamalgamated
|
|
||||||
examples:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: sudo apt-get install libmbedtls-dev libpcap-dev
|
with: { fetch-depth: 2 }
|
||||||
- run: make clean examples
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- run: make clean test IPV6=0 MG_ENABLE_POLL=1
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: sudo apt -y update ; sudo apt -y install qemu binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make s390
|
||||||
|
armhf:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: sudo apt -y update ; sudo apt -y install qemu binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make armhf
|
||||||
|
linux2:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: sudo apt -y update ; sudo apt -y install libmbedtls-dev valgrind
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make unamalgamated && make valgrind && make mg_prefix
|
||||||
macos:
|
macos:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
ssl: ["", MBEDTLS, OPENSSL]
|
||||||
|
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
|
||||||
|
exclude:
|
||||||
|
- ssl: MBEDTLS
|
||||||
|
select: -DMG_ENABLE_POLL=0
|
||||||
|
- ssl: OPENSSL
|
||||||
|
select: -DMG_ENABLE_POLL=0
|
||||||
|
name: macos SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||||
|
env:
|
||||||
|
SSL: ${{ matrix.ssl }}
|
||||||
|
TFLAGS: ${{ matrix.select }} -DNO_SNTP_CHECK -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
|
||||||
|
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install jq mbedtls openssl
|
with: { fetch-depth: 2 }
|
||||||
- run: make test++ upload-coverage IPV6=0 ASAN_OPTIONS=
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- run: make test SSL=OPENSSL IPV6=0 ASAN_OPTIONS= OPENSSL=`echo /usr/local/Cellar/openssl*/*`
|
- if: ${{ env.GO == 1 }}
|
||||||
- run: make mg_prefix
|
run: brew install jq mbedtls openssl
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make test ASAN_OPTIONS= MBEDTLS=`echo /usr/local/Cellar/mbedtls*/*` OPENSSL=`echo /usr/local/Cellar/openssl*/*`
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make mg_prefix
|
||||||
windows:
|
windows:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target: [vc98, vc17, vc22, mingw, mingw++]
|
||||||
|
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
|
||||||
|
exclude:
|
||||||
|
- target: vc98
|
||||||
|
select: -DMG_ENABLE_POLL=1
|
||||||
|
name: windows ${{ matrix.target }} TFLAGS=${{ matrix.select }}
|
||||||
|
env:
|
||||||
|
TFLAGS: ${{ matrix.select }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: make vc98
|
with: { fetch-depth: 2 }
|
||||||
- run: make vc17
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- run: make vc22
|
- if: ${{ env.GO == 1 }}
|
||||||
- run: make mingw
|
run: make ${{ matrix.target }}
|
||||||
- run: make mingw++
|
|
||||||
arm:
|
arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: make arm
|
- run: make arm
|
||||||
matrix_examples:
|
riscv:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: make riscv
|
||||||
|
|
||||||
|
examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: sudo apt -y install libmbedtls-dev libpcap-dev
|
||||||
|
- run: make examples
|
||||||
|
- run: make clean
|
||||||
|
examples_win:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
# - uses: egor-tensin/setup-mingw@v2
|
||||||
|
# with:
|
||||||
|
# platform: x64
|
||||||
|
- name: test they build
|
||||||
|
run: make examples_win
|
||||||
|
shell: cmd
|
||||||
|
- name: test they clean
|
||||||
|
run: make clean_examples_win
|
||||||
|
shell: cmd
|
||||||
|
examples_mac:
|
||||||
|
runs-on: macos-latest
|
||||||
|
env: { HOMEBREW_NO_AUTO_UPDATE: 1 }
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: make examples_mac
|
||||||
|
- run: make clean_examples_mac
|
||||||
|
|
||||||
|
|
||||||
|
arduino:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/arduino" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/arduino'; then
|
||||||
|
make -C examples/arduino arduino-xiao
|
||||||
|
fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/arduino'; then
|
||||||
|
# make -C examples/arduino arduino-nano
|
||||||
|
# fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/arduino clean
|
||||||
|
|
||||||
|
|
||||||
|
generic_examples:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- name: esp32/device-dashboard
|
- path: esp32/uart-bridge
|
||||||
path: esp32/device-dashboard
|
- path: esp32/micropython
|
||||||
- name: esp8266
|
- path: esp8266/http-client-server
|
||||||
path: esp8266
|
name: ${{ matrix.example.path }}
|
||||||
- name: stm32-freertos-tcp
|
env:
|
||||||
path: stm32/stm32-freertos-tcp
|
GO: 0
|
||||||
- name: stm32-nucleo-f746z
|
|
||||||
path: stm32/stm32-nucleo-f746z
|
|
||||||
- name: stm32-nucleo-f429z
|
|
||||||
path: stm32/stm32-nucleo-f429z
|
|
||||||
- name: stm32-nucleo-h743z
|
|
||||||
path: stm32/stm32-nucleo-h743z
|
|
||||||
- name: stm32-nucleo-f746zg-baremetal
|
|
||||||
path: stm32/nucleo-f746zg-baremetal
|
|
||||||
- name: nxp-mimxrt1020-azurertos
|
|
||||||
path: nxp/nxp-mimxrt1020-azurertos
|
|
||||||
- name: nxp-frdmk66f-freertos
|
|
||||||
path: nxp/nxp-frdmk66f-freertos
|
|
||||||
- name: nxp-lpcxpresso54s018m-freertos
|
|
||||||
path: nxp/nxp-lpcxpresso54s018m-freertos
|
|
||||||
- name: nxp-mimxrt1020-freertos
|
|
||||||
path: nxp/nxp-mimxrt1020-freertos
|
|
||||||
- name: nxp-evkbimxrt1050-lwip-freertos
|
|
||||||
path: nxp/nxp-evkbimxrt1050-lwip-freertos
|
|
||||||
- name: nxp-evkmimxrt1020-lwip-freertos
|
|
||||||
path: nxp/nxp-evkmimxrt1020-lwip-freertos
|
|
||||||
- name: nxp-evkmimxrt1024-lwip-freertos
|
|
||||||
path: nxp/nxp-evkmimxrt1024-lwip-freertos
|
|
||||||
- name: nxp-evkmimxrt1060-lwip-freertos
|
|
||||||
path: nxp/nxp-evkmimxrt1060-lwip-freertos
|
|
||||||
- name: nxp-evkmimxrt1064-lwip-freertos
|
|
||||||
path: nxp/nxp-evkmimxrt1064-lwip-freertos
|
|
||||||
- name: nxp-evkmimxrt1160-cm7-lwip-freertos
|
|
||||||
path: nxp/nxp-evkmimxrt1160-cm7-lwip-freertos
|
|
||||||
- name: nxp-evkmimxrt1170-cm7-lwip-freertos
|
|
||||||
path: nxp/nxp-evkmimxrt1170-cm7-lwip-freertos
|
|
||||||
- name: nxp-frdmk64f-lwip-freertos
|
|
||||||
path: nxp/nxp-frdmk64f-lwip-freertos
|
|
||||||
- name: nxp-frdmk66f-lwip-freertos
|
|
||||||
path: nxp/nxp-frdmk66f-lwip-freertos
|
|
||||||
- name: nxp-lpcxpresso54018-lwip-freertos
|
|
||||||
path: nxp/nxp-lpcxpresso54018-lwip-freertos
|
|
||||||
- name: nxp-lpcxpresso54608-lwip-freertos
|
|
||||||
path: nxp/nxp-lpcxpresso54608-lwip-freertos
|
|
||||||
- name: nxp-lpcxpresso54618-lwip-freertos
|
|
||||||
path: nxp/nxp-lpcxpresso54618-lwip-freertos
|
|
||||||
- name: nxp-lpcxpresso54628-lwip-freertos
|
|
||||||
path: nxp/nxp-lpcxpresso54628-lwip-freertos
|
|
||||||
- name: nxp-twrk65f180m-lwip-freertos
|
|
||||||
path: nxp/nxp-twrk65f180m-lwip-freertos
|
|
||||||
- name: nxp-twrkv58f220m-lwip-freertos
|
|
||||||
path: nxp/nxp-twrkv58f220m-lwip-freertos
|
|
||||||
- name: infineon-xmc4700_4800-lwip-rtx-rtos
|
|
||||||
path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
|
||||||
- name: ti
|
|
||||||
path: ti/ti-ek-tm4c1294xl-http-server
|
|
||||||
- name: nucleo_f746zg-zephyr-http-client
|
|
||||||
path: zephyr/http-client
|
|
||||||
- name: nucleo_f746zg-zephyr-http-server
|
|
||||||
path: zephyr/http-server
|
|
||||||
- name: nucleo_f746zg-zephyr-mqtt-aws-client
|
|
||||||
path: zephyr/mqtt-aws-client
|
|
||||||
- name: nucleo_f746zg-zephyr-websocket-server
|
|
||||||
path: zephyr/websocket-server
|
|
||||||
name: ${{ matrix.example.name }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: ${{ matrix.example.name }}
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
# nothing specific to install or do
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
generic_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: microchip/same54-xpro/mqtt-client
|
||||||
|
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
||||||
|
- path: nxp/nxp-mimxrt1020-azurertos
|
||||||
|
- path: nxp/nxp-frdmk66f-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54s018m-freertos
|
||||||
|
- path: nxp/nxp-mimxrt1020-freertos
|
||||||
|
- path: nxp/nxp-evkbimxrt1050-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1020-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1024-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1060-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1064-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1160-cm7-lwip-freertos
|
||||||
|
- path: nxp/nxp-evkmimxrt1170-cm7-lwip-freertos
|
||||||
|
- path: nxp/nxp-frdmk64f-lwip-freertos
|
||||||
|
- path: nxp/nxp-frdmk66f-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54018-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54608-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54618-lwip-freertos
|
||||||
|
- path: nxp/nxp-lpcxpresso54628-lwip-freertos
|
||||||
|
- path: nxp/nxp-twrk65f180m-lwip-freertos
|
||||||
|
- path: nxp/nxp-twrkv58f220m-lwip-freertos
|
||||||
|
- path: rp2040/pico-rmii
|
||||||
|
- path: stm32/nucleo-f429zi-make-baremetal-builtin-rndis
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin-rndis
|
||||||
|
- path: stm32/nucleo-g031-make-baremetal-builtin
|
||||||
|
- path: ti/ti-ek-tm4c1294xl-http-server
|
||||||
|
- path: ti/ek-tm4c1294xl-make-baremetal-builtin-rndis
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
device_dashboard_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: esp32/device-dashboard
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
device_dashboard_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: microchip/same54-xpro/device-dashboard
|
||||||
|
- path: nxp/rt1020-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1020-evk-make-freertos-builtin
|
||||||
|
- path: nxp/rt1060-evk-make-baremetal-builtin
|
||||||
|
- path: nxp/rt1060-evk-make-freertos-builtin
|
||||||
|
- path: rp2040/pico-rndis-dashboard
|
||||||
|
- path: rp2040/pico-w
|
||||||
|
- path: rp2040/pico-w5500
|
||||||
|
- path: stm32/nucleo-f429zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-f429zi-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-f746zg-make-freertos-tcp
|
||||||
|
- path: stm32/nucleo-f746zg-make-baremetal-builtin-cmsis_driver
|
||||||
|
- path: stm32/nucleo-h563zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-h563zi-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-h723zg-make-freertos-builtin
|
||||||
|
- path: stm32/nucleo-h743zi-make-baremetal-builtin
|
||||||
|
- path: stm32/nucleo-h743zi-make-freertos-builtin
|
||||||
|
- path: stm32/stm32h573i-dk-make-baremetal-builtin
|
||||||
|
- path: stm32/stm32h573i-dk-make-freertos-builtin
|
||||||
|
- path: ti/ek-tm4c1294xl-make-baremetal-builtin
|
||||||
|
- path: ti/ek-tm4c1294xl-make-freertos-builtin
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
# mqtt_dashboard_examples:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# strategy:
|
||||||
|
# fail-fast: false
|
||||||
|
# matrix:
|
||||||
|
# example:
|
||||||
|
# - path:
|
||||||
|
# name: ${{ matrix.example.path }}
|
||||||
|
# env:
|
||||||
|
# GO: 0
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v3
|
||||||
|
# with: { fetch-depth: 2 }
|
||||||
|
# - run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
|
# # nothing specific to install or do
|
||||||
|
# fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
mqtt_dashboard_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: rp2040/pico-rndis-device
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
# dual_examples:
|
||||||
|
# runs-on: ubuntu-latest
|
||||||
|
# strategy:
|
||||||
|
# fail-fast: false
|
||||||
|
# matrix:
|
||||||
|
# example:
|
||||||
|
# - path:
|
||||||
|
# name: ${{ matrix.example.path }}
|
||||||
|
# env:
|
||||||
|
# GO: 0
|
||||||
|
# steps:
|
||||||
|
# - uses: actions/checkout@v3
|
||||||
|
# with: { fetch-depth: 2 }
|
||||||
|
# - run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
|
# # nothing specific to install or do
|
||||||
|
# fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# make -C examples/${{ matrix.example.path }} device_dashboard
|
||||||
|
# fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
# make -C examples/${{ matrix.example.path }} mqtt_dashboard
|
||||||
|
# fi
|
||||||
|
|
||||||
|
dual_examples_arm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
example:
|
||||||
|
- path: stm32/nucleo-h723zg-make-baremetal-builtin
|
||||||
|
name: ${{ matrix.example.path }}
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
||||||
|
make -C examples/${{ matrix.example.path }} device_dashboard
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
||||||
|
make -C examples/${{ matrix.example.path }} mqtt_dashboard
|
||||||
|
fi
|
||||||
|
|
||||||
|
cube_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/stm32/nucleo-*-cube-*'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: cd test/cube && make
|
||||||
|
|
||||||
|
zephyr_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: |
|
||||||
|
if ./test/match_changed_files.sh '^src/.*.[ch]|^examples/zephyr'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/zephyr init
|
||||||
|
- name: minify manifest
|
||||||
|
if: ${{ env.GO == 1 }}
|
||||||
|
uses: mikefarah/yq@master
|
||||||
|
with:
|
||||||
|
cmd: yq -i eval '(.manifest.defaults, .manifest.remotes, .manifest.projects[] | select(.name == "cmsis" or .name == "hal_stm32" or .name == "mbedtls" or .name == "mcuboot" or .name == "picolibc" | del(.null) ), .manifest.self) as $i ireduce({};setpath($i | path; $i)) | del(.manifest.projects.[].null) | del(..|select(length==0))' examples/zephyr/zephyrproject/zephyr/west.yml
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/zephyr update
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/zephyr/device-dashboard build
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/zephyr/http-client build
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/zephyr/http-server build
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/zephyr/mqtt-aws-client build
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/zephyr/websocket-server build
|
||||||
|
|
||||||
|
test_f7:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f7.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f746zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-make-freertos-tcp'; then
|
||||||
|
make -C examples/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- name: Cube
|
||||||
|
run: |
|
||||||
|
echo GO=0 >> $GITHUB_ENV
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f7.*-cube-'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-cube-freertos-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f746zg-cube-freertos-lwip'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
test_f4:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-f4.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f429zi-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f429zi-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- name: Cube
|
||||||
|
run: |
|
||||||
|
echo GO=0 >> $GITHUB_ENV
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f4.*-cube-'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f429zi-cube-freertos-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-f429zi-cube-freertos-lwip'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_h743:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h74.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h743zi-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h743zi-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- name: Cube
|
||||||
|
run: |
|
||||||
|
echo GO=0 >> $GITHUB_ENV
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h74.*-cube-'; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
# nothing specific to install or do
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h743zi-cube-freertos-builtin'; then
|
||||||
|
make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_h723:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h72.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h723zg-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h723zg-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_h5:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h5.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h563zi-make-baremetal-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h563zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/stm32/nucleo-h563zi-make-freertos-builtin'; then
|
||||||
|
make -C examples/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_rt1020:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1020.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
#if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1020-evk-make-baremetal-builtin'; then
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/nxp/rt1020-evk-make-baremetal-builtin'; then
|
||||||
|
make -C examples/nxp/rt1020-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
#if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1020-evk-make-freertos-builtin'; then
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/nxp/rt1020-evk-make-freertos-builtin'; then
|
||||||
|
make -C examples/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_rt1060:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 3 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/nxp/rt1060.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1060-evk-make-baremetal-builtin'; then
|
||||||
|
make -C examples/nxp/rt1060-evk-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/nxp/rt1060-evk-make-freertos-builtin'; then
|
||||||
|
make -C examples/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
test_tm4c:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/ti/ek-tm4c.*-make-" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_same54:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: baremetal
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/microchip/same54-xpro" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/microchip/same54-xpro/device-dashboard test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/microchip/same54-xpro/mqtt-client test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
|
test_pico_w5500:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
GO: 0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- name: SDK
|
||||||
|
run: |
|
||||||
|
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/rp2040/pico-w5500" ; then
|
||||||
|
echo GO=1 >> $GITHUB_ENV
|
||||||
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
|
fi
|
||||||
|
- if: ${{ env.GO == 1 }}
|
||||||
|
run: make -C examples/rp2040/pico-w5500 test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2004-2013 Sergey Lyubka
|
Copyright (c) 2004-2013 Sergey Lyubka
|
||||||
Copyright (c) 2013-2021 Cesanta Software Limited
|
Copyright (c) 2013-2024 Cesanta Software Limited
|
||||||
All rights reserved
|
All rights reserved
|
||||||
|
|
||||||
This software is dual-licensed: you can redistribute it and/or modify
|
This software is dual-licensed: you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,164 +0,0 @@
|
|||||||
SRCS = mongoose.c test/unit_test.c test/packed_fs.c
|
|
||||||
HDRS = $(wildcard src/*.h) $(wildcard mip/*.h)
|
|
||||||
DEFS ?= -DMG_MAX_HTTP_HEADERS=7 -DMG_ENABLE_LINES -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_SSI=1
|
|
||||||
C_WARN ?= -Wmissing-prototypes -Wstrict-prototypes
|
|
||||||
WARN ?= -pedantic -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion -Wundef $(C_WARN)
|
|
||||||
OPTS ?= -O3 -g3
|
|
||||||
VALGRIND_OPTS ?= -O0 -g3
|
|
||||||
INCS ?= -Isrc -I.
|
|
||||||
SSL ?= MBEDTLS
|
|
||||||
CWD ?= $(realpath $(CURDIR))
|
|
||||||
ENV ?= -e Tmp=. -e WINEDEBUG=-all
|
|
||||||
DOCKER ?= docker run --platform linux/amd64 --rm $(ENV) -v $(CWD):$(CWD) -w $(CWD)
|
|
||||||
VCFLAGS = /nologo /W3 /O2 /MD /I. $(DEFS) $(TFLAGS)
|
|
||||||
IPV6 ?= 1
|
|
||||||
ASAN ?= -fsanitize=address,undefined -fno-sanitize-recover=all
|
|
||||||
ASAN_OPTIONS ?= detect_leaks=1
|
|
||||||
EXAMPLES := $(dir $(wildcard examples/*/Makefile)) examples/stm32/nucleo-f746zg-baremetal
|
|
||||||
PREFIX ?= /usr/local
|
|
||||||
VERSION ?= $(shell cut -d'"' -f2 src/version.h)
|
|
||||||
COMMON_CFLAGS ?= $(WARN) $(INCS) $(DEFS) -DMG_ENABLE_IPV6=$(IPV6) $(TFLAGS)
|
|
||||||
CFLAGS ?= $(OPTS) $(ASAN) $(COMMON_CFLAGS)
|
|
||||||
VALGRIND_CFLAGS ?= $(VALGRIND_OPTS) $(COMMON_CFLAGS)
|
|
||||||
VALGRIND_RUN ?= valgrind --tool=memcheck --gen-suppressions=all --leak-check=full --show-leak-kinds=all --leak-resolution=high --track-origins=yes --error-exitcode=1 --exit-on-first-error=yes
|
|
||||||
.PHONY: examples test valgrind
|
|
||||||
|
|
||||||
ifeq "$(SSL)" "MBEDTLS"
|
|
||||||
MBEDTLS ?= /usr/local
|
|
||||||
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
|
||||||
LDFLAGS ?= -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
|
||||||
endif
|
|
||||||
ifeq "$(SSL)" "OPENSSL"
|
|
||||||
OPENSSL ?= /usr/local
|
|
||||||
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include
|
|
||||||
LDFLAGS ?= -L$(OPENSSL)/lib -lssl -lcrypto
|
|
||||||
endif
|
|
||||||
|
|
||||||
all: mg_prefix unamalgamated unpacked test test++ arm examples vc98 vc17 vc22 mingw mingw++ linux linux++ fuzz
|
|
||||||
|
|
||||||
examples:
|
|
||||||
@for X in $(EXAMPLES); do test -f $$X/Makefile || continue; $(MAKE) -C $$X example || exit 1; done
|
|
||||||
|
|
||||||
test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt
|
|
||||||
$(CC) $(CFLAGS) test/pack.c -o pack
|
|
||||||
$(RUN) ./pack Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/range.txt > $@
|
|
||||||
|
|
||||||
DIR ?= test/data/
|
|
||||||
OUT ?= fs_packed.c
|
|
||||||
mkfs:
|
|
||||||
$(CC) $(CFLAGS) test/pack.c -o pack
|
|
||||||
$(RUN) ./pack -s $(DIR) `find $(DIR) -type f` > $(OUT)
|
|
||||||
# find $(DIR) -type f | sed -e s,^$(DIR),,g -e s,^/,,g
|
|
||||||
|
|
||||||
# Check that all external (exported) symbols have "mg_" prefix
|
|
||||||
mg_prefix: mongoose.c mongoose.h
|
|
||||||
$(CC) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T' | grep -v 'mg_' ; test $$? = 1
|
|
||||||
|
|
||||||
# C++ build
|
|
||||||
test++: test
|
|
||||||
test++: CC = g++
|
|
||||||
test++: C_WARN = -std=c++2a -Wno-vla -Wno-shadow -Wno-missing-field-initializers -Wno-deprecated
|
|
||||||
|
|
||||||
musl: test
|
|
||||||
musl: ASAN =
|
|
||||||
musl: WARN += -Wno-sign-conversion
|
|
||||||
musl: CC = $(DOCKER) mdashnet/cc1 gcc
|
|
||||||
musl: RUN = $(DOCKER) mdashnet/cc1
|
|
||||||
|
|
||||||
# Make sure we can build from an unamalgamated sources
|
|
||||||
unamalgamated: $(HDRS) Makefile test/packed_fs.c
|
|
||||||
$(CC) src/*.c test/packed_fs.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
|
|
||||||
|
|
||||||
unpacked:
|
|
||||||
$(CC) -I. mongoose.c test/unit_test.c -o $@
|
|
||||||
|
|
||||||
fuzzer: mongoose.c mongoose.h Makefile test/fuzz.c
|
|
||||||
clang++ mongoose.c test/fuzz.c $(WARN) $(INCS) $(TFLAGS) -DMG_ENABLE_LINES -fsanitize=fuzzer,signed-integer-overflow,address -Wno-deprecated -Wno-vla-extension -o $@
|
|
||||||
|
|
||||||
fuzz: fuzzer
|
|
||||||
$(RUN) ./fuzzer
|
|
||||||
|
|
||||||
unit_test: Makefile mongoose.h $(SRCS)
|
|
||||||
$(CC) $(SRCS) $(CFLAGS) $(LDFLAGS) -g -o unit_test
|
|
||||||
|
|
||||||
# make CC=/usr/local/opt/llvm\@8/bin/clang ASAN_OPTIONS=detect_leaks=1
|
|
||||||
test: unit_test
|
|
||||||
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./unit_test
|
|
||||||
|
|
||||||
coverage: CFLAGS += -coverage
|
|
||||||
coverage: test
|
|
||||||
gcov -l -n *.gcno | sed '/^$$/d' | sed 'N;s/\n/ /'
|
|
||||||
gcov -t mongoose.c > mongoose.gcov
|
|
||||||
|
|
||||||
upload-coverage: coverage
|
|
||||||
curl -s https://codecov.io/bash | /bin/bash
|
|
||||||
|
|
||||||
valgrind_unit_test: Makefile mongoose.h $(SRCS)
|
|
||||||
$(CC) $(SRCS) $(VALGRIND_CFLAGS) $(LDFLAGS) -g -o valgrind_unit_test
|
|
||||||
|
|
||||||
valgrind: valgrind_unit_test
|
|
||||||
$(VALGRIND_RUN) ./valgrind_unit_test
|
|
||||||
|
|
||||||
infer:
|
|
||||||
infer run -- cc test/unit_test.c -c -W -Wall -Werror -Isrc -I. -O2 -DMG_ENABLE_MBEDTLS=1 -DMG_ENABLE_LINES -I/usr/local/Cellar/mbedtls/2.23.0/include -DMG_ENABLE_IPV6=1 -g -o /dev/null
|
|
||||||
|
|
||||||
arm: DEFS += -DMG_ENABLE_FILE=0 -DMG_ENABLE_MIP=1 -DMG_ARCH=MG_ARCH_NEWLIB
|
|
||||||
arm: mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/armgcc arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test -nostartfiles --specs nosys.specs -e 0
|
|
||||||
|
|
||||||
riscv: DEFS += -DMG_ENABLE_FILE=0 -DMG_ENABLE_MIP=1 -DMG_ARCH=MG_ARCH_NEWLIB
|
|
||||||
riscv: mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/riscv riscv-none-elf-gcc -march=rv32imc -mabi=ilp32 $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test
|
|
||||||
|
|
||||||
vc98: Makefile mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
|
||||||
$(DOCKER) mdashnet/vc98 wine $@.exe
|
|
||||||
|
|
||||||
# vc17: DEFS += -DMG_ENABLE_IPV6=1
|
|
||||||
vc17: Makefile mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/vc17 wine64 cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
|
||||||
$(DOCKER) mdashnet/vc17 wine64 $@.exe
|
|
||||||
|
|
||||||
# vc22: DEFS += -DMG_ENABLE_IPV6=$(IPV6)
|
|
||||||
vc22: Makefile mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/vc22 wine64 cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
|
||||||
$(DOCKER) mdashnet/vc22 wine64 $@.exe
|
|
||||||
|
|
||||||
mingw: Makefile mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o $@.exe
|
|
||||||
$(DOCKER) mdashnet/mingw wine64 $@.exe
|
|
||||||
|
|
||||||
mingw++: Makefile mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o $@.exe
|
|
||||||
|
|
||||||
linux: IPV6=0
|
|
||||||
linux: Makefile mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/cc2 gcc $(SRCS) $(CFLAGS) $(LDFLAGS) -o unit_test_gcc
|
|
||||||
$(DOCKER) mdashnet/cc2 ./unit_test_gcc
|
|
||||||
|
|
||||||
linux++: CC = g++
|
|
||||||
linux++: WARN += -Wno-missing-field-initializers
|
|
||||||
linux++: linux
|
|
||||||
|
|
||||||
linux-libs: CFLAGS += -fPIC
|
|
||||||
linux-libs: mongoose.o
|
|
||||||
$(CC) mongoose.o $(LDFLAGS) -shared -o libmongoose.so.$(VERSION)
|
|
||||||
$(AR) rcs libmongoose.a mongoose.o
|
|
||||||
|
|
||||||
install: linux-libs
|
|
||||||
install -Dm644 libmongoose.a libmongoose.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib
|
|
||||||
ln -s libmongoose.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libmongoose.so
|
|
||||||
install -Dm644 mongoose.h $(DESTDIR)$(PREFIX)/include/mongoose.h
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -rf $(DESTDIR)$(PREFIX)/lib/libmongoose.a $(DESTDIR)$(PREFIX)/lib/libmongoose.so.$(VERSION) $(DESTDIR)$(PREFIX)/include/mongoose.h $(DESTDIR)$(PREFIX)/lib/libmongoose.so
|
|
||||||
|
|
||||||
mongoose.c: Makefile $(wildcard src/*) $(wildcard mip/*.c)
|
|
||||||
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c mip/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
|
||||||
|
|
||||||
mongoose.h: $(HDRS) Makefile
|
|
||||||
(cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/config.h src/str.h src/fmt.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h mip/mip.h | sed -e 's,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(PROG) *.exe *.o *.dSYM unit_test* valgrind_unit_test* ut fuzzer *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb slow-unit* _CL_* infer-out data.txt crash-* test/packed_fs.c pack unpacked
|
|
||||||
@for X in $(EXAMPLES); do $(MAKE) -C $$X clean; done
|
|
||||||
@@ -1,31 +1,136 @@
|
|||||||
# Mongoose - Embedded Web Server / Embedded Networking Library
|
# Mongoose - Embedded Web Server / Embedded Network Library
|
||||||
|
|
||||||
[](https://opensource.org/licenses/gpl-2.0.php)
|
[](https://opensource.org/licenses/gpl-2.0.php)
|
||||||
[](https://github.com/cesanta/mongoose/actions)
|
[](https://github.com/cesanta/mongoose/actions)
|
||||||
[](https://codecov.io/gh/cesanta/mongoose)
|
[](https://codecov.io/gh/cesanta/mongoose)
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:mongoose)
|
||||||
|
|
||||||
Mongoose is a networking library for C/C++. It implements event-driven
|
Mongoose is a network library for C/C++. It provides event-driven non-blocking
|
||||||
non-blocking APIs for TCP, UDP, HTTP, WebSocket, MQTT. It is designed for
|
APIs for TCP, UDP, HTTP, WebSocket, MQTT, and other protocols. It is designed
|
||||||
connecting devices and bringing them online. On the market since 2004, used by
|
for connecting devices and bringing them online. On the market since 2004, used
|
||||||
vast number of open source and commercial products - it even runs on the
|
by vast number of open source and commercial products - it even runs on the
|
||||||
International Space Station! Mongoose makes embedded network programming fast,
|
International Space Station! Mongoose makes embedded network programming fast,
|
||||||
robust, and easy. Features include:
|
robust, and easy. Features include:
|
||||||
|
|
||||||
- Cross-platform: works on Linux/UNIX, MacOS, Windows, Android, FreeRTOS, etc.
|
- Cross-platform:
|
||||||
- Supported embedded architectures: ESP32, NRF52, STM32, NXP, and more
|
- works on Linux/UNIX, MacOS, Windows, Android
|
||||||
- Built-in protocols: plain TCP/UDP, HTTP, MQTT, Websocket
|
- works on STM32, NXP, ESP32, NRF52, TI, Microchip, and other
|
||||||
- SSL/TLS support: mbedTLS, OpenSSL or custom (via API)
|
- write code once - and it'll work everywhere
|
||||||
|
- ideal for the unification of the network infrastructure code across company
|
||||||
|
- Built-in protocols: plain TCP/UDP, SNTP, HTTP, MQTT, Websocket, and other
|
||||||
- Asynchronous DNS resolver
|
- Asynchronous DNS resolver
|
||||||
- Tiny static and run-time footprint
|
- Tiny static and run-time footprint
|
||||||
- Source code is both ISO C and ISO C++ compliant
|
- Source code is both ISO C and ISO C++ compliant
|
||||||
- Works with any network stack with socket API, like LwIP or FreeRTOS-Plus-TCP
|
- Easy to integrate: just copy [mongoose.c](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.c)
|
||||||
- Very easy to integrate: just copy `mongoose.c` and `mongoose.h` files to your build tree
|
and [mongoose.h](https://raw.githubusercontent.com/cesanta/mongoose/master/mongoose.h) files to your source tree
|
||||||
- Detailed [documentation](https://mongoose.ws/documentation/) and
|
- Built-in TCP/IP stack with drivers for bare metal or RTOS systems
|
||||||
[tutorials](https://mongoose.ws/tutorials/)
|
- Available drivers: STM32F, STM32H; NXP RT1xxx; TI TM4C; Microchip SAME54; Wiznet W5500
|
||||||
|
- A complete Web device dashboard on bare metal ST Nucleo boards is only 6 files
|
||||||
|
- For comparison, a CubeIDE generated HTTP example is 400+ files
|
||||||
|
- Can run on top of an existing TCP/IP stack with BSD API, e.g. lwIP, Zephyr, Azure, etc
|
||||||
|
- Built-in TLS 1.3 ECC stack. Also can use external TLS libraries - mbedTLS, OpenSSL, or other
|
||||||
|
- Does not depend on any other software to implement networking
|
||||||
|
- Built-in firmware updates for STM32 H5, STM32 H7
|
||||||
|
|
||||||
|
See https://mongoose.ws/ for complete documentation, videos, case studies, etc.
|
||||||
|
|
||||||
# Commercial use
|
## Usage Examples
|
||||||
|
|
||||||
|
Below are quick snippets that should give an idea how simple the API is and
|
||||||
|
how easy it is to create applications with it.
|
||||||
|
|
||||||
|
Create a simple web server that serves a directory. The behavior of the
|
||||||
|
HTTP server is specified by its event handler function:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "mongoose.h" // To build, run: cc main.c mongoose.c
|
||||||
|
|
||||||
|
// HTTP server event handler function
|
||||||
|
void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
struct mg_http_serve_opts opts = { .root_dir = "./web_root/" };
|
||||||
|
mg_http_serve_dir(c, hm, &opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr; // Declare event manager
|
||||||
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
|
mg_http_listen(&mgr, "http://0.0.0.0:8000", ev_handler, NULL); // Setup listener
|
||||||
|
for (;;) { // Run an infinite event loop
|
||||||
|
mg_mgr_poll(&mgr, 1000);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
HTTP server implements a REST API that returns current time. JSON formatting:
|
||||||
|
```c
|
||||||
|
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
if (mg_http_match_uri(hm, "/api/time/get")) {
|
||||||
|
mg_http_reply(c, 200, "", "{%m:%lu}\n", MG_ESC("time"), time(NULL));
|
||||||
|
} else {
|
||||||
|
mg_http_reply(c, 500, "", "{%m:%m}\n", MG_ESC("error"), MG_ESC("Unsupported URI"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
MQTT client that subscribes to a topic `device1/rx` and
|
||||||
|
echoes incoming messages to `device1/tx`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static const char *s_mqtt_url = "mqtt://broker.hivemq.com:1883";
|
||||||
|
static struct mg_connection *s_mqtt_conn = NULL;
|
||||||
|
|
||||||
|
// MQTT connection event handler function
|
||||||
|
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_OPEN) {
|
||||||
|
MG_INFO(("%lu created, connecting to %s ...", c->id, s_mqtt_url));
|
||||||
|
} else if (ev == MG_EV_MQTT_OPEN) {
|
||||||
|
struct mg_mqtt_opts opts = {.qos = 1, .topic = mg_str("device1/rx")};
|
||||||
|
mg_mqtt_sub(c, &opts);
|
||||||
|
MG_INFO(("%lu connected, subscribing to %s", c->id, opts.topic.buf));
|
||||||
|
} else if (ev == MG_EV_MQTT_MSG) {
|
||||||
|
char response[100];
|
||||||
|
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
|
||||||
|
struct mg_mqtt_opts opts = {.qos = 1, .topic = mg_str("device1/tx")};
|
||||||
|
mg_snprintf(response, sizeof(response), "Received [%.*s] / [%.*s]",
|
||||||
|
mm->topic.len, mm->topic.buf, mm->data.len, mm->data.buf);
|
||||||
|
opts.message = mg_str(response);
|
||||||
|
mg_mqtt_pub(c, &opts);
|
||||||
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
|
MG_INFO(("%u closing", c->id));
|
||||||
|
s_mqtt_conn = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconnection timer function. If we get disconnected, reconnect again
|
||||||
|
static void timer_fn(void *arg) {
|
||||||
|
struct mg_mgr *mgr = (struct mg_mgr *) arg;
|
||||||
|
if (s_mqtt_conn == NULL) {
|
||||||
|
struct mg_mqtt_opts opts = {.clean = true};
|
||||||
|
s_mqtt_conn = mg_mqtt_connect(mgr, s_mqtt_url, &opts, ev_handler, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
struct mg_mgr mgr; // Mongoose event manager. Holds all connections
|
||||||
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
|
mg_timer_add(&mgr, 3000, MG_TIMER_REPEAT | MG_TIMER_RUN_NOW, timer_fn, &mgr);
|
||||||
|
for (;;) {
|
||||||
|
mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commercial use
|
||||||
- Mongoose is used by hundreds of businesses, from Fortune500 giants like
|
- Mongoose is used by hundreds of businesses, from Fortune500 giants like
|
||||||
Siemens, Schneider Electric, Broadcom, Bosch, Google, Samsung, Qualcomm, Caterpillar to the small businesses
|
Siemens, Schneider Electric, Broadcom, Bosch, Google, Samsung, Qualcomm, Caterpillar to the small businesses
|
||||||
- Used to solve a wide range of business needs, like implementing Web UI
|
- Used to solve a wide range of business needs, like implementing Web UI
|
||||||
@@ -35,11 +140,11 @@ robust, and easy. Features include:
|
|||||||
- See [Case Studies](https://mongoose.ws/case-studies/) from our respected
|
- See [Case Studies](https://mongoose.ws/case-studies/) from our respected
|
||||||
customers like [Schneider Electric](https://mongoose.ws/case-studies/schneider-electric/) (industrial automation), [Broadcom](https://mongoose.ws/case-studies/broadcom/) (semiconductors), [Pilz](https://mongoose.ws/case-studies/pilz/) (industrial automation), and others
|
customers like [Schneider Electric](https://mongoose.ws/case-studies/schneider-electric/) (industrial automation), [Broadcom](https://mongoose.ws/case-studies/broadcom/) (semiconductors), [Pilz](https://mongoose.ws/case-studies/pilz/) (industrial automation), and others
|
||||||
- See [Testimonials](https://mongoose.ws/testimonials/) from engineers that integrated Mongoose in their commercial products
|
- See [Testimonials](https://mongoose.ws/testimonials/) from engineers that integrated Mongoose in their commercial products
|
||||||
- We provide [Evaluation and Commercial licensing](https://mongoose.ws/licensing/), [support](https://mongoose.ws/support/), consultancy and integration
|
- We provide [Evaluation and Commercial licensing](https://mongoose.ws/licensing/), [support](https://mongoose.ws/support/), consultancy and [integration
|
||||||
assistance - don't hesitate to [contact us](https://mongoose.ws/contact/)
|
services](https://mongoose.ws/integration/) - don't hesitate to [contact us](https://mongoose.ws/contact/)
|
||||||
|
|
||||||
|
|
||||||
# Security
|
## Security
|
||||||
|
|
||||||
We take security seriously:
|
We take security seriously:
|
||||||
1. Mongoose repository runs a
|
1. Mongoose repository runs a
|
||||||
@@ -65,7 +170,7 @@ We take security seriously:
|
|||||||
of which we get notified and in case of any issue, act similar to (3).
|
of which we get notified and in case of any issue, act similar to (3).
|
||||||
|
|
||||||
|
|
||||||
# Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are welcome! Please follow the guidelines below:
|
Contributions are welcome! Please follow the guidelines below:
|
||||||
|
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 1034 239" style="enable-background:new 0 0 1034 239;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#576174;}
|
|
||||||
.st1{fill:#FFFFFF;}
|
|
||||||
.st2{font-family:'Courier-Bold';}
|
|
||||||
.st3{font-size:16.7604px;}
|
|
||||||
.st4{fill:#00983A;}
|
|
||||||
.st5{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st6{fill:#45CFFF;}
|
|
||||||
.st7{fill:none;stroke:#A000FF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st8{fill:#A000FF;}
|
|
||||||
.st9{fill:none;stroke:#FFDE00;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st10{fill:#FFDE00;}
|
|
||||||
.st11{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st12{fill:#EA5B0C;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M485.3,224.22H8.5c-4.7,0-8.5-3.8-8.5-8.5V27.22c0-4.7,3.8-8.5,8.5-8.5h476.8c4.7,0,8.5,3.8,8.5,8.5v188.5
|
|
||||||
C493.8,220.32,490,224.22,485.3,224.22z"/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 21.294 60.1267)" class="st1 st2 st3">struct mg_str k,v,s = mg_str(”a=333, b=777”);</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 21.294 136.2499)" class="st1 st2 st3">mg_commalist(&s, &k, &v); </text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 21.294 197.1485)" class="st1 st2 st3">mg_commalist(&s, &k, &v); </text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 291.5096 140.18)" class="st4 st2 st3">// 1st call</text>
|
|
||||||
<text transform="matrix(1 0 0 1 291.5096 199.8101)" class="st4 st2 st3">// 2nd call</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st5" points="336.4,64.52 336.4,68.52 317.8,68.52 317.8,64.52 "/>
|
|
||||||
<g>
|
|
||||||
<path class="st5" d="M122.3,59.62"/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st5" points="327.5,76.82 327.6,94.02 203.3,94.02 203.3,116.12 "/>
|
|
||||||
<path class="st6" d="M331,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C329.5,74.42,331,75.92,331,77.62z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st6" d="M203.2,114.92c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C206.5,116.32,205,114.92,203.2,114.92z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st7" points="407.4,64.52 407.4,68.52 388.8,68.52 388.8,64.52 "/>
|
|
||||||
<g>
|
|
||||||
<path class="st5" d="M193.4,59.62"/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st7" points="398.6,76.82 398.6,149.02 203.4,149.02 203.4,177.12 "/>
|
|
||||||
<path class="st8" d="M402,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C400.6,74.42,402,75.92,402,77.62z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st8" d="M203.2,175.42c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C206.5,176.82,205,175.42,203.2,175.42z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st9" points="440.8,64.52 440.8,68.52 414.2,68.52 414.2,64.52 "/>
|
|
||||||
<g>
|
|
||||||
<path class="st5" d="M218.8,59.62"/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st9" points="428,76.82 428,163.02 245.7,163.02 245.7,176.12 "/>
|
|
||||||
<path class="st10" d="M431.4,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C430,74.42,431.4,75.92,431.4,77.62z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st10" d="M245.4,175.42c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C248.7,176.82,247.2,175.42,245.4,175.42z
|
|
||||||
"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st11" points="372.8,64.52 372.8,68.52 343.2,68.52 343.2,64.52 "/>
|
|
||||||
<g>
|
|
||||||
<path class="st5" d="M164.7,59.62"/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st11" points="358.3,76.62 358.3,104.82 245.7,105.02 245.7,116.12 "/>
|
|
||||||
<path class="st12" d="M361.4,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C359.9,74.42,361.4,75.92,361.4,77.62z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st12" d="M245.7,114.92c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C248.9,116.32,247.4,114.92,245.7,114.92z
|
|
||||||
"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1,48 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 1034 158.07" style="enable-background:new 0 0 1034 158.07;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#67748A;}
|
|
||||||
.st1{fill:#FFFFFF;}
|
|
||||||
.st2{font-family:'Courier-Bold';}
|
|
||||||
.st3{font-size:16.7604px;}
|
|
||||||
.st4{fill:none;stroke:#45CFFF;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st5{fill:#45CFFF;}
|
|
||||||
.st6{font-family:'Arial-BoldMT';}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M516.7,39.8v56.33c0,4.17-3.8,7.54-8.5,7.54H14.6H8.5c-4.7,0-8.5-3.37-8.5-7.54V39.8c0-4.17,3.8-7.54,8.5-7.54
|
|
||||||
h499.7C512.9,32.26,516.7,35.63,516.7,39.8z"/>
|
|
||||||
<text transform="matrix(1 0 0 1 51.0379 69.3318)" class="st1 st2 st3">GET /test \n\nGET /test \n\nGET test \n\n</text>
|
|
||||||
<g>
|
|
||||||
<polyline class="st4" points="189.5,76.47 189.5,80.47 51.8,80.47 51.8,76.47 "/>
|
|
||||||
<polyline class="st4" points="331.3,76.47 331.3,80.47 195.6,80.47 195.6,76.47 "/>
|
|
||||||
<polyline class="st4" points="462.7,76.47 462.7,80.47 336.9,80.47 336.9,76.47 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 78.8909 148.8896)" class="st5 st6 st3">1st request</text>
|
|
||||||
<g>
|
|
||||||
<line class="st4" x1="120.2" y1="93.57" x2="120.3" y2="129.57"/>
|
|
||||||
<path class="st5" d="M117.1,92.57c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C118.5,95.77,117.1,94.37,117.1,92.57z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 217.3594 148.8891)" class="st5 st6 st3">2nd request </text>
|
|
||||||
<g>
|
|
||||||
<line class="st4" x1="263.8" y1="93.57" x2="263.9" y2="129.57"/>
|
|
||||||
<path class="st5" d="M260.7,92.57c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C262.1,95.77,260.7,94.37,260.7,92.57z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 354.7297 148.8896)" class="st5 st6 st3">3rd request </text>
|
|
||||||
<g>
|
|
||||||
<line class="st4" x1="399.4" y1="93.57" x2="399.4" y2="129.57"/>
|
|
||||||
<path class="st5" d="M396.2,92.57c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C397.7,95.77,396.2,94.37,396.2,92.57z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,113 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 1035.4 429.9" style="enable-background:new 0 0 1035.4 429.9;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#576174;}
|
|
||||||
.st1{fill:#67748A;}
|
|
||||||
.st2{fill:none;stroke:#87005B;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st3{fill:#87005B;}
|
|
||||||
.st4{fill:#FFFFFF;}
|
|
||||||
.st5{font-family:'Courier-Bold';}
|
|
||||||
.st6{font-size:16.7604px;}
|
|
||||||
.st7{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st8{fill:#EA5B0C;}
|
|
||||||
.st9{fill:none;stroke:#CA70FF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st10{fill:#CA70FF;}
|
|
||||||
.st11{fill:none;stroke:#FFDE00;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st12{fill:#FFDE00;}
|
|
||||||
.st13{fill:none;stroke:#00CF4F;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st14{fill:#00CF4F;}
|
|
||||||
.st15{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st16{fill:none;stroke:#EA5B0C;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st17{font-family:'Arial-BoldMT';}
|
|
||||||
.st18{font-size:24px;}
|
|
||||||
.st19{fill:#45CFFF;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M755.8,391.8H8.5c-4.7,0-8.5-3.8-8.5-8.5v-153c0-4.7,3.8-8.5,8.5-8.5h747.3c4.7,0,8.5,3.8,8.5,8.5v153
|
|
||||||
C764.3,388,760.5,391.8,755.8,391.8z"/>
|
|
||||||
<path class="st1" d="M996.9,261.5h-427c-4.7,0-8.5-3.8-8.5-8.5V81.2c0-4.7,3.8-8.5,8.5-8.5h427c4.7,0,8.5,3.8,8.5,8.5V253
|
|
||||||
C1005.4,257.7,1001.5,261.5,996.9,261.5z"/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st2" points="598.1,238.2 598.1,242.3 787.7,242.3 787.7,238.2 "/>
|
|
||||||
<g>
|
|
||||||
<line class="st2" x1="689.3" y1="342.2" x2="276.4" y2="343.3"/>
|
|
||||||
<g>
|
|
||||||
<line class="st2" x1="689.4" y1="253.3" x2="689.4" y2="342.1"/>
|
|
||||||
<path class="st3" d="M689.4,249.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2l0,0
|
|
||||||
C686.1,250.7,687.6,249.3,689.4,249.3z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st3" d="M274.2,340.4c1.8,0,3.2,1.4,3.3,3.2s-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2l0,0
|
|
||||||
C270.9,341.8,272.4,340.4,274.2,340.4z"/>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 26.0923 262.5192)" class="st4 st5 st6">struct mg_http_message {</text>
|
|
||||||
<text transform="matrix(1 0 0 1 45.542 286.2874)" class="st4 st5 st6">struct mg_str method; uri, query, proto; </text>
|
|
||||||
<text transform="matrix(1 0 0 1 45.542 306.3874)" class="st4 st5 st6">struct mg_http_header headers[MG_MAX_HTTP_HEADERS];</text>
|
|
||||||
<text transform="matrix(1 0 0 1 45.542 326.4874)" class="st4 st5 st6">struct mg_str body;</text>
|
|
||||||
<text transform="matrix(1 0 0 1 45.542 346.5874)" class="st4 st5 st6">struct mg_str message; </text>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st7" points="621.1,89.6 621.1,78.6 215.4,79.7 215.3,269.4 "/>
|
|
||||||
<path class="st8" d="M624.3,90.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C622.8,87.4,624.3,88.8,624.3,90.6z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st8" d="M212.3,269.4c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C213.7,272.6,212.3,271.2,212.3,269.4z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st9" points="597.2,183.6 593.1,183.6 593.1,127.8 597.2,127.8 "/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st9" points="582.4,156.2 575.2,156.2 575,302.8 563.4,302.8 "/>
|
|
||||||
<path class="st10" d="M586.1,156.2c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
|
||||||
C584.7,159.4,586.1,158,586.1,156.2z"/>
|
|
||||||
<path class="st10" d="M564.2,303c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2s1.4,3.2,3.2,3.3l0,0
|
|
||||||
C562.7,306.2,564.2,304.7,564.2,303z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 601.1215 118.1291)" class="st4 st5 st6">POST /foo/bar/baz?aa=b&cc=ddd HTTP/1.1</text>
|
|
||||||
<text transform="matrix(1 0 0 1 601.1215 138.2291)" class="st4 st5 st6">Content-Type: application/json</text>
|
|
||||||
<text transform="matrix(1 0 0 1 601.1215 158.3291)" class="st4 st5 st6">Content-Length: 19</text>
|
|
||||||
<text transform="matrix(1 0 0 1 601.1215 178.4291)" class="st4 st5 st6">Host: reqbin.com</text>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st11" points="712.3,90.6 712.4,67.6 277.8,67.6 279.7,269.3 "/>
|
|
||||||
<path class="st12" d="M715.6,90.8c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C714.1,87.6,715.6,89.1,715.6,90.8z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st12" d="M276.5,269.4c0-1.8,1.4-3.2,3.2-3.3s3.2,1.4,3.3,3.2s-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C278,272.6,276.5,271.2,276.5,269.4z"/>
|
|
||||||
</g>
|
|
||||||
<polyline class="st11" points="771.5,104.3 771.5,100.3 652.7,100.3 652.7,104.3 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st13" points="836.3,90.6 836.3,56.6 342.8,56.6 344.7,268.3 "/>
|
|
||||||
<path class="st14" d="M839.5,90.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C838,87.4,839.5,88.9,839.5,90.6z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st14" d="M341.4,269.3c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C342.9,272.5,341.4,271.1,341.4,269.3z"/>
|
|
||||||
</g>
|
|
||||||
<polyline class="st15" points="981.4,104.2 981.4,100.2 902.6,100.2 902.6,104.2 "/>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 596.891 232.3658)" class="st4 st5 st6">{"success": "true"}</text>
|
|
||||||
<polyline class="st16" points="643.1,104.4 643.1,100.4 599.3,100.4 599.3,104.4 "/>
|
|
||||||
<text transform="matrix(1 0 0 1 9.5506 207.5157)" class="st17 st18">Source Code</text>
|
|
||||||
<text transform="matrix(1 0 0 1 797.0799 32.3923)" class="st17 st18">HTTP message</text>
|
|
||||||
<text transform="matrix(1 0 0 1 26.0924 359.209)" class="st4 st5 st6">};</text>
|
|
||||||
<polyline class="st13" points="894.2,104.2 894.2,100.2 774.4,100.2 774.4,104.2 "/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st15" points="941.3,90.6 941.3,45.6 412.8,45.6 414.7,268.3 "/>
|
|
||||||
<path class="st19" d="M944.5,90.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C943,87.4,944.5,88.9,944.5,90.6z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st19" d="M411.4,269.3c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C412.9,272.5,411.4,271.1,411.4,269.3z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 6.0 KiB |
@@ -1,109 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 1034 663.54" style="enable-background:new 0 0 1034 663.54;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st1{fill:#45CFFF;}
|
|
||||||
.st2{fill:#576174;}
|
|
||||||
.st3{fill:#FFFFFF;}
|
|
||||||
.st4{font-family:'Courier-Bold';}
|
|
||||||
.st5{font-size:16.7604px;}
|
|
||||||
.st6{font-family:'Arial-BoldMT';}
|
|
||||||
.st7{font-size:24px;}
|
|
||||||
.st8{fill:#67748A;}
|
|
||||||
.st9{fill:#8B9CBA;}
|
|
||||||
.st10{fill:none;stroke:#00CF4F;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st11{fill:#00CF4F;}
|
|
||||||
.st12{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st13{fill:#EA5B0C;}
|
|
||||||
.st14{fill:#414857;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st0" points="498.5,624.21 498.5,628.21 447.9,628.21 447.9,624.21 "/>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M491.8,844.81"/>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M473.8,636.11c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
|
||||||
C477.1,637.61,475.6,636.11,473.8,636.11z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st1" d="M296.7,852.71c-1.8,0-3.2,1.3-3.3,3c0,1.7,1.4,3,3.2,3c1.8,0,3.2-1.3,3.3-3l0,0
|
|
||||||
C299.9,854.01,298.5,852.71,296.7,852.71z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st2" d="M584.6,199.01H8.5c-4.7,0-8.5-3.8-8.5-8.5V60.71c0-4.7,3.8-8.5,8.5-8.5h576.1c4.7,0,8.5,3.8,8.5,8.5v129.8
|
|
||||||
C593.1,195.21,589.3,199.01,584.6,199.01z"/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 90.8107)" class="st3 st4 st5">struct mg_http_part part;</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 110.9108)" class="st3 st4 st5">size_t pos = 0;</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 151.1107)" class="st3 st4 st5">pos = mg_http_next_multipart(&hm->body, pos, &part);</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 171.3107)" class="st3 st4 st5">pos = mg_http_next_multipart(&hm->body, pos, &part);</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 1.3738 40.559)" class="st6 st7">Source Code</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st8" d="M685.5,646.41H8.5c-4.7,0-8.5-3.8-8.5-8.5v-362.9c0-4.7,3.8-8.5,8.5-8.5h677c4.7,0,8.5,3.8,8.5,8.5v362.9
|
|
||||||
C694,642.61,690.2,646.41,685.5,646.41z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st9" d="M640.2,629.41H26.3c-4.7,0-8.5-3.8-8.5-8.5v-106.5c0-4.7,3.8-8.5,8.5-8.5h613.9c4.7,0,8.5,3.8,8.5,8.5v106.5
|
|
||||||
C648.7,625.61,644.8,629.41,640.2,629.41z"/>
|
|
||||||
<path class="st9" d="M644,490.91H30.1c-4.7,0-8.5-3.8-8.5-8.5v-106.5c0-4.7,3.8-8.5,8.5-8.5H644c4.7,0,8.5,3.8,8.5,8.5v106.5
|
|
||||||
C652.5,487.11,648.7,490.91,644,490.91z"/>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 0.0299 253.0343)" class="st6 st7">HTTP message</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 302.8107)" class="st3 st4 st5">POST /upload HTTP/1.1 </text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 322.9107)" class="st3 st4 st5">Content-Type: multipart/form-data; boundary="--xyz"</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 363.1107)" class="st3 st4 st5">--xyz</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 383.3107)" class="st3 st4 st5">Content-Disposition: form-data; name="foo"; filename="a.txt"</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 403.4107)" class="st3 st4 st5">Content-Type: text/plain</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 443.6107)" class="st3 st4 st5">hello world</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 483.8107)" class="st3 st4 st5">--xyz---</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 524.0107)" class="st3 st4 st5">Content-Disposition: form-data; name="bar"; filename="b.txt"</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 544.2108)" class="st3 st4 st5">Content-Type: text/plain</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 584.4108)" class="st3 st4 st5">hello world again</text>
|
|
||||||
<text transform="matrix(1 0 0 1 28.7 624.6107)" class="st3 st4 st5">--xyz--</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st10" points="569.5,162.51 574.5,162.51 574.5,176.11 569.5,176.11 "/>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M726.8,392.91"/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st10" points="587.3,169.71 726.7,169.71 726.6,569.31 684.3,569.31 "/>
|
|
||||||
<path class="st11" d="M585,166.41c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
|
||||||
C588.2,167.91,586.8,166.41,585,166.41z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st11" d="M685,566.31c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3l0,0C688,567.61,686.6,566.31,685,566.31z"/>
|
|
||||||
</g>
|
|
||||||
<polyline class="st10" points="657.9,501.61 673.9,501.61 673.9,634.21 657.9,634.21 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st12" points="569.5,143.21 574.5,143.21 574.5,156.81 569.5,156.81 "/>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M726.8,254.61"/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st12" points="587.3,150.41 710.7,150.41 710.6,431.01 684.3,431.01 "/>
|
|
||||||
<path class="st13" d="M585,147.11c-1.8,0-3.2,1.4-3.3,3.2s1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
|
||||||
C588.2,148.61,586.8,147.11,585,147.11z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st13" d="M685,428.01c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3l0,0C688,429.31,686.6,428.01,685,428.01z"/>
|
|
||||||
</g>
|
|
||||||
<polyline class="st12" points="657.9,363.31 673.9,363.31 673.9,495.91 657.9,495.91 "/>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 537.9671 462.1467)" class="st14 st6 st7">Part 1</text>
|
|
||||||
<text transform="matrix(1 0 0 1 537.9671 600.4373)" class="st14 st6 st7">Part 2</text>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 5.5 KiB |
@@ -1,94 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 1034 480.6" style="enable-background:new 0 0 1034 480.6;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#67748A;}
|
|
||||||
.st1{fill:#8B9CBA;}
|
|
||||||
.st2{fill:#FFFFFF;}
|
|
||||||
.st3{font-family:'Courier-Bold';}
|
|
||||||
.st4{font-size:16.7604px;}
|
|
||||||
.st5{fill:#414857;}
|
|
||||||
.st6{font-family:'Arial-BoldMT';}
|
|
||||||
.st7{font-size:30px;}
|
|
||||||
.st8{font-size:24px;}
|
|
||||||
.st9{fill:#576174;}
|
|
||||||
.st10{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st11{fill:#45CFFF;}
|
|
||||||
.st12{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st13{fill:#EA5B0C;}
|
|
||||||
.st14{fill:none;stroke:#EA5B0C;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st15{fill:none;stroke:#FFDE00;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st16{fill:#FFDE00;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M908.4,454.9H272c-4.7,0-8.5-3.8-8.5-8.5V216c0-4.7,3.8-8.5,8.5-8.5h636.4c4.7,0,8.5,3.8,8.5,8.5v230.4
|
|
||||||
C916.9,451.1,913.1,454.9,908.4,454.9z"/>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M898.6,430.8H284.7c-4.7,0-8.5-3.8-8.5-8.5V315.9c0-4.7,3.8-8.5,8.5-8.5h613.9c4.7,0,8.5,3.8,8.5,8.5v106.5
|
|
||||||
C907.1,427,903.3,430.8,898.6,430.8z"/>
|
|
||||||
<text transform="matrix(1 0 0 1 295.3688 243.086)" class="st2 st3 st4">POST /upload HTTP/1.1 </text>
|
|
||||||
<text transform="matrix(1 0 0 1 295.3688 263.186)" class="st2 st3 st4">Content-Type: multipart/form-data: boundary="--xyz"</text>
|
|
||||||
<text transform="matrix(1 0 0 1 295.3688 303.386)" class="st2 st3 st4">--xyz</text>
|
|
||||||
<text transform="matrix(1 0 0 1 295.3688 323.586)" class="st2 st3 st4">Content-Disposition: form-data; name="foo"; filename="a.txt"</text>
|
|
||||||
<text transform="matrix(1 0 0 1 295.3688 343.686)" class="st2 st3 st4">Content-Type: text/plain</text>
|
|
||||||
<text transform="matrix(1 0 0 1 295.3688 383.886)" class="st2 st3 st4">hello world</text>
|
|
||||||
<text transform="matrix(1 0 0 1 295.3688 424.086)" class="st2 st3 st4">--xyz---</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 739.2766 414.2906)" class="st5 st6 st7">HTTP part</text>
|
|
||||||
<text transform="matrix(1 0 0 1 739.2764 193.4305)" class="st6 st8">HTTP message</text>
|
|
||||||
<path class="st9" d="M304.9,198H8.5c-4.7,0-8.5-3.8-8.5-8.5V64.8c0-4.7,3.8-8.5,8.5-8.5H305c4.7,0,8.5,3.8,8.5,8.5v124.7
|
|
||||||
C313.4,194.2,309.6,198,304.9,198z"/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 25.2409 91.1617)" class="st2 st3 st4">struct mg_http_part {</text>
|
|
||||||
<text transform="matrix(1 0 0 1 47.0734 113.7079)" class="st2 st3 st4">struct mg_str name;</text>
|
|
||||||
<text transform="matrix(1 0 0 1 47.0734 133.8079)" class="st2 st3 st4">strucy mg_str filename;</text>
|
|
||||||
<text transform="matrix(1 0 0 1 47.0734 153.9079)" class="st2 st3 st4">struct mg_str body;</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st10" points="237.4,159 237.4,163 185.8,163 185.8,159 "/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st10" points="211.7,348.3 349.5,348.4 349.5,355.6 "/>
|
|
||||||
<g>
|
|
||||||
<line class="st10" x1="211.6" y1="174.4" x2="211.6" y2="348.1"/>
|
|
||||||
<path class="st11" d="M211.6,170.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
|
||||||
C214.8,171.8,213.4,170.3,211.6,170.3z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st11" d="M349.6,353.6c-1.8,0-3.2,1.4-3.3,3.2s1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
|
||||||
C352.8,355.1,351.4,353.6,349.6,353.6z"/>
|
|
||||||
<polyline class="st10" points="237.4,159 237.4,163 185.8,163 185.8,159 "/>
|
|
||||||
<polyline class="st10" points="407.3,371.1 407.3,367.1 293.3,367.1 293.3,371.1 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st12" points="693.7,291.6 693.7,277.7 280.7,278.8 280.5,109.4 248.3,109.4 "/>
|
|
||||||
<path class="st13" d="M696.9,293.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C695.4,290.4,696.9,291.9,696.9,293.6z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st13" d="M243.9,109.5c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C245.3,112.7,243.9,111.3,243.9,109.5z"/>
|
|
||||||
</g>
|
|
||||||
<polyline class="st14" points="707.6,309.2 707.6,305.2 679.9,305.2 679.9,309.2 "/>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 0.8627 37.8099)" class="st6 st8">Source Code</text>
|
|
||||||
<text transform="matrix(1 0 0 1 25.2408 177.7241)" class="st2 st3 st4">};</text>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st15" points="863.8,291.5 863.7,218.6 329.7,218.7 329.6,130.3 298.4,130.3 "/>
|
|
||||||
<path class="st16" d="M867.1,293.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
|
||||||
C865.6,290.3,867.1,291.8,867.1,293.6z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st16" d="M293,130.1c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
|
||||||
C294.4,133.3,293,131.9,293,130.1z"/>
|
|
||||||
</g>
|
|
||||||
<polyline class="st15" points="888.7,309.1 888.7,305.1 838.9,305.1 838.9,309.1 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -1,84 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 1034 331.2" style="enable-background:new 0 0 1034 331.2;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#576174;}
|
|
||||||
.st1{fill:#67748A;}
|
|
||||||
.st2{fill:#FFFFFF;}
|
|
||||||
.st3{font-family:'Courier-Bold';}
|
|
||||||
.st4{font-size:16.7604px;}
|
|
||||||
.st5{font-family:'Arial-BoldMT';}
|
|
||||||
.st6{font-size:24px;}
|
|
||||||
.st7{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st8{fill:#45CFFF;}
|
|
||||||
.st9{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st10{fill:#EA5B0C;}
|
|
||||||
.st11{fill:none;stroke:#EA5B0C;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st12{fill:none;stroke:#00CF4F;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st13{fill:#00CF4F;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M541.43,184.2H8.53c-4.7,0-8.5-3.8-8.5-8.5V54.8c0-4.7,3.8-8.5,8.5-8.5h532.9c4.7,0,8.5,3.8,8.5,8.5v120.9
|
|
||||||
C549.93,180.4,546.13,184.2,541.43,184.2z"/>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M829.23,315.5h-370c-4.7,0-8.5-3.8-8.5-8.5V157c0-4.7,3.8-8.5,8.5-8.5h370c4.7,0,8.5,3.8,8.5,8.5v150
|
|
||||||
C837.83,311.7,833.93,315.5,829.23,315.5z"/>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 490.6096 184.0905)" class="st2 st3 st4">HTTP/1.1 200 OK</text>
|
|
||||||
<text transform="matrix(1 0 0 1 490.6096 204.1905)" class="st2 st3 st4">Content-Length; 13</text>
|
|
||||||
<text transform="matrix(1 0 0 1 490.6096 224.2905)" class="st2 st3 st4">X-Header-1: additional value 1</text>
|
|
||||||
<text transform="matrix(1 0 0 1 490.6096 244.3905)" class="st2 st3 st4">X-Header-2: additional value 2</text>
|
|
||||||
<text transform="matrix(1 0 0 1 490.8657 293.1559)" class="st2 st3 st4">Hello, world!</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 660.5036 137.3383)" class="st5 st6">HTTP message</text>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 20.7331 85.1617)" class="st2 st3 st4">mg_http_reply(c, 200</text>
|
|
||||||
<text transform="matrix(1 0 0 1 159.5657 113.7079)" class="st2 st3 st4">"X-Header-1: additional value 1\r\n"</text>
|
|
||||||
<text transform="matrix(1 0 0 1 159.5657 133.8079)" class="st2 st3 st4">"X-Header-2: additional value 2\r\n",</text>
|
|
||||||
<text transform="matrix(1 0 0 1 159.5657 153.9079)" class="st2 st3 st4">"Hello, %s!", "world");</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st7" points="362.93,159 362.93,163 167.33,163 167.33,159 "/>
|
|
||||||
<g>
|
|
||||||
<polyline class="st7" points="265.93,256.6 552.13,256.7 552.13,264.4 "/>
|
|
||||||
<g>
|
|
||||||
<line class="st7" x1="265.83" y1="174.4" x2="265.83" y2="256.6"/>
|
|
||||||
<path class="st8" d="M265.83,170.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
|
||||||
C269.03,171.8,267.53,170.3,265.83,170.3z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st8" d="M552.23,261.6c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
|
||||||
C555.43,263.1,554.03,261.6,552.23,261.6z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st9" points="206.33,53.6 206.43,37.6 596.43,38.7 596.53,161.3 "/>
|
|
||||||
<path class="st10" d="M203.23,54.6c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2c0-1.8-1.4-3.2-3.2-3.3l0,0
|
|
||||||
C204.63,51.4,203.23,52.8,203.23,54.6z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st10" d="M599.83,164c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
|
||||||
C598.33,167.2,599.83,165.8,599.83,164z"/>
|
|
||||||
</g>
|
|
||||||
<polyline class="st11" points="192.43,69.2 192.43,65.2 220.23,65.2 220.23,69.2 "/>
|
|
||||||
</g>
|
|
||||||
<text transform="matrix(1 0 0 1 -1.917133e-04 35.0037)" class="st5 st6">Source Code</text>
|
|
||||||
<g>
|
|
||||||
<polyline class="st12" points="160.13,135.9 156.03,135.9 156.03,100.1 160.13,100.1 "/>
|
|
||||||
<g>
|
|
||||||
<line class="st12" x1="123.93" y1="231" x2="469.73" y2="231"/>
|
|
||||||
<polyline class="st12" points="144.73,117.2 123.83,117.2 123.73,230.8 "/>
|
|
||||||
<path class="st13" d="M147.83,117.2c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
|
||||||
C146.33,120.4,147.83,119,147.83,117.2z"/>
|
|
||||||
<path class="st13" d="M474.83,230.8c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
|
||||||
C473.43,234,474.83,232.5,474.83,230.8z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<polyline class="st7" points="489.03,279.6 489.03,275.6 620.63,275.6 620.63,279.6 "/>
|
|
||||||
<polyline class="st12" points="487.63,248.3 483.63,248.3 483.63,211.5 487.63,211.5 "/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.4 KiB |
@@ -1,124 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 869.6 185.67" style="enable-background:new 0 0 869.6 185.67;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{font-family:'Arial-BoldMT';}
|
|
||||||
.st1{font-size:24px;}
|
|
||||||
.st2{opacity:0.2;fill:#00983A;enable-background:new ;}
|
|
||||||
.st3{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st4{fill:#00983A;}
|
|
||||||
.st5{fill:none;stroke:#576174;stroke-miterlimit:10;}
|
|
||||||
.st6{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st7{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st8{font-family:'Courier-Bold';}
|
|
||||||
.st9{font-size:16.7604px;}
|
|
||||||
.st10{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st11{fill:#576174;}
|
|
||||||
.st12{font-family:'Courier';}
|
|
||||||
.st13{fill:none;}
|
|
||||||
.st14{fill:#7A8387;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 1.0956 32.4549)" class="st0 st1">Memory</text>
|
|
||||||
<polyline class="st2" points="424.58,115.4 219.88,115.4 219.88,90.7 424.58,90.7 "/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st3" points="458.98,115.4 218.98,115.4 218.98,90.7 458.98,90.7 "/>
|
|
||||||
<polyline class="st4" points="219.18,115.1 2.98,115.1 2.98,91.3 219.18,91.3 "/>
|
|
||||||
<line class="st3" x1="2.98" y1="69.2" x2="2.98" y2="130.4"/>
|
|
||||||
<line class="st5" x1="219.78" y1="69.2" x2="219.78" y2="130.4"/>
|
|
||||||
<line class="st5" x1="425.28" y1="69.2" x2="425.28" y2="130.4"/>
|
|
||||||
<path class="st6" d="M458.98,115.4"/>
|
|
||||||
<path class="st7" d="M33.98,114.6"/>
|
|
||||||
<path class="st7" d="M33.98,90.9"/>
|
|
||||||
<path class="st7" d="M2.98,90.7h216.8v24.9l-216.8-0.2C2.98,115.4,3.18,90.7,2.98,90.7z"/>
|
|
||||||
<line class="st3" x1="425.18" y1="90.8" x2="425.18" y2="115.3"/>
|
|
||||||
<path class="st6" d="M251.98,115.6"/>
|
|
||||||
<path class="st6" d="M251.98,91.9"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 -2.290726e-04 175.3858)" class="st4 st8 st9">buf</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st10" x1="2.68" y1="158.2" x2="2.68" y2="137.2"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st4" points="0.28,137.6 5.08,137.6 2.68,135.1 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 214.6515 175.3858)" class="st4 st8 st9">len</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st10" x1="219.78" y1="158.2" x2="219.78" y2="137.2"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st4" points="217.38,137.6 222.18,137.6 219.78,135.1 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 421.6186 175.3858)" class="st4 st8 st9">size</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st10" x1="425.38" y1="158.2" x2="425.38" y2="137.2"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st4" points="422.98,137.6 427.78,137.6 425.38,135.1 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 93.1143 69.4458)" class="st11 st12 st9">data</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 273.8231 69.4458)" class="st11 st12 st9">free space</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st5" x1="132.98" y1="76.3" x2="13.98" y2="76.3"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st11" points="14.28,78.7 14.28,73.8 11.88,76.3 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<line class="st13" x1="123.88" y1="76.3" x2="210.88" y2="76.3"/>
|
|
||||||
<g>
|
|
||||||
<line class="st5" x1="123.88" y1="76.3" x2="208.78" y2="76.3"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st11" points="208.48,73.8 208.48,78.7 210.88,76.3 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st5" x1="320.38" y1="76.3" x2="414.28" y2="76.3"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st14" points="413.98,73.8 413.98,78.7 416.38,76.3 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st5" x1="322.28" y1="76.3" x2="233.28" y2="76.3"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st14" points="233.68,78.7 233.68,73.8 231.18,76.3 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 4.1 KiB |
@@ -1,52 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 869 124.66" style="enable-background:new 0 0 869 124.66;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st1{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st2{fill:#00983A;}
|
|
||||||
.st3{font-family:'Courier-Bold';}
|
|
||||||
.st4{font-size:16.7604px;}
|
|
||||||
.st5{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st6{fill:#7A8387;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st0" points="830.92,78.4 5.52,78.4 5.52,53.7 830.92,53.6 "/>
|
|
||||||
<line class="st1" x1="5.52" y1="32.2" x2="5.52" y2="93.4"/>
|
|
||||||
<path class="st0" d="M830.92,78.4"/>
|
|
||||||
<line class="st1" x1="36.52" y1="53.9" x2="36.52" y2="77.6"/>
|
|
||||||
<line class="st1" x1="68.92" y1="53.9" x2="68.92" y2="77.6"/>
|
|
||||||
<line class="st1" x1="101.42" y1="53.9" x2="101.42" y2="77.6"/>
|
|
||||||
<line class="st1" x1="133.72" y1="53.9" x2="133.72" y2="77.6"/>
|
|
||||||
<line class="st1" x1="166.22" y1="53.9" x2="166.22" y2="77.6"/>
|
|
||||||
<line class="st1" x1="198.52" y1="54.6" x2="198.52" y2="78.3"/>
|
|
||||||
<line class="st1" x1="230.92" y1="54.6" x2="230.92" y2="78.3"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 59.1908 40.8585)" class="st2 st3 st4">buf=NULL, len=0, size=0 </text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 -1.811981e-04 109.9024)" class="st2 st3 st4">0</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st5" x1="46.72" y1="37.7" x2="17.72" y2="37.7"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st2" points="18.12,40.1 18.12,35.2 15.62,37.7 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st6" d="M511.52,66.4c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S511.52,65.5,511.52,66.4z"/>
|
|
||||||
<path class="st6" d="M525.32,66.4c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S525.32,65.5,525.32,66.4z"/>
|
|
||||||
<path class="st6" d="M539.02,66.4c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S539.02,65.5,539.02,66.4z"/>
|
|
||||||
<path class="st6" d="M552.82,66.4c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S552.82,65.5,552.82,66.4z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 2.3 KiB |
@@ -1,185 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 869.6 127.5" style="enable-background:new 0 0 869.6 127.5;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{opacity:0.2;fill:#00983A;enable-background:new ;}
|
|
||||||
.st1{fill:#F2F3F3;}
|
|
||||||
.st2{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st3{fill:#00983A;}
|
|
||||||
.st4{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st5{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st6{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:square;stroke-linejoin:round;}
|
|
||||||
.st7{font-family:'Courier-Bold';}
|
|
||||||
.st8{font-size:16.7604px;}
|
|
||||||
.st9{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st10{fill:#7A8387;}
|
|
||||||
.st11{fill:#576174;}
|
|
||||||
.st12{fill:none;stroke:#576174;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st13{fill:none;stroke:#7A8387;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st14{fill:#333A45;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st0" points="577.2,72.8 282.4,72.8 282.4,48 577.2,48 "/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st1" points="122.6,72.8 5.9,72.8 5.9,48 122.6,48 "/>
|
|
||||||
<polyline class="st2" points="831.51,72.8 5.5,72.8 5.5,48 831.51,48 "/>
|
|
||||||
<polyline class="st3" points="282.7,72.5 122.5,72.5 122.5,47.7 282.7,47.7 "/>
|
|
||||||
<line class="st2" x1="122.5" y1="26.6" x2="122.5" y2="87.8"/>
|
|
||||||
<line class="st2" x1="283.3" y1="26.6" x2="283.3" y2="87.8"/>
|
|
||||||
<line class="st2" x1="576.8" y1="26.6" x2="576.8" y2="87.8"/>
|
|
||||||
<path class="st4" d="M831.51,72.8"/>
|
|
||||||
<line class="st5" x1="153.5" y1="48.3" x2="153.5" y2="72"/>
|
|
||||||
<line class="st2" x1="36.5" y1="48.3" x2="36.5" y2="72"/>
|
|
||||||
<line class="st2" x1="67.6" y1="48.3" x2="67.6" y2="72"/>
|
|
||||||
<line class="st5" x1="186" y1="48.3" x2="186" y2="72"/>
|
|
||||||
<line class="st5" x1="218.4" y1="48.3" x2="218.4" y2="72"/>
|
|
||||||
<line class="st5" x1="250.9" y1="48.3" x2="250.9" y2="72"/>
|
|
||||||
<line class="st2" x1="315.9" y1="48.3" x2="315.9" y2="72"/>
|
|
||||||
<line class="st2" x1="348.4" y1="48.3" x2="348.4" y2="72"/>
|
|
||||||
<line class="st2" x1="381.2" y1="48.3" x2="381.2" y2="72"/>
|
|
||||||
<line class="st2" x1="413.8" y1="48.3" x2="413.8" y2="72"/>
|
|
||||||
<line class="st2" x1="446.3" y1="48.3" x2="446.3" y2="72"/>
|
|
||||||
<line class="st2" x1="478.9" y1="48.3" x2="478.9" y2="72"/>
|
|
||||||
<line class="st5" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
|
||||||
<line class="st2" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
|
||||||
<line class="st5" x1="544.01" y1="48.3" x2="544.01" y2="72"/>
|
|
||||||
<line class="st2" x1="544.1" y1="48.3" x2="544.1" y2="72"/>
|
|
||||||
<line class="st6" x1="283.3" y1="73" x2="122.5" y2="72.8"/>
|
|
||||||
<line class="st6" x1="122.5" y1="48" x2="283.3" y2="48.1"/>
|
|
||||||
<path class="st4" d="M385.5,73"/>
|
|
||||||
<path class="st4" d="M385.5,49.3"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 127.5176 105.8013)" class="st3 st7 st8">buf</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st9" x1="122.2" y1="105.6" x2="122.2" y2="94.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st3" points="119.8,94.9 124.6,94.9 122.2,92.5 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 286.6495 105.8008)" class="st3 st7 st8">len=5</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st9" x1="283.3" y1="105.6" x2="283.3" y2="94.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st3" points="280.9,94.9 285.8,94.9 283.3,92.5 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 581.4624 105.8013)" class="st3 st7 st8">size=16</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st9" x1="576.9" y1="105.6" x2="576.9" y2="94.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st3" points="574.51,94.9 579.4,94.9 576.9,92.5 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st10" d="M687.51,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S687.51,59.9,687.51,60.7z"/>
|
|
||||||
<path class="st10" d="M701.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S701.2,59.9,701.2,60.7z"/>
|
|
||||||
<path class="st10" d="M714.9,60.7c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
C714.2,59.1,714.9,59.9,714.9,60.7z"/>
|
|
||||||
<path class="st10" d="M728.7,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
C728.01,59.1,728.7,59.9,728.7,60.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st10" d="M82.8,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S82.8,59.9,82.8,60.7z"/>
|
|
||||||
<path class="st10" d="M96.5,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6C95.8,59.1,96.5,59.9,96.5,60.7
|
|
||||||
z"/>
|
|
||||||
<path class="st10" d="M110.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S110.2,59.9,110.2,60.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 180.6541 26.8123)" class="st11 st7 st8">data</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 387.363 26.8123)" class="st10 st7 st8">free space</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st12" x1="272.2" y1="33.6" x2="133.5" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st11" points="271.9,36.2 273.5,33.6 271.9,31.1 271.8,31.1 271.8,36.2 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st11" points="133.8,36.1 133.8,31.2 131.4,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st13" x1="563.7" y1="33.6" x2="295.9" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st10" points="563.4,36.1 563.4,31.2 565.8,33.6 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st10" points="296.2,36.1 296.2,31.2 293.7,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 615.4679 25.1898)" class="st10 st7 st8">non-allocated space</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st13" x1="593.7" y1="33.6" x2="829.7" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st10" points="829.4,31.2 829.4,36.1 831.8,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st13" x1="678.7" y1="33.6" x2="589.7" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st10" points="590.01,36.1 590.01,31.2 587.6,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 133.1212 64.9593)" class="st14 st7 st8">h</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 165.1564 64.9593)" class="st14 st7 st8">e</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 196.8744 64.9593)" class="st14 st7 st8">l</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 229.8611 64.9593)" class="st14 st7 st8">l</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 262.2135 64.9593)" class="st14 st7 st8">o</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 1.811981e-04 105.8011)" class="st3 st7 st8">0</text>
|
|
||||||
</g>
|
|
||||||
<line class="st2" x1="5.5" y1="26.4" x2="5.5" y2="87.6"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 7.1 KiB |
@@ -1,347 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 869.6 247.73" style="enable-background:new 0 0 869.6 247.73;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{opacity:0.2;fill:#00983A;enable-background:new ;}
|
|
||||||
.st1{fill:#00983A;}
|
|
||||||
.st2{fill:#FF80A4;}
|
|
||||||
.st3{fill:#F2F3F3;}
|
|
||||||
.st4{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st5{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st6{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st7{fill:none;stroke:#576174;stroke-width:1.2;stroke-linejoin:round;}
|
|
||||||
.st8{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:square;stroke-linejoin:round;}
|
|
||||||
.st9{font-family:'Courier-Bold';}
|
|
||||||
.st10{font-size:16.7604px;}
|
|
||||||
.st11{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st12{fill:#7A8387;}
|
|
||||||
.st13{fill:#576174;}
|
|
||||||
.st14{fill:none;stroke:#576174;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st15{fill:none;stroke:#7A8387;stroke-linecap:round;stroke-linejoin:round;}
|
|
||||||
.st16{fill:#333A45;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st0" points="577.2,72.8 282.4,72.8 282.4,48 577.2,48 "/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<rect x="250.9" y="47.7" class="st1" width="32.4" height="24.8"/>
|
|
||||||
<rect x="153.5" y="47.7" class="st2" width="97.3" height="24.8"/>
|
|
||||||
<polyline class="st3" points="122.6,72.8 5.9,72.8 5.9,48 122.6,48 "/>
|
|
||||||
<polyline class="st4" points="831.51,72.8 5.5,72.8 5.5,48 831.51,48 "/>
|
|
||||||
<rect x="122.5" y="47.7" class="st1" width="31" height="24.8"/>
|
|
||||||
<line class="st4" x1="122.5" y1="26.6" x2="122.5" y2="87.8"/>
|
|
||||||
<line class="st4" x1="576.8" y1="26.6" x2="576.8" y2="87.8"/>
|
|
||||||
<path class="st5" d="M831.51,72.8"/>
|
|
||||||
<line class="st6" x1="153.5" y1="48.3" x2="153.5" y2="72"/>
|
|
||||||
<line class="st4" x1="36.5" y1="48.3" x2="36.5" y2="72"/>
|
|
||||||
<line class="st4" x1="67.6" y1="48.3" x2="67.6" y2="72"/>
|
|
||||||
<line class="st6" x1="186" y1="48.3" x2="186" y2="72"/>
|
|
||||||
<line class="st6" x1="218.4" y1="48.3" x2="218.4" y2="72"/>
|
|
||||||
<line class="st7" x1="250.9" y1="73" x2="250.81" y2="47.7"/>
|
|
||||||
<line class="st4" x1="315.9" y1="48.3" x2="315.9" y2="72"/>
|
|
||||||
<line class="st4" x1="348.4" y1="48.3" x2="348.4" y2="72"/>
|
|
||||||
<line class="st4" x1="381.2" y1="48.3" x2="381.2" y2="72"/>
|
|
||||||
<line class="st4" x1="413.8" y1="48.3" x2="413.8" y2="72"/>
|
|
||||||
<line class="st4" x1="446.3" y1="48.3" x2="446.3" y2="72"/>
|
|
||||||
<line class="st4" x1="478.9" y1="48.3" x2="478.9" y2="72"/>
|
|
||||||
<line class="st6" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
|
||||||
<line class="st4" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
|
||||||
<line class="st6" x1="544.01" y1="48.3" x2="544.01" y2="72"/>
|
|
||||||
<line class="st4" x1="544.1" y1="48.3" x2="544.1" y2="72"/>
|
|
||||||
<line class="st8" x1="283.3" y1="73" x2="122.5" y2="72.8"/>
|
|
||||||
<line class="st8" x1="122.5" y1="48" x2="283.3" y2="48.1"/>
|
|
||||||
<path class="st5" d="M385.5,73"/>
|
|
||||||
<path class="st5" d="M385.5,49.3"/>
|
|
||||||
<line class="st4" x1="283.3" y1="26.6" x2="283.3" y2="87.8"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 127.5176 105.8013)" class="st1 st9 st10">buf</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st11" x1="122.2" y1="105.6" x2="122.2" y2="94.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st1" points="119.8,94.9 124.6,94.9 122.2,92.5 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 286.6495 105.8008)" class="st1 st9 st10">len=5</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st11" x1="283.3" y1="105.6" x2="283.3" y2="94.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st1" points="280.9,94.9 285.8,94.9 283.3,92.5 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 581.4624 105.8013)" class="st1 st9 st10">size=16</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st11" x1="576.9" y1="105.6" x2="576.9" y2="94.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st1" points="574.51,94.9 579.4,94.9 576.9,92.5 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st12" d="M687.51,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S687.51,59.9,687.51,60.7z"/>
|
|
||||||
<path class="st12" d="M701.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S701.2,59.9,701.2,60.7z"/>
|
|
||||||
<path class="st12" d="M714.9,60.7c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
C714.2,59.1,714.9,59.9,714.9,60.7z"/>
|
|
||||||
<path class="st12" d="M728.7,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
C728.01,59.1,728.7,59.9,728.7,60.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st12" d="M82.8,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S82.8,59.9,82.8,60.7z"/>
|
|
||||||
<path class="st12" d="M96.5,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6C95.8,59.1,96.5,59.9,96.5,60.7
|
|
||||||
z"/>
|
|
||||||
<path class="st12" d="M110.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S110.2,59.9,110.2,60.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 180.6541 26.8123)" class="st13 st9 st10">data</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 387.363 26.8123)" class="st12 st9 st10">free space</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st14" x1="272.2" y1="33.6" x2="133.5" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st13" points="271.9,36.2 273.5,33.6 271.9,31.1 271.8,31.1 271.8,36.2 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st13" points="133.8,36.1 133.8,31.2 131.4,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st15" x1="563.7" y1="33.6" x2="295.9" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="563.4,36.1 563.4,31.2 565.8,33.6 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="296.2,36.1 296.2,31.2 293.7,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 615.4679 25.1898)" class="st12 st9 st10">non-allocated space</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st15" x1="593.7" y1="33.6" x2="829.7" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="829.4,31.2 829.4,36.1 831.8,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st15" x1="678.7" y1="33.6" x2="589.7" y2="33.6"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="590.01,36.1 590.01,31.2 587.6,33.6 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 133.1212 64.9593)" class="st16 st9 st10">h</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 165.1564 64.9593)" class="st16 st9 st10">e</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 196.8744 64.9593)" class="st16 st9 st10">l</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 229.8611 64.9593)" class="st16 st9 st10">l</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 262.2135 64.9593)" class="st16 st9 st10">o</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 1.811981e-04 105.8011)" class="st1 st9 st10">0</text>
|
|
||||||
</g>
|
|
||||||
<line class="st4" x1="5.5" y1="26.4" x2="5.5" y2="87.6"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st0" points="577.2,207.99 186.3,207.99 186.3,183.19 577.2,183.19 "/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<polyline class="st3" points="122.6,207.99 5.9,207.99 5.9,183.19 122.6,183.19 "/>
|
|
||||||
<polyline class="st4" points="831.51,207.99 5.5,207.99 5.5,183.19 831.51,183.19 "/>
|
|
||||||
<polyline class="st1" points="186.3,207.69 122.5,207.69 122.5,182.89 186.3,182.89 "/>
|
|
||||||
<line class="st4" x1="122.5" y1="161.79" x2="122.5" y2="222.99"/>
|
|
||||||
<line class="st4" x1="186" y1="161.79" x2="186" y2="222.99"/>
|
|
||||||
<line class="st4" x1="576.8" y1="161.79" x2="576.8" y2="222.99"/>
|
|
||||||
<path class="st5" d="M831.51,207.99"/>
|
|
||||||
<line class="st6" x1="153.5" y1="183.49" x2="153.5" y2="207.19"/>
|
|
||||||
<line class="st4" x1="36.5" y1="183.49" x2="36.5" y2="207.19"/>
|
|
||||||
<line class="st4" x1="67.6" y1="183.49" x2="67.6" y2="207.19"/>
|
|
||||||
<line class="st6" x1="186" y1="183.49" x2="186" y2="207.99"/>
|
|
||||||
<line class="st4" x1="218.4" y1="183.49" x2="218.4" y2="207.19"/>
|
|
||||||
<line class="st4" x1="250.9" y1="183.49" x2="250.9" y2="207.19"/>
|
|
||||||
<line class="st4" x1="283.3" y1="183.49" x2="283.3" y2="207.19"/>
|
|
||||||
<line class="st4" x1="315.9" y1="183.49" x2="315.9" y2="207.19"/>
|
|
||||||
<line class="st4" x1="348.4" y1="183.49" x2="348.4" y2="207.19"/>
|
|
||||||
<line class="st4" x1="381.2" y1="183.49" x2="381.2" y2="207.19"/>
|
|
||||||
<line class="st4" x1="413.8" y1="183.49" x2="413.8" y2="207.19"/>
|
|
||||||
<line class="st4" x1="446.3" y1="183.49" x2="446.3" y2="207.19"/>
|
|
||||||
<line class="st4" x1="478.9" y1="183.49" x2="478.9" y2="207.19"/>
|
|
||||||
<line class="st6" x1="511.51" y1="183.49" x2="511.51" y2="207.19"/>
|
|
||||||
<line class="st4" x1="511.51" y1="183.49" x2="511.51" y2="207.19"/>
|
|
||||||
<line class="st6" x1="544.01" y1="183.49" x2="544.01" y2="207.19"/>
|
|
||||||
<line class="st4" x1="544.1" y1="183.49" x2="544.1" y2="207.19"/>
|
|
||||||
<line class="st8" x1="186" y1="208.19" x2="122.5" y2="207.99"/>
|
|
||||||
<line class="st8" x1="122.5" y1="183.19" x2="186" y2="183.29"/>
|
|
||||||
<path class="st5" d="M385.5,208.19"/>
|
|
||||||
<path class="st5" d="M385.5,184.49"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 127.5176 240.9952)" class="st1 st9 st10">buf</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st11" x1="122.2" y1="240.79" x2="122.2" y2="229.79"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st1" points="119.8,230.09 124.6,230.09 122.2,227.69 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 189.2273 240.9947)" class="st1 st9 st10">len=2</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st11" x1="185.88" y1="240.79" x2="185.88" y2="229.79"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st1" points="183.48,230.09 188.38,230.09 185.88,227.69 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 581.4624 240.9952)" class="st1 st9 st10">size=16</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st11" x1="576.9" y1="240.79" x2="576.9" y2="229.79"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st1" points="574.51,230.09 579.4,230.09 576.9,227.69 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st12" d="M687.51,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
S687.51,195.09,687.51,195.89z"/>
|
|
||||||
<path class="st12" d="M701.2,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S701.2,195.09,701.2,195.89z
|
|
||||||
"/>
|
|
||||||
<path class="st12" d="M714.9,195.89c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
S714.9,195.09,714.9,195.89z"/>
|
|
||||||
<path class="st12" d="M728.7,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
C728.01,194.29,728.7,195.09,728.7,195.89z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st12" d="M82.8,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S82.8,195.09,82.8,195.89z"/>
|
|
||||||
<path class="st12" d="M96.5,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
|
||||||
C95.8,194.29,96.5,195.09,96.5,195.89z"/>
|
|
||||||
<path class="st12" d="M110.2,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S110.2,195.09,110.2,195.89z
|
|
||||||
"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 133.6541 162.0062)" class="st13 st9 st10">data</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 327.363 162.0062)" class="st12 st9 st10">free space</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st14" x1="175.2" y1="168.79" x2="133.5" y2="168.79"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st13" points="174.9,171.39 176.5,168.79 174.9,166.29 174.8,166.29 174.8,171.39 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st13" points="133.8,171.29 133.8,166.39 131.4,168.79 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st15" x1="563.7" y1="168.79" x2="197.49" y2="168.79"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="563.4,171.29 563.4,166.39 565.8,168.79 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="197.79,171.29 197.79,166.39 195.29,168.79 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 615.4679 160.3837)" class="st12 st9 st10">non-allocated space</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st15" x1="593.7" y1="168.79" x2="829.7" y2="168.79"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="829.4,166.39 829.4,171.29 831.8,168.79 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<line class="st15" x1="678.7" y1="168.79" x2="589.7" y2="168.79"/>
|
|
||||||
<g>
|
|
||||||
<polygon class="st12" points="590.01,171.29 590.01,166.39 587.6,168.79 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 133.1212 200.1532)" class="st16 st9 st10">h</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 165.1565 200.1532)" class="st16 st9 st10">o</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 1.811981e-04 240.995)" class="st1 st9 st10">0</text>
|
|
||||||
</g>
|
|
||||||
<line class="st4" x1="5.5" y1="161.59" x2="5.5" y2="222.79"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 13 KiB |
@@ -1,384 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 858.5 424.3" style="enable-background:new 0 0 858.5 424.3;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#9E9B83;}
|
|
||||||
.st1{fill:#9E8900;}
|
|
||||||
.st2{font-family:Arial;font-weight:bold;}
|
|
||||||
.st3{font-size:11px;}
|
|
||||||
.st4{display:none;fill:#576174;}
|
|
||||||
.st5{fill:#1F5F75;}
|
|
||||||
.st6{clip-path:url(#SVGID_3_);fill:#FFFFFF;fill-opacity:0.1;}
|
|
||||||
.st7{fill:#277691;}
|
|
||||||
.st8{fill:#FFFFFF;}
|
|
||||||
.st9{font-family:Arial;font-weight:bold;}
|
|
||||||
.st10{fill:#004219;}
|
|
||||||
.st11{clip-path:url(#SVGID_6_);fill:#FFFFFF;fill-opacity:0.1;}
|
|
||||||
.st12{fill:#005721;}
|
|
||||||
.st13{fill:url(#SVGID_7_);}
|
|
||||||
.st14{clip-path:url(#XMLID_13_);fill:#FFFFFF;fill-opacity:0.1;}
|
|
||||||
.st15{fill:#752E06;}
|
|
||||||
.st16{fill:#963B08;}
|
|
||||||
.st17{fill:#59008F;}
|
|
||||||
.st18{clip-path:url(#XMLID_15_);fill:#FFFFFF;fill-opacity:0.1;}
|
|
||||||
.st19{fill:#7300B8;}
|
|
||||||
.st20{fill:#FFDE00;}
|
|
||||||
.st21{fill:#576174;}
|
|
||||||
.st22{font-size:13px;}
|
|
||||||
.st23{fill:#8A8C8E;}
|
|
||||||
.st24{font-size:12px;}
|
|
||||||
.st25{opacity:0.69;}
|
|
||||||
.st26{fill:#B3B1B3;}
|
|
||||||
.st27{clip-path:url(#XMLID_17_);fill:#FFFFFF;fill-opacity:0.1;}
|
|
||||||
.st28{fill:#919091;}
|
|
||||||
.st29{fill:#BFBEBF;}
|
|
||||||
.st30{fill:#454445;}
|
|
||||||
.st31{font-size:9px;}
|
|
||||||
.st32{clip-path:url(#XMLID_19_);fill:#FFFFFF;fill-opacity:0.1;}
|
|
||||||
.st33{fill:#8695B3;}
|
|
||||||
.st34{fill:url(#SVGID_8_);}
|
|
||||||
.st35{font-size:18px;}
|
|
||||||
.st36{clip-path:url(#XMLID_20_);fill:#610041;fill-opacity:0.1;}
|
|
||||||
.st37{fill:#610041;}
|
|
||||||
.st38{clip-path:url(#XMLID_22_);fill:url(#SVGID_9_);fill-opacity:0.1;}
|
|
||||||
.st39{fill:none;stroke:#86005B;stroke-width:0.5;stroke-linecap:round;stroke-miterlimit:10;}
|
|
||||||
.st40{fill:none;stroke:#86005B;stroke-width:0.75;stroke-linecap:round;stroke-miterlimit:10;}
|
|
||||||
.st41{fill:url(#SVGID_10_);}
|
|
||||||
.st42{fill:url(#SVGID_11_);}
|
|
||||||
.st43{fill:#610042;}
|
|
||||||
.st44{fill:url(#SVGID_12_);}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M457.9,111.2l0.1,87.3c0,1.4-1.1,2.6-2.5,2.6h-76.3c-4.4-0.2-7.3-3.9-7.3-5.3l4.7-101.8
|
|
||||||
c0-1.4,0.8-7.4,2.2-7.4l54-0.1L457.9,111.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 383.2604 149.9447)" class="st1 st2 st3">packed_fs.c</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<rect x="84" y="25" class="st4" width="727.7" height="429.8"/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st5" d="M207.5,104.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V84.5c0-1.4,1.1-2.5,2.5-2.5h58
|
|
||||||
L207.5,104.6z"/>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="SVGID_1_" d="M205.5,102.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5V82.5c0-1.4,1.1-2.5,2.5-2.5
|
|
||||||
h58L205.5,102.6z"/>
|
|
||||||
</defs>
|
|
||||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="122.1091" y1="136.2824" x2="205.5191" y2="136.2824">
|
|
||||||
<stop offset="0" style="stop-color:#45CFFF"/>
|
|
||||||
<stop offset="1" style="stop-color:#85DDFA"/>
|
|
||||||
</linearGradient>
|
|
||||||
<use xlink:href="#SVGID_1_" style="overflow:visible;fill:url(#SVGID_2_);"/>
|
|
||||||
<clipPath id="SVGID_3_">
|
|
||||||
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<path class="st6" d="M121.4,101.4c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V101.4z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st5" d="M205.9,104.4l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L205.9,104.4z"/>
|
|
||||||
<path class="st7" d="M205.7,102.8h-20.5c-1.4,0-2.5-1.1-2.5-2.5V79.9l0,0l22.9,22.7L205.7,102.8z"/>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 129.0689 92.8531)" class="st8 st9 st3">filex.y</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st10" d="M191.4,121.6V209c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V101.4c0-1.4,1.1-2.5,2.5-2.5h58
|
|
||||||
L191.4,121.6z"/>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="SVGID_4_" d="M189.4,119.6V207c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5V99.4c0-1.4,1.1-2.5,2.5-2.5
|
|
||||||
h58L189.4,119.6z"/>
|
|
||||||
</defs>
|
|
||||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="106.0386" y1="153.2384" x2="189.4486" y2="153.2384">
|
|
||||||
<stop offset="0" style="stop-color:#00983A"/>
|
|
||||||
<stop offset="1" style="stop-color:#3A985D"/>
|
|
||||||
</linearGradient>
|
|
||||||
<use xlink:href="#SVGID_4_" style="overflow:visible;fill:url(#SVGID_5_);"/>
|
|
||||||
<clipPath id="SVGID_6_">
|
|
||||||
<use xlink:href="#SVGID_4_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<path class="st11" d="M105.3,118.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V118.3z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st10" d="M189.8,121.3l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L189.8,121.3z"/>
|
|
||||||
<path class="st12" d="M189.6,119.7h-20.5c-1.4,0-2.5-1.1-2.5-2.5V96.9l0,0l22.9,22.7L189.6,119.7z"/>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 113.9984 109.809)" class="st8 st9 st3">main.js</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="93.2369" y1="173.2516" x2="176.6469" y2="173.2516">
|
|
||||||
<stop offset="0" style="stop-color:#EA5B0C"/>
|
|
||||||
<stop offset="1" style="stop-color:#EA671E"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path class="st13" d="M176.6,139.6V227c0,1.4-1.1,2.6-2.5,2.6H95.8c-1.4,0-2.5-1.1-2.5-2.6V119.5c0-1.4,1.1-2.5,2.5-2.5h58
|
|
||||||
L176.6,139.6z"/>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="XMLID_2_" d="M174.6,137.6V225c0,1.4-1.1,2.6-2.5,2.6H93.8c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1c0-1.4,1.1-2.5,2.5-2.5
|
|
||||||
h58L174.6,137.6z"/>
|
|
||||||
</defs>
|
|
||||||
<linearGradient id="XMLID_12_" gradientUnits="userSpaceOnUse" x1="91.2369" y1="171.2516" x2="174.6469" y2="171.2516">
|
|
||||||
<stop offset="0" style="stop-color:#EA5B0C"/>
|
|
||||||
<stop offset="1" style="stop-color:#EA7B3D"/>
|
|
||||||
</linearGradient>
|
|
||||||
<use xlink:href="#XMLID_2_" style="overflow:visible;fill:url(#XMLID_12_);"/>
|
|
||||||
<clipPath id="XMLID_13_">
|
|
||||||
<use xlink:href="#XMLID_2_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<path class="st14" d="M90.5,136.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V136.3z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st15" d="M175,139.3l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L175,139.3z"/>
|
|
||||||
<path class="st16" d="M174.8,137.7h-20.5c-1.4,0-2.5-1.1-2.5-2.5v-20.3l0,0l22.9,22.7L174.8,137.7z"/>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 97.1967 127.8222)" class="st8 st9 st3">style.css</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st17" d="M164.6,157.7v87.4c0,1.4-1.1,2.6-2.5,2.6H83.8c-1.4,0-2.5-1.1-2.5-2.6V137.5c0-1.4,1.1-2.5,2.5-2.5h58
|
|
||||||
L164.6,157.7z"/>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="XMLID_1_" d="M162.6,155.7v87.4c0,1.4-1.1,2.6-2.5,2.6H81.8c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1c0-1.4,1.1-2.5,2.5-2.5
|
|
||||||
h58L162.6,155.7z"/>
|
|
||||||
</defs>
|
|
||||||
<linearGradient id="XMLID_14_" gradientUnits="userSpaceOnUse" x1="79.2009" y1="189.3131" x2="162.6108" y2="189.3131">
|
|
||||||
<stop offset="0" style="stop-color:#A000FF"/>
|
|
||||||
<stop offset="1" style="stop-color:#C96EFF"/>
|
|
||||||
</linearGradient>
|
|
||||||
<use xlink:href="#XMLID_1_" style="overflow:visible;fill:url(#XMLID_14_);"/>
|
|
||||||
<clipPath id="XMLID_15_">
|
|
||||||
<use xlink:href="#XMLID_1_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<path class="st18" d="M78.5,154.4c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V154.4z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st17" d="M163,157.4l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L163,157.4z"/>
|
|
||||||
<path class="st19" d="M162.8,155.8h-20.5c-1.4,0-2.5-1.1-2.5-2.5V133l0,0l22.9,22.7L162.8,155.8z"/>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 83.1607 145.8838)" class="st8 st9 st3">index.html</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st20" d="M455.2,108.2v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V88.1c0-1.4,1.1-2.5,2.5-2.5h58
|
|
||||||
L455.2,108.2z"/>
|
|
||||||
<path class="st0" d="M455.3,110.3l-18.4,0c-1.4,0-2.5-1.1-2.5-2.5V87.5l0,0l20.9,20.7L455.3,110.3z"/>
|
|
||||||
<polygon class="st0" points="435.2,109.7 432.9,107.3 436.3,106.9 "/>
|
|
||||||
<path class="st1" d="M455.4,108.3h-20.5c-1.4,0-2.5-1.1-2.5-2.5V85.5l0,0l22.9,22.7L455.4,108.3z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 379.2604 144.9447)" class="st21 st9 st22">packed_fs.c</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st23" points="483.6,195.4 397.3,195.4 394.3,193.4 397.3,162.8 481.5,159.7 483.6,162.8 "/>
|
|
||||||
<rect x="394.3" y="159.8" class="st21" width="87.3" height="33.7"/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 400.0845 171.7588)" class="st8 st9 st24">mg_unpack()</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 400.0845 186.935)" class="st8 st9 st24">mg_unlist()</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g class="st25">
|
|
||||||
<g>
|
|
||||||
<path class="st26" d="M467.7,256.6V344c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V236.4c0-1.4,1.1-2.5,2.5-2.5h58
|
|
||||||
L467.7,256.6z"/>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="XMLID_9_" d="M465.7,254.6V342c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1c0-1.4,1.1-2.5,2.5-2.5
|
|
||||||
h58L465.7,254.6z"/>
|
|
||||||
</defs>
|
|
||||||
<linearGradient id="XMLID_16_" gradientUnits="userSpaceOnUse" x1="382.3115" y1="288.2073" x2="465.7215" y2="288.2073">
|
|
||||||
<stop offset="0" style="stop-color:#D6D4D6"/>
|
|
||||||
<stop offset="1" style="stop-color:#FFFDFE"/>
|
|
||||||
</linearGradient>
|
|
||||||
<use xlink:href="#XMLID_9_" style="overflow:visible;fill:url(#XMLID_16_);"/>
|
|
||||||
<clipPath id="XMLID_17_">
|
|
||||||
<use xlink:href="#XMLID_9_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<path class="st27" d="M381.6,253.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V253.3z"/>
|
|
||||||
</g>
|
|
||||||
<path class="st28" d="M466.1,256.3l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L466.1,256.3z"/>
|
|
||||||
<path class="st29" d="M465.9,254.7h-20.5c-1.4,0-2.5-1.1-2.5-2.5v-20.3l0,0l22.9,22.7L465.9,254.7z"/>
|
|
||||||
<text transform="matrix(1 0 0 1 386.2713 244.7779)" class="st30 st9 st31">mongoose.c</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st26" d="M455.7,276.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6V256.5c0-1.4,1.1-2.5,2.5-2.5h58
|
|
||||||
L455.7,276.6z"/>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="XMLID_8_" d="M453.7,274.6v87.4c0,1.4-1.1,2.6-2.5,2.6h-78.3c-1.4,0-2.5-1.1-2.5-2.6v-57.5v-50.1
|
|
||||||
c0-1.4,1.1-2.5,2.5-2.5h58L453.7,274.6z"/>
|
|
||||||
</defs>
|
|
||||||
<linearGradient id="XMLID_18_" gradientUnits="userSpaceOnUse" x1="370.2755" y1="308.2689" x2="453.6855" y2="308.2689">
|
|
||||||
<stop offset="0" style="stop-color:#D6D4D6"/>
|
|
||||||
<stop offset="1" style="stop-color:#FFFDFE"/>
|
|
||||||
</linearGradient>
|
|
||||||
<use xlink:href="#XMLID_8_" style="overflow:visible;fill:url(#XMLID_18_);"/>
|
|
||||||
<clipPath id="XMLID_19_">
|
|
||||||
<use xlink:href="#XMLID_8_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<path class="st32" d="M369.6,273.3c9.4,0.7,36.6,1.5,53.2,14.7c25,20,31.2,47.1,31.2,47.1l0.4,35.3l-84.8,0.2V273.3z"/>
|
|
||||||
<use xlink:href="#XMLID_8_" style="overflow:visible;fill:none;stroke:#FFFDFE;stroke-width:0.25;stroke-miterlimit:10;"/>
|
|
||||||
</g>
|
|
||||||
<path class="st28" d="M454,276.4l-20.6,0c-1.4,0-2.6-1.2-2.6-2.6l0-21.8l22.9,22.7L454,276.4z"/>
|
|
||||||
<path class="st29" d="M453.8,274.8h-20.5c-1.4,0-2.5-1.1-2.5-2.5v-20.3l0,0l22.9,22.7L453.8,274.8z"/>
|
|
||||||
<text transform="matrix(1 0 0 1 379.2353 264.8395)" class="st30 st9 st31">app.c</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st33" points="342.3,123.3 351.1,141.7 342.3,160.7 234.8,160.9 234.8,122.6 "/>
|
|
||||||
<path class="st23" d="M347.4,145.4"/>
|
|
||||||
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="233.6667" y1="139.4088" x2="350.0318" y2="139.4088">
|
|
||||||
<stop offset="0" style="stop-color:#C1D5FF"/>
|
|
||||||
<stop offset="0.1995" style="stop-color:#BACDF6"/>
|
|
||||||
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
|
|
||||||
<stop offset="1" style="stop-color:#ADC0E6"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon class="st34" points="341.2,120.9 350,139.3 341.2,158.3 233.7,158.5 233.7,120.3 "/>
|
|
||||||
<text transform="matrix(1 0 0 1 262.9869 146.2633)" class="st8 st9 st35">PACK</text>
|
|
||||||
<polygon class="st33" points="234.8,160.9 233.7,158.5 238,158.7 "/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st23" d="M634.9,144.6L634.9,144.6z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st33" points="619.6,139.3 619.6,139.3 618.7,137.4 618.7,137.4 "/>
|
|
||||||
<path class="st23" d="M623.1,168.2L623.1,168.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st33" points="619.6,288.1 618.7,290 618.7,290 619.6,288.1 "/>
|
|
||||||
<path class="st23" d="M623.1,259.2L623.1,259.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st23" d="M617,282L617,282z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="XMLID_10_" d="M722.7,276.5h-71.2c-11.6,0-21.1-9.4-21.1-21.1v-71.2c0-11.6,9.4-21.1,21.1-21.1h71.2
|
|
||||||
c11.6,0,21.1,9.4,21.1,21.1v71.2C743.8,267,734.4,276.5,722.7,276.5z"/>
|
|
||||||
</defs>
|
|
||||||
<use xlink:href="#XMLID_10_" style="overflow:visible;fill:#610041;"/>
|
|
||||||
<clipPath id="XMLID_20_">
|
|
||||||
<use xlink:href="#XMLID_10_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<path class="st36" d="M754.3,172.5c-2.7,8-17.3,30.9-65.8,30.8c-24.5,0-48.4-7.4-65.7-24.7l-12.1-12l69.3-64.6L754.3,172.5z"/>
|
|
||||||
</g>
|
|
||||||
<polygon class="st37" points="637.6,271.2 632.5,266.1 640.3,269.4 "/>
|
|
||||||
<polygon class="st37" points="738.3,169.9 734.6,166.2 736.4,171 "/>
|
|
||||||
<g>
|
|
||||||
<defs>
|
|
||||||
<path id="XMLID_5_" d="M719.7,273.5h-71.2c-11.6,0-21.1-9.4-21.1-21.1v-71.2c0-11.6,9.4-21.1,21.1-21.1h71.2
|
|
||||||
c11.6,0,21.1,9.4,21.1,21.1v71.2C740.8,264,731.4,273.5,719.7,273.5z"/>
|
|
||||||
</defs>
|
|
||||||
<radialGradient id="XMLID_21_" cx="684.119" cy="216.7761" r="56.6929" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop offset="0" style="stop-color:#8B005D;stop-opacity:0.7"/>
|
|
||||||
<stop offset="1" style="stop-color:#8B005D"/>
|
|
||||||
</radialGradient>
|
|
||||||
<use xlink:href="#XMLID_5_" style="overflow:visible;fill:url(#XMLID_21_);"/>
|
|
||||||
<clipPath id="XMLID_22_">
|
|
||||||
<use xlink:href="#XMLID_5_" style="overflow:visible;"/>
|
|
||||||
</clipPath>
|
|
||||||
<radialGradient id="SVGID_9_" cx="678.486" cy="148.5836" r="90.2195" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop offset="0" style="stop-color:#8B005D"/>
|
|
||||||
<stop offset="1" style="stop-color:#FFFFFF"/>
|
|
||||||
</radialGradient>
|
|
||||||
<path class="st38" d="M750.3,168.5c-2.7,8-17.3,30.9-65.8,30.8c-24.5,0-48.4-7.4-65.7-24.7l-12.1-12L676,97.9L750.3,168.5z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<text transform="matrix(1 0 0 1 646.3768 216.49)" class="st8 st9 st35">APP.EXE</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st8" d="M732,240.1c-0.3-1.4-0.8-2.7-1.4-3.9l1.7-2.3c-0.3-0.5-0.6-0.9-1-1.4c-0.3-0.5-0.7-0.9-1.1-1.3l-2.7,1
|
|
||||||
c-1-1-2.2-1.8-3.4-2.4l0-2.9c-1-0.4-2.1-0.8-3.2-1l-1.5,2.4c-1.4-0.2-2.8-0.2-4.1,0l-1.7-2.4c-1.1,0.2-2.1,0.6-3.1,1.1l0.2,2.9
|
|
||||||
c-0.6,0.3-1.2,0.7-1.7,1.1c-0.6,0.4-1.1,0.9-1.5,1.4l-2.7-0.9l-1.9,2.7l1.8,2.3c-0.6,1.3-1,2.6-1.1,4l-2.7,0.9
|
|
||||||
c-0.1,1.1,0,2.2,0.1,3.3l2.8,0.8c0.3,1.3,0.8,2.7,1.4,3.9l-1.7,2.3c0.3,0.5,0.6,0.9,1,1.4c0.3,0.4,0.7,0.9,1.1,1.3l2.7-1
|
|
||||||
c1,1,2.2,1.8,3.4,2.4l0,2.9c1,0.4,2.1,0.8,3.2,1l1.5-2.4c1.4,0.2,2.8,0.2,4.1,0l1.7,2.4c1.1-0.3,2.1-0.6,3.1-1.1l-0.2-2.9
|
|
||||||
c0.6-0.3,1.2-0.7,1.7-1.1c0.6-0.4,1.1-0.9,1.5-1.4l2.8,0.9c0.7-0.8,1.3-1.8,1.9-2.7L731,249c0.6-1.3,1-2.6,1.1-4l2.7-0.9
|
|
||||||
c0.1-1.1,0-2.2-0.1-3.3L732,240.1z M724,251c-4.6,3.5-11.1,2.6-14.6-2c-3.5-4.6-2.6-11.1,2-14.6s11.1-2.6,14.6,2
|
|
||||||
C729.5,241,728.6,247.5,724,251z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st8" d="M700.5,249.3c-0.2-0.8-0.5-1.6-0.8-2.4l1-1.4c-0.2-0.3-0.4-0.6-0.6-0.8c-0.2-0.3-0.4-0.5-0.7-0.8l-1.6,0.6
|
|
||||||
c-0.6-0.6-1.3-1.1-2.1-1.4l0-1.7c-0.6-0.3-1.3-0.5-1.9-0.6l-0.9,1.4c-0.8-0.1-1.7-0.1-2.5,0l-1-1.4c-0.6,0.1-1.3,0.4-1.9,0.6
|
|
||||||
l0.1,1.7c-0.4,0.2-0.7,0.4-1,0.7c-0.3,0.3-0.6,0.5-0.9,0.8l-1.6-0.6l-1.1,1.6l1.1,1.4c-0.3,0.8-0.6,1.6-0.7,2.4l-1.6,0.5
|
|
||||||
c0,0.7,0,1.3,0.1,2l1.7,0.5c0.2,0.8,0.4,1.6,0.9,2.4l-1,1.4c0.2,0.3,0.4,0.6,0.6,0.8c0.2,0.3,0.4,0.5,0.7,0.8l1.6-0.6
|
|
||||||
c0.6,0.6,1.3,1.1,2.1,1.4l0,1.7c0.6,0.3,1.3,0.5,1.9,0.6l0.9-1.4c0.8,0.1,1.7,0.1,2.5,0l1,1.4c0.6-0.2,1.3-0.4,1.9-0.6l-0.1-1.7
|
|
||||||
c0.4-0.2,0.7-0.4,1-0.7c0.3-0.3,0.6-0.5,0.9-0.8l1.6,0.6c0.4-0.5,0.8-1.1,1.1-1.6l-1.1-1.4c0.3-0.8,0.6-1.6,0.7-2.4l1.6-0.5
|
|
||||||
c0-0.7,0-1.3-0.1-2L700.5,249.3z M694.5,254.2c-1.8,1.4-4.5,1-5.9-0.8c-1.4-1.8-1-4.5,0.8-5.9c1.8-1.4,4.5-1,5.9,0.8
|
|
||||||
C696.8,250.2,696.4,252.8,694.5,254.2z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st39" d="M708.9,234.5"/>
|
|
||||||
<path class="st39" d="M706.7,237.9"/>
|
|
||||||
<path class="st40" d="M705.7,242.7c0-1.7,0.4-3.4,1-4.9"/>
|
|
||||||
<path class="st40" d="M708.9,234.5c2.2-2.4,5.3-3.8,8.8-3.8"/>
|
|
||||||
<path class="st40" d="M687.4,247.3c1.1-1.4,2.7-2.2,4.6-2.2"/>
|
|
||||||
<path class="st39" d="M686.4,249.5"/>
|
|
||||||
<path class="st40" d="M686.2,250.9c0-0.5,0.1-1,0.2-1.4"/>
|
|
||||||
<path class="st39" d="M686.7,253.2"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st33" d="M611.7,174.2l-23,3.3l-13.1-9.6c-6.3-4.6-13.9-7.1-21.7-7l-55.5,0.1l-1.1-2.4h1.1l64.2-0.2h0.1l3.9,0h0.1
|
|
||||||
l3.2,2.4l19.2,14l0.2,0.2l23.4-3.3L611.7,174.2z"/>
|
|
||||||
<path class="st23" d="M595.9,145.5L595.9,145.5z"/>
|
|
||||||
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="497.2089" y1="147.636" x2="612.739" y2="147.636">
|
|
||||||
<stop offset="0" style="stop-color:#C1D5FF"/>
|
|
||||||
<stop offset="0.1995" style="stop-color:#BACDF6"/>
|
|
||||||
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
|
|
||||||
<stop offset="1" style="stop-color:#ADC0E6"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path class="st41" d="M612.7,171.7l-3,0.4l-20.3,2.8l-0.2-0.1l-13.6-9.9l0,0c-3.7-2.7-8.7-4.4-12.9-5.4c-2.9-0.7-6-1-9-1l-35.5,0.1
|
|
||||||
l-19.8,0.1h-1.1v-38.3l13.5,0.2l4,0l42.6,0.2l7.9,0c7,0,14,1.6,20.2,4.9c0,0,0,0,0,0c0.8,0.5,1.6,0.9,2.4,1.5l7.5,5.6l0.1,0.1l0,0
|
|
||||||
l15.4,11.3v0l0.1,3.2L612.7,171.7z"/>
|
|
||||||
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="597.6228" y1="138.4046" x2="598.5728" y2="138.4046">
|
|
||||||
<stop offset="0" style="stop-color:#C1D5FF"/>
|
|
||||||
<stop offset="0.1995" style="stop-color:#BACDF6"/>
|
|
||||||
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
|
|
||||||
<stop offset="1" style="stop-color:#ADC0E6"/>
|
|
||||||
</linearGradient>
|
|
||||||
<polygon class="st42" points="598.6,139.3 598.6,139.4 597.6,137.4 597.7,137.5 "/>
|
|
||||||
<text transform="matrix(1 0 0 1 513.7678 146.3103)" class="st8 st9 st35">BUILD</text>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st33" d="M612.7,258.8l-0.1,2.2l-1.8-0.2l-20.3-2.8l-0.2,0.1l-13.6,9.9l0-0.1c-3.7,2.7-8.7,4.4-12.9,5.4
|
|
||||||
c-2.9,0.7-6,1-9,1l-35.5-0.1l-19.8-0.1h-1.1v35.4l-1.1,0.4l1.1,2.4l13.5-0.2l4,0l42.6-0.2l7.9-0.1c7,0,14-1.6,20.2-4.9c0,0,0,0,0,0
|
|
||||||
c0.8-0.5,1.6-0.9,2.4-1.5l7.5-5.6l0.1-0.1l0,0l15.4-11.3l1-0.9l1.9-26.7L612.7,258.8z"/>
|
|
||||||
<path class="st43" d="M593.5,272.5"/>
|
|
||||||
<g>
|
|
||||||
<path class="st23" d="M598.5,285L598.5,285z"/>
|
|
||||||
|
|
||||||
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="497.2089" y1="451.0054" x2="612.739" y2="451.0054" gradientTransform="matrix(1 0 0 -1 0 733.8616)">
|
|
||||||
<stop offset="0" style="stop-color:#C1D5FF"/>
|
|
||||||
<stop offset="0.1995" style="stop-color:#BACDF6"/>
|
|
||||||
<stop offset="0.6001" style="stop-color:#B0C3EA"/>
|
|
||||||
<stop offset="1" style="stop-color:#ADC0E6"/>
|
|
||||||
</linearGradient>
|
|
||||||
<path class="st44" d="M612.7,258.8l-3-0.4l-20.3-2.8l-0.2,0.1l-13.6,9.9l0,0c-3.7,2.7-8.7,4.4-12.9,5.4c-2.9,0.7-6,1-9,1
|
|
||||||
l-35.5-0.1l-19.8-0.1h-1.1v38.3l13.5-0.2l4,0l42.6-0.2l7.9,0c7,0,14-1.6,20.2-4.9c0,0,0,0,0,0c0.8-0.5,1.6-0.9,2.4-1.5l7.5-5.6
|
|
||||||
l0.1-0.1l0,0l15.4-11.3v0l0.1-3.2L612.7,258.8z"/>
|
|
||||||
<text transform="matrix(1 0 0 1 513.7682 298.0848)" class="st8 st9 st35">BUILD</text>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path class="st33" d="M619.9,149.1"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
# Mongoose Network Library Examples
|
||||||
|
|
||||||
|
In order to build and run any of the existing examples, please follow:
|
||||||
|
https://mongoose.ws/documentation/#how-to-build-and-run-examples
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Rules for creating a new example:
|
||||||
|
|
||||||
|
- Makefile golden reference for desktop/server example: [http-server](http-server)
|
||||||
|
- Makefile golden reference for the embedded example:
|
||||||
|
[stm32/nucleo-f746zg-baremetal](stm32/nucleo-f746zg-baremetal)
|
||||||
|
- An example must build on Windows, Mac and Ubuntu Linux systems
|
||||||
|
- Assume that user installed tools according to https://mongoose.ws/tutorials/tools/
|
||||||
|
- Makefile must not include any other make files
|
||||||
|
- Use `CFLAGS` for system-specific compilation options
|
||||||
|
- Use `CFLAGS_MONGOOSE` for mongoose-specific compilation options
|
||||||
|
- Use `$(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA)` to compile
|
||||||
|
- If external repository is required, download it on demand using git
|
||||||
|
shallow clone. See embedded example golden reference
|
||||||
|
- Keep Makefile as short as possible, but verbose to understand it easily
|
||||||
|
- Symlink files when required, like `mongoose.c`, `ca.pem`, etc. Make no copies
|
||||||
|
- Example's README.md should contain only the title and the link to mongoose.ws
|
||||||
|
tutorial page
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
all:
|
||||||
|
example:
|
||||||
|
true
|
||||||
|
|
||||||
|
arduino: ENV = -v $(CWD):/root
|
||||||
|
arduino:
|
||||||
|
curl -sL http://downloads.arduino.cc/arduino-1.8.19-linux64.tar.xz | unxz | tar -xf -
|
||||||
|
mv arduino-* $@
|
||||||
|
|
||||||
|
arduino-xiao-board:
|
||||||
|
./arduino/arduino --pref "boardsmanager.additional.urls=https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json" --save-prefs
|
||||||
|
./arduino/arduino --pref "compiler.warning_level=all" --save-prefs
|
||||||
|
./arduino/arduino --install-boards Seeeduino:samd
|
||||||
|
|
||||||
|
arduino-xiao: arduino arduino-xiao-board
|
||||||
|
cd w5500-http && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 w5500-http.ino
|
||||||
|
cd w5500-mqtt && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 w5500-mqtt.ino
|
||||||
|
|
||||||
|
arduino-nano: arduino
|
||||||
|
cd w5500-http && ../arduino/arduino --pref compiler.cpp.extra_flags=-DMG_ENABLE_LOG=0 --verbose --verify --board arduino:avr:nano w5500-http.ino
|
||||||
|
cd w5500-mqtt && ../arduino/arduino --pref compiler.cpp.extra_flags=-DMG_ENABLE_LOG=0 --verbose --verify --board arduino:avr:nano w5500-mqtt.ino
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf arduino
|
||||||
|
|
||||||
|
cleanall: clean #otherwise some parts of xiao-board installation will fail as already installed
|
||||||
|
rm -rf ~/.arduino15 ~/.oracle_jre_usage
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../mongoose.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../mongoose.h
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define MG_ARCH MG_ARCH_NEWLIB // Use ARM toolchain
|
||||||
|
#define MG_ENABLE_TCPIP 1 // Enable built-in network stack
|
||||||
|
#define MG_ENABLE_DRIVER_IMXRT 1 // Enable RTxx driver
|
||||||
|
#define MG_ENABLE_CUSTOM_MILLIS 1 // Let user implement mg_millis()
|
||||||
|
#define MG_ENABLE_POSIX_FS 0 // Disable POSIX filesystem
|
||||||
|
#define MG_ENABLE_PACKED_FS 1 // Enable packed filesystem
|
||||||
|
|
||||||
|
#define HTTP_URL "http://0.0.0.0"
|
||||||
|
#define HTTPS_URL "https://0.0.0.0"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../device-dashboard/net.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../device-dashboard/net.h
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../device-dashboard/packed_fs.c
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
#include "mongoose.h"
|
||||||
|
#include "net.h"
|
||||||
|
|
||||||
|
void ethernet_init(void);
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
struct mg_tcpip_driver_imxrt_data data = {.mdc_cr = 24, .phy_addr = 0};
|
||||||
|
struct mg_tcpip_if mif = {
|
||||||
|
// Construct MAC address from the unique chip ID
|
||||||
|
.mac = {2, (uint8_t) (HW_OCOTP_CFG0 & 255),
|
||||||
|
(uint8_t) ((HW_OCOTP_CFG0 >> 10) & 255),
|
||||||
|
(uint8_t) (((HW_OCOTP_CFG0 >> 19) ^ (HW_OCOTP_CFG1 >> 19)) & 255),
|
||||||
|
(uint8_t) ((HW_OCOTP_CFG1 >> 10) & 255),
|
||||||
|
(uint8_t) (HW_OCOTP_CFG1 & 255)},
|
||||||
|
// The default is DHCP. Uncomment 3 lines below for static IP config:
|
||||||
|
// .ip = mg_htonl(MG_U32(192, 168, 0, 223)),
|
||||||
|
// .mask = mg_htonl(MG_U32(255, 255, 255, 0)),
|
||||||
|
// .gw = mg_htonl(MG_U32(192, 168, 0, 1)),
|
||||||
|
.driver = &mg_tcpip_driver_imxrt,
|
||||||
|
.driver_data = &data};
|
||||||
|
|
||||||
|
uint64_t mg_millis(void) { // Let Mongoose use our uptime function
|
||||||
|
return millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple HTTP server that runs on port 8000
|
||||||
|
// Mongoose event handler function, gets called by the mg_mgr_poll()
|
||||||
|
// See https://mongoose.ws/documentation/#2-minute-integration-guide
|
||||||
|
static void simple_http_listener(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
// The MG_EV_HTTP_MSG event means HTTP request. `hm` holds parsed request,
|
||||||
|
// see https://mongoose.ws/documentation/#struct-mg_http_message
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
|
||||||
|
// If the requested URI is "/api/hi", send a simple JSON response back
|
||||||
|
if (mg_match(hm->uri, mg_str("/api/hi"), NULL)) {
|
||||||
|
// Use mg_http_reply() API function to generate JSON response. It adds a
|
||||||
|
// Content-Length header automatically. In the response, we show
|
||||||
|
// the requested URI and HTTP body:
|
||||||
|
mg_http_reply(c, 200, "", "{%m:%m,%m:%m}\n", // See mg_snprintf doc
|
||||||
|
MG_ESC("uri"), mg_print_esc, hm->uri.len, hm->uri.buf,
|
||||||
|
MG_ESC("body"), mg_print_esc, hm->body.len, hm->body.buf);
|
||||||
|
} else {
|
||||||
|
// For all other URIs, serve some static content
|
||||||
|
mg_http_reply(c, 200, "", "<html>millis: %lu</html>", millis());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
Serial.begin(115200);
|
||||||
|
while (!Serial) delay(50);
|
||||||
|
|
||||||
|
mg_mgr_init(&mgr); // Initialise Mongoose event manager
|
||||||
|
mg_log_set(MG_LL_DEBUG); // Set log level and log function
|
||||||
|
mg_log_set_fn([](char ch, void *) { Serial.print(ch); }, NULL);
|
||||||
|
|
||||||
|
MG_INFO(("CPU %g MHz. Starting TCP/IP stack", (double) F_CPU / 1000000));
|
||||||
|
ethernet_init();
|
||||||
|
mg_tcpip_init(&mgr, &mif); // Initialise built-in TCP/IP stack
|
||||||
|
|
||||||
|
MG_INFO(("Waiting for IP..."));
|
||||||
|
while (mif.state != MG_TCPIP_STATE_READY) mg_mgr_poll(&mgr, 1);
|
||||||
|
|
||||||
|
// We start two HTTP listeners: one is a simple one on port 8000,
|
||||||
|
// with event handler function defined above - simple_http_listener
|
||||||
|
// See https://mongoose.ws/documentation/#2-minute-integration-guide
|
||||||
|
// Another listener is for a more sophisticated Web device dashboard
|
||||||
|
MG_INFO(("Starting web dashboard"));
|
||||||
|
mg_http_listen(&mgr, "http://0.0.0.0:8000", simple_http_listener, NULL);
|
||||||
|
web_init(&mgr); // Sophisticated Web UI, see net.c :: fn()
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
static uint64_t timer;
|
||||||
|
if (mg_timer_expired(&timer, 500, mg_millis())) { // Every 500ms
|
||||||
|
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); // blink an LED
|
||||||
|
}
|
||||||
|
|
||||||
|
mg_mgr_poll(&mgr, 1); // Process network events
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void ENET_IRQHandler(void);
|
||||||
|
|
||||||
|
#define CLRSET(reg, clear, set) ((reg) = ((reg) & ~(clear)) | (set))
|
||||||
|
#define RMII_PAD_INPUT_PULLDOWN 0x30E9
|
||||||
|
#define RMII_PAD_INPUT_PULLUP 0xB0E9
|
||||||
|
#define RMII_PAD_CLOCK 0x0031
|
||||||
|
|
||||||
|
// initialize the ethernet hardware
|
||||||
|
void ethernet_init(void) {
|
||||||
|
CCM_CCGR1 |= CCM_CCGR1_ENET(CCM_CCGR_ON);
|
||||||
|
// configure PLL6 for 50 MHz, pg 1173
|
||||||
|
CCM_ANALOG_PLL_ENET_CLR =
|
||||||
|
CCM_ANALOG_PLL_ENET_POWERDOWN | CCM_ANALOG_PLL_ENET_BYPASS | 0x0F;
|
||||||
|
CCM_ANALOG_PLL_ENET_SET = CCM_ANALOG_PLL_ENET_ENABLE |
|
||||||
|
CCM_ANALOG_PLL_ENET_BYPASS
|
||||||
|
/*| CCM_ANALOG_PLL_ENET_ENET2_REF_EN*/
|
||||||
|
| CCM_ANALOG_PLL_ENET_ENET_25M_REF_EN
|
||||||
|
/*| CCM_ANALOG_PLL_ENET_ENET2_DIV_SELECT(1)*/
|
||||||
|
| CCM_ANALOG_PLL_ENET_DIV_SELECT(1);
|
||||||
|
while (!(CCM_ANALOG_PLL_ENET & CCM_ANALOG_PLL_ENET_LOCK))
|
||||||
|
; // wait for PLL lock
|
||||||
|
CCM_ANALOG_PLL_ENET_CLR = CCM_ANALOG_PLL_ENET_BYPASS;
|
||||||
|
// configure REFCLK to be driven as output by PLL6, pg 326
|
||||||
|
|
||||||
|
CLRSET(IOMUXC_GPR_GPR1,
|
||||||
|
IOMUXC_GPR_GPR1_ENET1_CLK_SEL | IOMUXC_GPR_GPR1_ENET_IPG_CLK_S_EN,
|
||||||
|
IOMUXC_GPR_GPR1_ENET1_TX_CLK_DIR);
|
||||||
|
|
||||||
|
// Configure pins
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_14 = 5; // Reset B0_14 Alt5 GPIO7.15
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B0_15 = 5; // Power B0_15 Alt5 GPIO7.14
|
||||||
|
GPIO7_GDIR |= (1 << 14) | (1 << 15);
|
||||||
|
GPIO7_DR_SET = (1 << 15); // Power on
|
||||||
|
GPIO7_DR_CLEAR = (1 << 14); // Reset PHY chip
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_04 = RMII_PAD_INPUT_PULLDOWN; // PhyAdd[0] = 0
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_06 = RMII_PAD_INPUT_PULLDOWN; // PhyAdd[1] = 1
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_05 = RMII_PAD_INPUT_PULLUP; // Slave mode
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_11 = RMII_PAD_INPUT_PULLDOWN; // Auto MDIX
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_07 = RMII_PAD_INPUT_PULLUP;
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_08 = RMII_PAD_INPUT_PULLUP;
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_09 = RMII_PAD_INPUT_PULLUP;
|
||||||
|
IOMUXC_SW_PAD_CTL_PAD_GPIO_B1_10 = RMII_PAD_CLOCK;
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_05 = 3; // RXD1 B1_05 Alt3, pg 525
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_04 = 3; // RXD0 B1_04 Alt3, pg 524
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_10 = 6 | 0x10; // REFCLK B1_10 Alt6, pg 530
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_11 = 3; // RXER B1_11 Alt3, pg 531
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_06 = 3; // RXEN B1_06 Alt3, pg 526
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_09 = 3; // TXEN B1_09 Alt3, pg 529
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_07 = 3; // TXD0 B1_07 Alt3, pg 527
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_08 = 3; // TXD1 B1_08 Alt3, pg 528
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_15 = 0; // MDIO B1_15 Alt0, pg 535
|
||||||
|
IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_14 = 0; // MDC B1_14 Alt0, pg 534
|
||||||
|
IOMUXC_ENET_MDIO_SELECT_INPUT = 2; // GPIO_B1_15_ALT0, pg 792
|
||||||
|
IOMUXC_ENET0_RXDATA_SELECT_INPUT = 1; // GPIO_B1_04_ALT3, pg 792
|
||||||
|
IOMUXC_ENET1_RXDATA_SELECT_INPUT = 1; // GPIO_B1_05_ALT3, pg 793
|
||||||
|
IOMUXC_ENET_RXEN_SELECT_INPUT = 1; // GPIO_B1_06_ALT3, pg 794
|
||||||
|
IOMUXC_ENET_RXERR_SELECT_INPUT = 1; // GPIO_B1_11_ALT3, pg 795
|
||||||
|
IOMUXC_ENET_IPG_CLK_RMII_SELECT_INPUT = 1; // GPIO_B1_10_ALT6, pg 791
|
||||||
|
delay(1);
|
||||||
|
GPIO7_DR_SET = (1 << 14); // Start PHY chip
|
||||||
|
// ENET_MSCR = ENET_MSCR_MII_SPEED(9);
|
||||||
|
delay(1);
|
||||||
|
|
||||||
|
// Setup IRQ handler
|
||||||
|
attachInterruptVector(IRQ_ENET, ENET_IRQHandler);
|
||||||
|
NVIC_ENABLE_IRQ(IRQ_ENET);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../mongoose.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../mongoose.h
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define MG_ARCH MG_ARCH_CUSTOM
|
||||||
|
#define MG_ENABLE_SOCKET 0
|
||||||
|
#define MG_ENABLE_TCPIP 1
|
||||||
|
#define MG_ENABLE_DRIVER_W5500 1
|
||||||
|
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
|
||||||
|
#define mkdir(a, b) (-1)
|
||||||
|
#define MG_IO_SIZE 128
|
||||||
|
//#define MG_ENABLE_LOG 0
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include <SPI.h>
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
#define SS_PIN 3 // Slave select pin
|
||||||
|
struct mg_mgr mgr; // Mongoose event manager
|
||||||
|
struct mg_tcpip_spi spi = {
|
||||||
|
NULL, // SPI data
|
||||||
|
[](void *) { digitalWrite(SS_PIN, LOW); }, // begin transation
|
||||||
|
[](void *) { digitalWrite(SS_PIN, HIGH); }, // end transaction
|
||||||
|
[](void *, uint8_t c) { return SPI.transfer(c); }, // execute transaction
|
||||||
|
};
|
||||||
|
struct mg_tcpip_if mif = {.mac = {2, 0, 1, 2, 3, 5}}; // network interface
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
pinMode(SS_PIN, OUTPUT);
|
||||||
|
SPI.begin();
|
||||||
|
|
||||||
|
// Set logging function to a serial print
|
||||||
|
mg_log_set_fn([](char ch, void *) { Serial.print(ch); }, NULL);
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
|
||||||
|
delay(3000);
|
||||||
|
MG_INFO(("Starting TCP/IP stack..."));
|
||||||
|
|
||||||
|
mif.driver = &mg_tcpip_driver_w5500;
|
||||||
|
mif.driver_data = &spi;
|
||||||
|
mg_tcpip_init(&mgr, &mif);
|
||||||
|
|
||||||
|
// Start a 5 sec timer, print status message periodically
|
||||||
|
mg_timer_add(
|
||||||
|
&mgr, 5000, MG_TIMER_REPEAT,
|
||||||
|
[](void *) {
|
||||||
|
MG_INFO(("ethernet: %s", mg_tcpip_driver_w5500.up(&mif) ? "up" : "down"));
|
||||||
|
},
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
// Setup HTTP listener. Respond "ok" on any HTTP request
|
||||||
|
mg_http_listen(
|
||||||
|
&mgr, "http://0.0.0.0",
|
||||||
|
[](struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "ok\n");
|
||||||
|
},
|
||||||
|
&mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
mg_mgr_poll(&mgr, 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../mongoose.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../mongoose.h
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define MG_ARCH MG_ARCH_CUSTOM
|
||||||
|
#define MG_ENABLE_SOCKET 0
|
||||||
|
#define MG_ENABLE_TCPIP 1
|
||||||
|
#define MG_ENABLE_DRIVER_W5500 1
|
||||||
|
#define MG_ENABLE_TCPIP_DRIVER_INIT 0
|
||||||
|
#define mkdir(a, b) (-1)
|
||||||
|
#define MG_IO_SIZE 512
|
||||||
|
//#define MG_ENABLE_LOG 0
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
#include "net.h"
|
||||||
|
|
||||||
|
#define MQTT_SERVER "mqtt://broker.hivemq.com:1883"
|
||||||
|
struct mg_connection *mqtt_connection;
|
||||||
|
const char *mqtt_subscribe_topic = "mg/rx";
|
||||||
|
const char *mqtt_publish_topic = "mg/tx";
|
||||||
|
|
||||||
|
struct mg_mgr mgr; // Mongoose event manager
|
||||||
|
struct mg_tcpip_if mif = {.mac = {2, 0, 1, 2, 3, 5}}; // network interface
|
||||||
|
|
||||||
|
void mqtt_publish(const char *message) {
|
||||||
|
struct mg_mqtt_opts opts = {};
|
||||||
|
opts.topic = mg_str(mqtt_publish_topic);
|
||||||
|
opts.message = mg_str(message);
|
||||||
|
if (mqtt_connection) mg_mqtt_pub(mqtt_connection, &opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_MQTT_OPEN) {
|
||||||
|
MG_INFO(("%lu CONNECTED to %s", c->id, MQTT_SERVER));
|
||||||
|
struct mg_mqtt_opts opts = {};
|
||||||
|
opts.topic = mg_str(mqtt_subscribe_topic);
|
||||||
|
mg_mqtt_sub(c, &opts);
|
||||||
|
MG_INFO(("%lu SUBSCRIBED to %s", c->id, mqtt_subscribe_topic));
|
||||||
|
} else if (ev == MG_EV_MQTT_MSG) {
|
||||||
|
// Received MQTT message
|
||||||
|
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
|
||||||
|
MG_INFO(("%lu RECEIVED %.*s <- %.*s", c->id, (int) mm->data.len,
|
||||||
|
mm->data.buf, (int) mm->topic.len, mm->topic.buf));
|
||||||
|
exec_command(mm->data.buf, mm->data.len);
|
||||||
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
|
MG_INFO(("%lu CLOSED", c->id));
|
||||||
|
mqtt_connection = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_fn(void *arg) {
|
||||||
|
struct mg_mgr *mgr = (struct mg_mgr *) arg;
|
||||||
|
struct mg_mqtt_opts opts;
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
opts.clean = true;
|
||||||
|
if (mif.state == MG_TCPIP_STATE_READY && mqtt_connection == NULL) {
|
||||||
|
mqtt_connection = mg_mqtt_connect(mgr, MQTT_SERVER, &opts, fn, NULL);
|
||||||
|
}
|
||||||
|
// MG_INFO(("Eth: %d, MQTT: %p", mif.state, mqtt_connection));
|
||||||
|
}
|
||||||
|
|
||||||
|
void net_init(void) {
|
||||||
|
// Set Mongoose logging function to a serial print
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
|
||||||
|
mif.driver = &mg_tcpip_driver_w5500;
|
||||||
|
mif.driver_data = &spi;
|
||||||
|
mg_tcpip_init(&mgr, &mif);
|
||||||
|
|
||||||
|
// Start a timer that keeps MQTT connection alive
|
||||||
|
mg_timer_add(&mgr, 3000, MG_TIMER_REPEAT, timer_fn, &mgr);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern struct mg_tcpip_spi spi;
|
||||||
|
extern struct mg_mgr mgr;
|
||||||
|
void mqtt_publish(const char *message);
|
||||||
|
void net_init(void);
|
||||||
|
void exec_command(const char *req, size_t req_len);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#include <SPI.h>
|
||||||
|
#include "net.h"
|
||||||
|
|
||||||
|
#define SS_PIN 17 // Slave select pin
|
||||||
|
struct mg_tcpip_spi spi = {
|
||||||
|
NULL, // SPI data
|
||||||
|
[](void *) { digitalWrite(SS_PIN, LOW); }, // Begin transaction
|
||||||
|
[](void *) { digitalWrite(SS_PIN, HIGH); }, // End transaction
|
||||||
|
[](void *, uint8_t c) { return SPI.transfer(c); }, // Execute transaction
|
||||||
|
};
|
||||||
|
|
||||||
|
void exec_command(const char *req, size_t req_len) {
|
||||||
|
char res[100];
|
||||||
|
if (req_len == 2 && strncmp(req, "on", req_len) == 0) {
|
||||||
|
digitalWrite(LED_BUILTIN, true);
|
||||||
|
snprintf(res, sizeof(res), "LED on");
|
||||||
|
} else if (req_len == 3 && strncmp(req, "off", req_len) == 0) {
|
||||||
|
digitalWrite(LED_BUILTIN, false);
|
||||||
|
snprintf(res, sizeof(res), "LED off");
|
||||||
|
} else {
|
||||||
|
snprintf(res, sizeof(res), "Unknown command: [%.*s]", (int) req_len, req);
|
||||||
|
}
|
||||||
|
Serial.println(res);
|
||||||
|
mqtt_publish(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_input(char c) {
|
||||||
|
static char buf[100];
|
||||||
|
static size_t len = 0;
|
||||||
|
char response[100];
|
||||||
|
if (c != '\n' && c != '\0') buf[len++] = c; // Append to the buffer
|
||||||
|
if (len >= sizeof(buf)) len = 0; // On overflow, reset
|
||||||
|
if (c == '\n' && len > 0) {
|
||||||
|
exec_command(buf, len);
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
SPI.begin();
|
||||||
|
pinMode(SS_PIN, OUTPUT);
|
||||||
|
pinMode(LED_BUILTIN, OUTPUT);
|
||||||
|
mg_log_set_fn([](char ch, void *) { Serial.print(ch); }, NULL);
|
||||||
|
net_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (Serial.available()) process_input(Serial.read());
|
||||||
|
mg_mgr_poll(&mgr, 1);
|
||||||
|
}
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
PROG ?= example
|
|
||||||
CFLAGS ?= -DMG_IO_SIZE=8192 -DMG_ENABLE_LINES
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
$(DEBUGGER) ./$(PROG) $(ARGS)
|
|
||||||
|
|
||||||
$(PROG): main.c
|
|
||||||
$(CC) ../../mongoose.c -I../.. -W -Wall $(CFLAGS) -o $(PROG) main.c
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
See detailed tutorial at https://mongoose.ws/tutorials/captive-dns-portal/
|
|
||||||
@@ -1,40 +1,56 @@
|
|||||||
PROG ?= example
|
PROG ?= ./example # Program we are building
|
||||||
SOURCES ?= ../../mongoose.c main.c net.c packed_fs.c
|
PACK ?= ./pack # Packing executable
|
||||||
CFLAGS ?= -I../.. -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_LINES=1 $(EXTRA)
|
DELETE = rm -rf # Command to remove files
|
||||||
FILES_TO_EMBED ?= $(wildcard web_root/*)
|
GZIP ?= gzip # For compressing files in web_root/
|
||||||
ROOT ?= $(realpath $(CURDIR)/../../..)
|
OUT ?= -o $(PROG) # Compiler argument for output file
|
||||||
DOCKER ?= docker run --rm -e Tmp=. -e WINEDEBUG=-all -v $(ROOT):$(ROOT) -w $(CURDIR)
|
SOURCES = main.c mongoose.c net.c packed_fs.c # Source code files
|
||||||
VC98 ?= $(DOCKER) mdashnet/vc98 wine
|
CFLAGS = -W -Wall -Wextra -g -I. # Build options
|
||||||
MINGW ?= $(DOCKER) mdashnet/mingw
|
NPX ?= npx
|
||||||
|
|
||||||
ifeq "$(SSL)" "MBEDTLS"
|
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
|
||||||
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
CFLAGS_MONGOOSE += -DMG_ENABLE_PACKED_FS=1
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq "$(SSL)" "OPENSSL"
|
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
|
||||||
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include -L$(OPENSSL)/lib -lssl -lcrypto
|
PROG = example.exe # Use .exe suffix for the binary
|
||||||
|
PACK = pack.exe # Packing executable
|
||||||
|
CC = gcc # Use MinGW gcc compiler
|
||||||
|
CFLAGS += -lws2_32 # Link against Winsock library
|
||||||
|
DELETE = cmd /C del /Q /F /S # Command prompt command to delete files
|
||||||
|
GZIP = echo # No gzip on Windows
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Default target. Build and run program
|
||||||
all: $(PROG)
|
all: $(PROG)
|
||||||
$(RUN) ./$(PROG)
|
$(RUN) $(PROG) $(ARGS)
|
||||||
|
|
||||||
$(PROG): $(SOURCES) $(FILES_TO_EMBED)
|
# Build program from sources
|
||||||
$(CC) ../../test/pack.c -o pack
|
$(PROG): $(SOURCES)
|
||||||
./pack $(FILES_TO_EMBED) > packed_fs.c
|
$(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(OUT)
|
||||||
$(CC) -W -Wall -Wextra -O0 -g3 $(CFLAGS) -o $(PROG) $(SOURCES)
|
|
||||||
|
|
||||||
|
# Bundle JS libraries (preact, preact-router, ...) into a single file
|
||||||
|
web_root/bundle.js:
|
||||||
|
curl -s https://npm.reversehttp.com/preact,preact/hooks,htm/preact,preact-router -o $@
|
||||||
|
|
||||||
mingw: $(SOURCES) $(FILES_TO_EMBED)
|
# Create optimised CSS. Prerequisite: npm -g i tailwindcss tailwindcss-font-inter
|
||||||
$(MINGW) i686-w64-mingw32-gcc $(CFLAGS) ../../test/pack.c -o pack.exe
|
web_root/main.css: web_root/index.html $(wildcard web_root/*.js)
|
||||||
$(MINGW) wine cmd /c 'pack.exe $(FILES_TO_EMBED) > packed_fs.c'
|
$(NPX) tailwindcss -o $@ --minify
|
||||||
$(MINGW) i686-w64-mingw32-gcc $(CFLAGS) $(SOURCES) -lws2_32 -o $(PROG).exe
|
|
||||||
$(MINGW) wine $(PROG).exe
|
|
||||||
|
|
||||||
vc98: $(SOURCES) $(FILES_TO_EMBED)
|
# Generate packed filesystem for serving Web UI
|
||||||
$(VC98) cl.exe /nologo $(CFLAGS) ../../test/pack.c /Fepack.exe
|
packed_fs.c: $(wildcard web_root/*) $(wildcard certs/*) Makefile web_root/main.css web_root/bundle.js
|
||||||
$(VC98) cmd /c 'pack.exe $(FILES_TO_EMBED) > packed_fs.c'
|
$(GZIP) web_root/*
|
||||||
$(VC98) cl.exe /nologo /O2 $(CFLAGS) $(SOURCES) /Fe$(PROG).exe
|
$(CC) ../../test/pack.c -o $(PACK)
|
||||||
$(VC98) $(PROG).exe
|
$(PACK) web_root/* certs/* > $@
|
||||||
|
$(GZIP) -d web_root/*
|
||||||
|
|
||||||
|
mbedtls:
|
||||||
|
git clone --depth 1 -b v2.28.2 https://github.com/mbed-tls/mbedtls $@
|
||||||
|
|
||||||
|
ifeq ($(TLS), mbedtls)
|
||||||
|
CFLAGS += -DMG_TLS=MG_TLS_MBED -Wno-conversion -Imbedtls/include
|
||||||
|
CFLAGS += -DMBEDTLS_CONFIG_FILE=\"mbedtls_config.h\" mbedtls/library/*.c
|
||||||
|
$(PROG): mbedtls
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Cleanup. Delete built program and all build artifacts
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb log.txt pack
|
$(DELETE) $(PROG) $(PACK) *.o *.obj *.exe *.dSYM mbedtls
|
||||||
@@ -5,23 +5,9 @@ into an embedded device and provide a complete device dashboard with the
|
|||||||
following features:
|
following features:
|
||||||
|
|
||||||
- Authentication: login-protected dashboard
|
- Authentication: login-protected dashboard
|
||||||
- Multiple logins with different permissions (admin and user)
|
- Multiple logins (with possibly different permissions)
|
||||||
- Web UI is fully embedded into the server/firmware binary, and does not
|
- The Web UI can be fully embedded into the firmware binary, then not
|
||||||
need a filesystem to serve it. UI is resilient to FS problems
|
needing a filesystem to serve it; so being resilient to FS problems
|
||||||
- Administrators can change server settings
|
- All changes are propagated to all connected clients
|
||||||
- All changes are propagates to all connected clients
|
|
||||||
- A device is connected to the external MQTT server
|
|
||||||
- Logged in clients can send/receive messages to a device which get
|
|
||||||
forwarded to MQTT
|
|
||||||
|
|
||||||
# Screenshots
|
See a detailed tutorial at https://mongoose.ws/tutorials/device-dashboard/
|
||||||
|
|
||||||
This is a login screen that prompts for user/password
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
# Main dashboard
|
|
||||||
|
|
||||||
A main dashboard page shows and interactive MQTT console
|
|
||||||
|
|
||||||

|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../test/data/ca.pem
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIBCTCBsAIJAK9wbIDkHnAoMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAklFMB4X
|
||||||
|
DTIzMDEyOTIxMjEzOFoXDTMzMDEyNjIxMjEzOFowDTELMAkGA1UEBhMCSUUwWTAT
|
||||||
|
BgcqhkjOPQIBBggqhkjOPQMBBwNCAARzSQS5OHd17lUeNI+6kp9WYu0cxuEIi/JT
|
||||||
|
jphbCmdJD1cUvhmzM9/phvJT9ka10Z9toZhgnBq0o0xfTQ4jC1vwMAoGCCqGSM49
|
||||||
|
BAMCA0gAMEUCIQCe0T2E0GOiVe9KwvIEPeX1J1J0T7TNacgR0Ya33HV9VgIgNvdn
|
||||||
|
aEWiBp1xshs4iz6WbpxrS1IHucrqkZuJLfNZGZI=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-----BEGIN EC PRIVATE KEY-----
|
||||||
|
MHcCAQEEICBz3HOkQLPBDtdknqC7k1PNsWj6HfhyNB5MenfjmqiooAoGCCqGSM49
|
||||||
|
AwEHoUQDQgAEc0kEuTh3de5VHjSPupKfVmLtHMbhCIvyU46YWwpnSQ9XFL4ZszPf
|
||||||
|
6YbyU/ZGtdGfbaGYYJwatKNMX00OIwtb8A==
|
||||||
|
-----END EC PRIVATE KEY-----
|
||||||
@@ -1,18 +1,32 @@
|
|||||||
// Copyright (c) 2020-2022 Cesanta Software Limited
|
// Copyright (c) 2020-2023 Cesanta Software Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
|
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
const char *s_listening_url = "http://0.0.0.0:8000";
|
#include "net.h"
|
||||||
|
|
||||||
void device_dashboard_fn(struct mg_connection *, int, void *, void *);
|
static int s_sig_num;
|
||||||
|
static void signal_handler(int sig_num) {
|
||||||
|
signal(sig_num, signal_handler);
|
||||||
|
s_sig_num = sig_num;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_mgr mgr;
|
struct mg_mgr mgr;
|
||||||
|
|
||||||
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
signal(SIGINT, signal_handler);
|
||||||
|
signal(SIGTERM, signal_handler);
|
||||||
|
|
||||||
mg_log_set(MG_LL_DEBUG); // Set debug log level
|
mg_log_set(MG_LL_DEBUG); // Set debug log level
|
||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, &mgr);
|
|
||||||
MG_INFO(("Listening on %s", s_listening_url));
|
web_init(&mgr);
|
||||||
while (mgr.conns != NULL) mg_mgr_poll(&mgr, 500);
|
while (s_sig_num == 0) {
|
||||||
|
mg_mgr_poll(&mgr, 50);
|
||||||
|
}
|
||||||
|
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
|
MG_INFO(("Exiting on signal %d", s_sig_num));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/* Workaround for some mbedtls source files using INT_MAX without including limits.h */
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||||
|
//#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||||
|
#define MBEDTLS_SSL_OUT_CONTENT_LEN 2048
|
||||||
|
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||||
|
#define MBEDTLS_HAVE_TIME
|
||||||
|
#define MBEDTLS_SSL_SESSION_TICKETS
|
||||||
|
|
||||||
|
#define MBEDTLS_CIPHER_MODE_CBC
|
||||||
|
#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_BP256R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_BP384R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_BP512R1_ENABLED
|
||||||
|
#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
||||||
|
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||||
|
#define MBEDTLS_PKCS1_V15
|
||||||
|
#define MBEDTLS_SHA256_SMALLER
|
||||||
|
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||||
|
#define MBEDTLS_AES_C
|
||||||
|
#define MBEDTLS_ASN1_PARSE_C
|
||||||
|
#define MBEDTLS_BIGNUM_C
|
||||||
|
#define MBEDTLS_CIPHER_C
|
||||||
|
#define MBEDTLS_CTR_DRBG_C
|
||||||
|
#define MBEDTLS_ENTROPY_C
|
||||||
|
#define MBEDTLS_ERROR_C
|
||||||
|
#define MBEDTLS_MD_C
|
||||||
|
#define MBEDTLS_MD5_C
|
||||||
|
#define MBEDTLS_OID_C
|
||||||
|
#define MBEDTLS_PKCS5_C
|
||||||
|
#define MBEDTLS_PK_C
|
||||||
|
#define MBEDTLS_PK_PARSE_C
|
||||||
|
#define MBEDTLS_PLATFORM_C
|
||||||
|
#define MBEDTLS_RSA_C
|
||||||
|
#define MBEDTLS_SHA1_C
|
||||||
|
#define MBEDTLS_SHA224_C
|
||||||
|
#define MBEDTLS_SHA256_C
|
||||||
|
#define MBEDTLS_SHA512_C
|
||||||
|
#define MBEDTLS_SSL_CLI_C
|
||||||
|
#define MBEDTLS_SSL_SRV_C
|
||||||
|
#define MBEDTLS_SSL_TLS_C
|
||||||
|
#define MBEDTLS_X509_CRT_PARSE_C
|
||||||
|
#define MBEDTLS_X509_USE_C
|
||||||
|
#define MBEDTLS_AES_FEWER_TABLES
|
||||||
|
#define MBEDTLS_PEM_PARSE_C
|
||||||
|
#define MBEDTLS_BASE64_C
|
||||||
|
#define MBEDTLS_SSL_TICKET_C
|
||||||
|
|
||||||
|
#define MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||||
|
#define MBEDTLS_GCM_C
|
||||||
|
#define MBEDTLS_ECDH_C
|
||||||
|
#define MBEDTLS_ECP_C
|
||||||
|
#define MBEDTLS_ECDSA_C
|
||||||
|
#define MBEDTLS_ASN1_WRITE_C
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../mongoose.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../mongoose.h
|
||||||
@@ -1,217 +1,306 @@
|
|||||||
// Copyright (c) 2020-2022 Cesanta Software Limited
|
// Copyright (c) 2023 Cesanta Software Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
|
|
||||||
#include "mongoose.h"
|
#include "net.h"
|
||||||
|
|
||||||
#define MQTT_SERVER "mqtt://broker.hivemq.com:1883"
|
|
||||||
#define MQTT_PUBLISH_TOPIC "mg/my_device"
|
|
||||||
#define MQTT_SUBSCRIBE_TOPIC "mg/#"
|
|
||||||
|
|
||||||
static time_t s_boot_timestamp = 0; // Updated by SNTP
|
|
||||||
static struct mg_connection *s_sntp_conn = NULL; // SNTP connection
|
|
||||||
|
|
||||||
// Define system time()
|
|
||||||
time_t time(time_t *tp) {
|
|
||||||
time_t t = s_boot_timestamp + (time_t) (mg_millis() / 1000);
|
|
||||||
if (tp != NULL) *tp = t;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Authenticated user.
|
// Authenticated user.
|
||||||
// A user can be authenticated by:
|
// A user can be authenticated by:
|
||||||
// - a name:pass pair
|
// - a name:pass pair, passed in a header Authorization: Basic .....
|
||||||
// - a token
|
// - an access_token, passed in a header Cookie: access_token=....
|
||||||
// When a user is shown a login screen, she enters a user:pass. If successful,
|
// When a user is shown a login screen, she enters a user:pass. If successful,
|
||||||
// a server returns user info which includes token. From that point on,
|
// a server responds with a http-only access_token cookie set.
|
||||||
// client can use token for authentication. Tokens could be refreshed/changed
|
|
||||||
// on a server side, forcing clients to re-login.
|
|
||||||
struct user {
|
struct user {
|
||||||
const char *name, *pass, *token;
|
const char *name, *pass, *access_token;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is a configuration structure we're going to show on a dashboard
|
// Settings
|
||||||
static struct config {
|
struct settings {
|
||||||
char *url, *pub, *sub; // MQTT settings
|
bool log_enabled;
|
||||||
} s_config;
|
int log_level;
|
||||||
|
long brightness;
|
||||||
|
char *device_name;
|
||||||
|
};
|
||||||
|
|
||||||
static struct mg_connection *s_mqtt = NULL; // MQTT connection
|
static struct settings s_settings = {true, 1, 57, NULL};
|
||||||
static bool s_connected = false; // MQTT connection established
|
|
||||||
|
|
||||||
// Try to update a single configuration value
|
static const char *s_json_header =
|
||||||
static void update_config(struct mg_str *body, const char *name, char **value) {
|
"Content-Type: application/json\r\n"
|
||||||
char buf[256];
|
"Cache-Control: no-cache\r\n";
|
||||||
if (mg_http_get_var(body, name, buf, sizeof(buf)) > 0) {
|
|
||||||
free(*value);
|
int ui_event_next(int no, struct ui_event *e) {
|
||||||
*value = strdup(buf);
|
if (no < 0 || no >= MAX_EVENTS_NO) return 0;
|
||||||
}
|
|
||||||
|
srand((unsigned) no);
|
||||||
|
e->type = (uint8_t) rand() % 4;
|
||||||
|
e->prio = (uint8_t) rand() % 3;
|
||||||
|
e->timestamp =
|
||||||
|
(unsigned long) ((int64_t) mg_now() - 86400 * 1000 /* one day back */ +
|
||||||
|
no * 300 * 1000 /* 5 mins between alerts */ +
|
||||||
|
1000 * (rand() % 300) /* randomize event time */) /
|
||||||
|
1000UL;
|
||||||
|
|
||||||
|
mg_snprintf(e->text, MAX_EVENT_TEXT_SIZE, "event#%d", no);
|
||||||
|
return no + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time
|
||||||
|
mg_sntp_connect(param, "udp://time.google.com:123", NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse HTTP requests, return authenticated user or NULL
|
// Parse HTTP requests, return authenticated user or NULL
|
||||||
static struct user *getuser(struct mg_http_message *hm) {
|
static struct user *authenticate(struct mg_http_message *hm) {
|
||||||
// In production, make passwords strong and tokens randomly generated
|
// In production, make passwords strong and tokens randomly generated
|
||||||
// In this example, user list is kept in RAM. In production, it can
|
// In this example, user list is kept in RAM. In production, it can
|
||||||
// be backed by file, database, or some other method.
|
// be backed by file, database, or some other method.
|
||||||
static struct user users[] = {
|
static struct user users[] = {
|
||||||
{"admin", "pass0", "admin_token"},
|
{"admin", "admin", "admin_token"},
|
||||||
{"user1", "pass1", "user1_token"},
|
{"user1", "user1", "user1_token"},
|
||||||
{"user2", "pass2", "user2_token"},
|
{"user2", "user2", "user2_token"},
|
||||||
{NULL, NULL, NULL},
|
{NULL, NULL, NULL},
|
||||||
};
|
};
|
||||||
char user[256], pass[256];
|
char user[64], pass[64];
|
||||||
struct user *u;
|
struct user *u, *result = NULL;
|
||||||
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
|
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
|
||||||
|
MG_VERBOSE(("user [%s] pass [%s]", user, pass));
|
||||||
|
|
||||||
if (user[0] != '\0' && pass[0] != '\0') {
|
if (user[0] != '\0' && pass[0] != '\0') {
|
||||||
// Both user and password is set, search by user/password
|
// Both user and password is set, search by user/password
|
||||||
for (u = users; u->name != NULL; u++)
|
for (u = users; result == NULL && u->name != NULL; u++)
|
||||||
if (strcmp(user, u->name) == 0 && strcmp(pass, u->pass) == 0) return u;
|
if (strcmp(user, u->name) == 0 && strcmp(pass, u->pass) == 0) result = u;
|
||||||
} else if (user[0] == '\0') {
|
} else if (user[0] == '\0') {
|
||||||
// Only password is set, search by token
|
// Only password is set, search by token
|
||||||
for (u = users; u->name != NULL; u++)
|
for (u = users; result == NULL && u->name != NULL; u++)
|
||||||
if (strcmp(pass, u->token) == 0) return u;
|
if (strcmp(pass, u->access_token) == 0) result = u;
|
||||||
}
|
}
|
||||||
return NULL;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify all config watchers about the config change
|
static void handle_login(struct mg_connection *c, struct user *u) {
|
||||||
static void send_notification(struct mg_mgr *mgr, const char *fmt, ...) {
|
char cookie[256];
|
||||||
struct mg_connection *c;
|
mg_snprintf(cookie, sizeof(cookie),
|
||||||
for (c = mgr->conns; c != NULL; c = c->next) {
|
"Set-Cookie: access_token=%s; Path=/; "
|
||||||
if (c->label[0] == 'W') {
|
"%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n",
|
||||||
va_list ap;
|
u->access_token, c->is_tls ? "Secure; " : "", 3600 * 24);
|
||||||
va_start(ap, fmt);
|
mg_http_reply(c, 200, cookie, "{%m:%m}", MG_ESC("user"), MG_ESC(u->name));
|
||||||
mg_ws_vprintf(c, WEBSOCKET_OP_TEXT, fmt, &ap);
|
}
|
||||||
va_end(ap);
|
|
||||||
|
static void handle_logout(struct mg_connection *c) {
|
||||||
|
char cookie[256];
|
||||||
|
mg_snprintf(cookie, sizeof(cookie),
|
||||||
|
"Set-Cookie: access_token=; Path=/; "
|
||||||
|
"Expires=Thu, 01 Jan 1970 00:00:00 UTC; "
|
||||||
|
"%sHttpOnly; Max-Age=0; \r\n",
|
||||||
|
c->is_tls ? "Secure; " : "");
|
||||||
|
mg_http_reply(c, 200, cookie, "true\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_debug(struct mg_connection *c, struct mg_http_message *hm) {
|
||||||
|
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
|
||||||
|
mg_log_set(level);
|
||||||
|
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t print_int_arr(void (*out)(char, void *), void *ptr, va_list *ap) {
|
||||||
|
size_t i, len = 0, num = va_arg(*ap, size_t); // Number of items in the array
|
||||||
|
int *arr = va_arg(*ap, int *); // Array ptr
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
len += mg_xprintf(out, ptr, "%s%d", i == 0 ? "" : ",", arr[i]);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_stats_get(struct mg_connection *c) {
|
||||||
|
int points[] = {21, 22, 22, 19, 18, 20, 23, 23, 22, 22, 22, 23, 22};
|
||||||
|
mg_http_reply(c, 200, s_json_header, "{%m:%d,%m:%d,%m:[%M]}\n",
|
||||||
|
MG_ESC("temperature"), 21, //
|
||||||
|
MG_ESC("humidity"), 67, //
|
||||||
|
MG_ESC("points"), print_int_arr,
|
||||||
|
sizeof(points) / sizeof(points[0]), points);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t print_events(void (*out)(char, void *), void *ptr, va_list *ap) {
|
||||||
|
size_t len = 0;
|
||||||
|
struct ui_event ev;
|
||||||
|
int pageno = va_arg(*ap, int);
|
||||||
|
int no = (pageno - 1) * EVENTS_PER_PAGE;
|
||||||
|
int end = no + EVENTS_PER_PAGE;
|
||||||
|
|
||||||
|
while ((no = ui_event_next(no, &ev)) != 0 && no <= end) {
|
||||||
|
len += mg_xprintf(out, ptr, "%s{%m:%lu,%m:%d,%m:%d,%m:%m}\n", //
|
||||||
|
len == 0 ? "" : ",", //
|
||||||
|
MG_ESC("time"), ev.timestamp, //
|
||||||
|
MG_ESC("type"), ev.type, //
|
||||||
|
MG_ESC("prio"), ev.prio, //
|
||||||
|
MG_ESC("text"), MG_ESC(ev.text));
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_events_get(struct mg_connection *c,
|
||||||
|
struct mg_http_message *hm) {
|
||||||
|
int pageno = mg_json_get_long(hm->body, "$.page", 1);
|
||||||
|
mg_http_reply(c, 200, s_json_header, "{%m:[%M], %m:%d}\n", MG_ESC("arr"),
|
||||||
|
print_events, pageno, MG_ESC("totalCount"), MAX_EVENTS_NO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_settings_set(struct mg_connection *c, struct mg_str body) {
|
||||||
|
struct settings settings;
|
||||||
|
char *s = mg_json_get_str(body, "$.device_name");
|
||||||
|
bool ok = true;
|
||||||
|
memset(&settings, 0, sizeof(settings));
|
||||||
|
mg_json_get_bool(body, "$.log_enabled", &settings.log_enabled);
|
||||||
|
settings.log_level = mg_json_get_long(body, "$.log_level", 0);
|
||||||
|
settings.brightness = mg_json_get_long(body, "$.brightness", 0);
|
||||||
|
if (s && strlen(s) < MAX_DEVICE_NAME) {
|
||||||
|
free(settings.device_name);
|
||||||
|
settings.device_name = s;
|
||||||
|
} else {
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
s_settings = settings; // Save to the device flash
|
||||||
|
mg_http_reply(c, 200, s_json_header,
|
||||||
|
"{%m:%s,%m:%m}", //
|
||||||
|
MG_ESC("status"), ok ? "true" : "false", //
|
||||||
|
MG_ESC("message"), MG_ESC(ok ? "Success" : "Failed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_settings_get(struct mg_connection *c) {
|
||||||
|
mg_http_reply(c, 200, s_json_header, "{%m:%s,%m:%hhu,%m:%hhu,%m:%m}\n", //
|
||||||
|
MG_ESC("log_enabled"),
|
||||||
|
s_settings.log_enabled ? "true" : "false", //
|
||||||
|
MG_ESC("log_level"), s_settings.log_level, //
|
||||||
|
MG_ESC("brightness"), s_settings.brightness, //
|
||||||
|
MG_ESC("device_name"), MG_ESC(s_settings.device_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_firmware_upload(struct mg_connection *c,
|
||||||
|
struct mg_http_message *hm) {
|
||||||
|
char name[64], offset[20], total[20];
|
||||||
|
struct mg_str data = hm->body;
|
||||||
|
long ofs = -1, tot = -1;
|
||||||
|
name[0] = offset[0] = '\0';
|
||||||
|
mg_http_get_var(&hm->query, "name", name, sizeof(name));
|
||||||
|
mg_http_get_var(&hm->query, "offset", offset, sizeof(offset));
|
||||||
|
mg_http_get_var(&hm->query, "total", total, sizeof(total));
|
||||||
|
MG_INFO(("File %s, offset %s, len %lu", name, offset, data.len));
|
||||||
|
if ((ofs = mg_json_get_long(mg_str(offset), "$", -1)) < 0 ||
|
||||||
|
(tot = mg_json_get_long(mg_str(total), "$", -1)) < 0) {
|
||||||
|
mg_http_reply(c, 500, "", "offset and total not set\n");
|
||||||
|
} else if (ofs == 0 && mg_ota_begin((size_t) tot) == false) {
|
||||||
|
mg_http_reply(c, 500, "", "mg_ota_begin(%ld) failed\n", tot);
|
||||||
|
} else if (data.len > 0 && mg_ota_write(data.buf, data.len) == false) {
|
||||||
|
mg_http_reply(c, 500, "", "mg_ota_write(%lu) @%ld failed\n", data.len, ofs);
|
||||||
|
mg_ota_end();
|
||||||
|
} else if (data.len == 0 && mg_ota_end() == false) {
|
||||||
|
mg_http_reply(c, 500, "", "mg_ota_end() failed\n", tot);
|
||||||
|
} else {
|
||||||
|
mg_http_reply(c, 200, s_json_header, "true\n");
|
||||||
|
if (data.len == 0) {
|
||||||
|
// Successful mg_ota_end() called, schedule device reboot
|
||||||
|
mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_device_reset, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send simulated metrics data to the dashboard, for chart rendering
|
static void handle_firmware_commit(struct mg_connection *c) {
|
||||||
static void timer_metrics_fn(void *param) {
|
mg_http_reply(c, 200, s_json_header, "%s\n",
|
||||||
send_notification(param, "{%Q:%Q,%Q:[%lu, %d]}", "name", "metrics", "data",
|
mg_ota_commit() ? "true" : "false");
|
||||||
(unsigned long) time(NULL),
|
|
||||||
10 + (int) ((double) rand() * 10 / RAND_MAX));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MQTT event handler function
|
static void handle_firmware_rollback(struct mg_connection *c) {
|
||||||
static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
|
mg_http_reply(c, 200, s_json_header, "%s\n",
|
||||||
if (ev == MG_EV_CONNECT && mg_url_is_ssl(s_config.url)) {
|
mg_ota_rollback() ? "true" : "false");
|
||||||
struct mg_tls_opts opts = {.ca = "ca.pem",
|
|
||||||
.srvname = mg_url_host(s_config.url)};
|
|
||||||
mg_tls_init(c, &opts);
|
|
||||||
} else if (ev == MG_EV_MQTT_OPEN) {
|
|
||||||
s_connected = true;
|
|
||||||
c->is_hexdumping = 1;
|
|
||||||
mg_mqtt_sub(s_mqtt, mg_str(s_config.sub), 2);
|
|
||||||
send_notification(c->mgr, "{%Q:%Q,%Q:null}", "name", "config", "data");
|
|
||||||
} else if (ev == MG_EV_MQTT_MSG) {
|
|
||||||
struct mg_mqtt_message *mm = ev_data;
|
|
||||||
send_notification(c->mgr, "{%Q:%Q,%Q:{%Q: %.*Q, %Q: %.*Q, %Q: %d}}", "name",
|
|
||||||
"message", "data", "topic", (int) mm->topic.len,
|
|
||||||
mm->topic.ptr, "data", (int) mm->data.len, mm->data.ptr,
|
|
||||||
"qos", (int) mm->qos);
|
|
||||||
} else if (ev == MG_EV_MQTT_CMD) {
|
|
||||||
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
|
|
||||||
MG_DEBUG(("cmd %d qos %d", mm->cmd, mm->qos));
|
|
||||||
} else if (ev == MG_EV_CLOSE) {
|
|
||||||
s_mqtt = NULL;
|
|
||||||
if (s_connected) {
|
|
||||||
s_connected = false;
|
|
||||||
send_notification(c->mgr, "{%Q:%Q,%Q:null}", "name", "config", "data");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void) fnd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep MQTT connection open - reconnect if closed
|
static size_t print_status(void (*out)(char, void *), void *ptr, va_list *ap) {
|
||||||
static void timer_mqtt_fn(void *param) {
|
int fw = va_arg(*ap, int);
|
||||||
struct mg_mgr *mgr = (struct mg_mgr *) param;
|
return mg_xprintf(out, ptr, "{%m:%d,%m:%c%lx%c,%m:%u,%m:%u}\n",
|
||||||
if (s_mqtt == NULL) {
|
MG_ESC("status"), mg_ota_status(fw), MG_ESC("crc32"), '"',
|
||||||
struct mg_mqtt_opts opts = {0};
|
mg_ota_crc32(fw), '"', MG_ESC("size"), mg_ota_size(fw),
|
||||||
s_mqtt = mg_mqtt_connect(mgr, s_config.url, &opts, mqtt_fn, NULL);
|
MG_ESC("timestamp"), mg_ota_timestamp(fw));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SNTP connection event handler. When we get a response from an SNTP server,
|
static void handle_firmware_status(struct mg_connection *c) {
|
||||||
// adjust s_boot_timestamp. We'll get a valid time from that point on
|
mg_http_reply(c, 200, s_json_header, "[%M,%M]\n", print_status,
|
||||||
static void sfn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
MG_FIRMWARE_CURRENT, print_status, MG_FIRMWARE_PREVIOUS);
|
||||||
if (ev == MG_EV_SNTP_TIME) {
|
|
||||||
uint64_t t = *(uint64_t *) ev_data;
|
|
||||||
MG_INFO(("%lu SNTP: %lld ms from epoch", c->id, t));
|
|
||||||
s_boot_timestamp = (time_t) ((t - mg_millis()) / 1000);
|
|
||||||
c->is_closing = 1;
|
|
||||||
} else if (ev == MG_EV_CLOSE) {
|
|
||||||
s_sntp_conn = NULL;
|
|
||||||
}
|
|
||||||
(void) fn_data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time
|
static void handle_device_reset(struct mg_connection *c) {
|
||||||
struct mg_mgr *mgr = (struct mg_mgr *) param;
|
mg_http_reply(c, 200, s_json_header, "true\n");
|
||||||
if (s_sntp_conn == NULL && s_boot_timestamp == 0) {
|
mg_timer_add(c->mgr, 500, 0, (void (*)(void *)) mg_device_reset, NULL);
|
||||||
s_sntp_conn = mg_sntp_connect(mgr, NULL, sfn, NULL);
|
}
|
||||||
}
|
|
||||||
|
static void handle_device_eraselast(struct mg_connection *c) {
|
||||||
|
size_t ss = mg_flash_sector_size(), size = mg_flash_size();
|
||||||
|
char *base = (char *) mg_flash_start(), *last = base + size - ss;
|
||||||
|
if (mg_flash_bank() == 2) last -= size / 2;
|
||||||
|
mg_flash_erase(last);
|
||||||
|
mg_http_reply(c, 200, s_json_header, "true\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTP request handler function
|
// HTTP request handler function
|
||||||
void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data,
|
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
void *fn_data) {
|
if (ev == MG_EV_ACCEPT) {
|
||||||
if (ev == MG_EV_OPEN && c->is_listening) {
|
if (c->fn_data != NULL) { // TLS listener!
|
||||||
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_metrics_fn, c->mgr);
|
struct mg_tls_opts opts = {0};
|
||||||
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_mqtt_fn, c->mgr);
|
opts.cert = mg_unpacked("/certs/server_cert.pem");
|
||||||
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_sntp_fn, c->mgr);
|
opts.key = mg_unpacked("/certs/server_key.pem");
|
||||||
s_config.url = strdup(MQTT_SERVER);
|
mg_tls_init(c, &opts);
|
||||||
s_config.pub = strdup(MQTT_PUBLISH_TOPIC);
|
}
|
||||||
s_config.sub = strdup(MQTT_SUBSCRIBE_TOPIC);
|
|
||||||
} else if (ev == MG_EV_HTTP_MSG) {
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
struct user *u = getuser(hm);
|
struct user *u = authenticate(hm);
|
||||||
// MG_INFO(("%p [%.*s] auth %s", c->fd, (int) hm->uri.len, hm->uri.ptr,
|
|
||||||
// u ? u->name : "NULL"));
|
if (mg_match(hm->uri, mg_str("/api/#"), NULL) && u == NULL) {
|
||||||
if (mg_http_match_uri(hm, "/api/hi")) {
|
mg_http_reply(c, 403, "", "Not Authorised\n");
|
||||||
mg_http_reply(c, 200, "", "hi\n"); // Testing endpoint
|
} else if (mg_match(hm->uri, mg_str("/api/login"), NULL)) {
|
||||||
} else if (u == NULL && mg_http_match_uri(hm, "/api/#")) {
|
handle_login(c, u);
|
||||||
// All URIs starting with /api/ must be authenticated
|
} else if (mg_match(hm->uri, mg_str("/api/logout"), NULL)) {
|
||||||
mg_http_reply(c, 403, "", "Denied\n");
|
handle_logout(c);
|
||||||
} else if (mg_http_match_uri(hm, "/api/config/get")) {
|
} else if (mg_match(hm->uri, mg_str("/api/debug"), NULL)) {
|
||||||
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q,%Q:%Q,%Q:%s}\n", "url",
|
handle_debug(c, hm);
|
||||||
s_config.url, "pub", s_config.pub, "sub", s_config.sub,
|
} else if (mg_match(hm->uri, mg_str("/api/stats/get"), NULL)) {
|
||||||
"connected", s_connected ? "true" : "false");
|
handle_stats_get(c);
|
||||||
} else if (mg_http_match_uri(hm, "/api/config/set")) {
|
} else if (mg_match(hm->uri, mg_str("/api/events/get"), NULL)) {
|
||||||
// Admins only
|
handle_events_get(c, hm);
|
||||||
if (strcmp(u->name, "admin") == 0) {
|
} else if (mg_match(hm->uri, mg_str("/api/settings/get"), NULL)) {
|
||||||
update_config(&hm->body, "url", &s_config.url);
|
handle_settings_get(c);
|
||||||
update_config(&hm->body, "pub", &s_config.pub);
|
} else if (mg_match(hm->uri, mg_str("/api/settings/set"), NULL)) {
|
||||||
update_config(&hm->body, "sub", &s_config.sub);
|
handle_settings_set(c, hm->body);
|
||||||
if (s_mqtt) s_mqtt->is_closing = 1; // Ask to disconnect from MQTT
|
} else if (mg_match(hm->uri, mg_str("/api/firmware/upload"), NULL)) {
|
||||||
send_notification(fn_data, "{%Q:%Q,%Q:null}", "name", "config", "data");
|
handle_firmware_upload(c, hm);
|
||||||
mg_http_reply(c, 200, "", "ok\n");
|
} else if (mg_match(hm->uri, mg_str("/api/firmware/commit"), NULL)) {
|
||||||
} else {
|
handle_firmware_commit(c);
|
||||||
mg_http_reply(c, 403, "", "Denied\n");
|
} else if (mg_match(hm->uri, mg_str("/api/firmware/rollback"), NULL)) {
|
||||||
}
|
handle_firmware_rollback(c);
|
||||||
} else if (mg_http_match_uri(hm, "/api/message/send")) {
|
} else if (mg_match(hm->uri, mg_str("/api/firmware/status"), NULL)) {
|
||||||
char buf[256];
|
handle_firmware_status(c);
|
||||||
if (s_connected &&
|
} else if (mg_match(hm->uri, mg_str("/api/device/reset"), NULL)) {
|
||||||
mg_http_get_var(&hm->body, "message", buf, sizeof(buf)) > 0) {
|
handle_device_reset(c);
|
||||||
mg_mqtt_pub(s_mqtt, mg_str(s_config.pub), mg_str(buf), 1, false);
|
} else if (mg_match(hm->uri, mg_str("/api/device/eraselast"), NULL)) {
|
||||||
}
|
handle_device_eraselast(c);
|
||||||
mg_http_reply(c, 200, "", "ok\n");
|
|
||||||
} else if (mg_http_match_uri(hm, "/api/watch")) {
|
|
||||||
c->label[0] = 'W'; // Mark ourselves as a event listener
|
|
||||||
mg_ws_upgrade(c, hm, NULL);
|
|
||||||
} else if (mg_http_match_uri(hm, "/api/login")) {
|
|
||||||
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q}\n", "user", u->name, "token",
|
|
||||||
u->token);
|
|
||||||
} else {
|
} else {
|
||||||
struct mg_http_serve_opts opts = {0};
|
struct mg_http_serve_opts opts;
|
||||||
#if 1
|
memset(&opts, 0, sizeof(opts));
|
||||||
opts.root_dir = "/web_root";
|
#if MG_ARCH == MG_ARCH_UNIX || MG_ARCH == MG_ARCH_WIN32
|
||||||
opts.fs = &mg_fs_packed;
|
opts.root_dir = "web_root"; // On workstations, use filesystem
|
||||||
#else
|
#else
|
||||||
opts.root_dir = "web_root";
|
opts.root_dir = "/web_root"; // On embedded, use packed files
|
||||||
|
opts.fs = &mg_fs_packed;
|
||||||
#endif
|
#endif
|
||||||
mg_http_serve_dir(c, ev_data, &opts);
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
}
|
}
|
||||||
MG_DEBUG(("%.*s %.*s -> %.*s", (int) hm->method.len, hm->method.ptr,
|
MG_DEBUG(("%lu %.*s %.*s -> %.*s", c->id, (int) hm->method.len,
|
||||||
(int) hm->uri.len, hm->uri.ptr, (int) 3, &c->send.buf[9]));
|
hm->method.buf, (int) hm->uri.len, hm->uri.buf, (int) 3,
|
||||||
|
&c->send.buf[9]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void web_init(struct mg_mgr *mgr) {
|
||||||
|
s_settings.device_name = strdup("My Device");
|
||||||
|
mg_http_listen(mgr, HTTP_URL, fn, NULL);
|
||||||
|
mg_http_listen(mgr, HTTPS_URL, fn, (void *) 1);
|
||||||
|
mg_timer_add(mgr, 3600 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT,
|
||||||
|
timer_sntp_fn, mgr);
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2023 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(HTTP_URL)
|
||||||
|
#define HTTP_URL "http://0.0.0.0:8000"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(HTTPS_URL)
|
||||||
|
#define HTTPS_URL "https://0.0.0.0:8443"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_DEVICE_NAME 40
|
||||||
|
#define MAX_EVENTS_NO 400
|
||||||
|
#define MAX_EVENT_TEXT_SIZE 10
|
||||||
|
#define EVENTS_PER_PAGE 20
|
||||||
|
|
||||||
|
// Event log entry
|
||||||
|
struct ui_event {
|
||||||
|
uint8_t type, prio;
|
||||||
|
unsigned long timestamp;
|
||||||
|
char text[10];
|
||||||
|
};
|
||||||
|
|
||||||
|
void web_init(struct mg_mgr *mgr);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Before Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 65 KiB |
@@ -0,0 +1,17 @@
|
|||||||
|
module.exports = {
|
||||||
|
content: ['./web_root/*.{html,js}'],
|
||||||
|
xplugins: [ 'tailwindcss', 'xautoprefixer' ],
|
||||||
|
corePlugins: {outline: false},
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
fontFamily: {
|
||||||
|
sans:
|
||||||
|
[
|
||||||
|
"Inter var, Helvetica, sans-serif", {
|
||||||
|
fontFeatureSettings: '"cv11", "ss01"',
|
||||||
|
fontVariationSettings: '"opsz" 32',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
var n,t,e,_,r,o,i,u,l,c={},a=[],s=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function f(n,t){for(var e in t)n[e]=t[e];return n}function p(n){var t=n.parentNode;t&&t.removeChild(n)}function h(t,e,_){var r,o,i,u={};for(i in e)"key"==i?r=e[i]:"ref"==i?o=e[i]:u[i]=e[i];if(arguments.length>2&&(u.children=arguments.length>3?n.call(arguments,2):_),"function"==typeof t&&null!=t.defaultProps)for(i in t.defaultProps)void 0===u[i]&&(u[i]=t.defaultProps[i]);return d(t,u,r,o,null)}function d(n,_,r,o,i){var u={type:n,props:_,key:r,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==i?++e:i};return null==i&&null!=t.vnode&&t.vnode(u),u}function v(){return{current:null}}function m(n){return n.children}function y(n,t){this.props=n,this.context=t}function g(n,t){if(null==t)return n.__?g(n.__,n.__.__k.indexOf(n)+1):null;for(var e;t<n.__k.length;t++)if(null!=(e=n.__k[t])&&null!=e.__e)return e.__e;return"function"==typeof n.type?g(n):null}function b(n){var t,e;if(null!=(n=n.__)&&null!=n.__c){for(n.__e=n.__c.base=null,t=0;t<n.__k.length;t++)if(null!=(e=n.__k[t])&&null!=e.__e){n.__e=n.__c.base=e.__e;break}return b(n)}}function k(n){(!n.__d&&(n.__d=!0)&&r.push(n)&&!C.__r++||o!==t.debounceRendering)&&((o=t.debounceRendering)||i)(C)}function C(){var n,t,e,_,o,i,l,c;for(r.sort(u);n=r.shift();)n.__d&&(t=r.length,_=void 0,o=void 0,l=(i=(e=n).__v).__e,(c=e.__P)&&(_=[],(o=f({},i)).__v=i.__v+1,T(c,i,o,e.__n,void 0!==c.ownerSVGElement,null!=i.__h?[l]:null,_,null==l?g(i):l,i.__h),R(_,i),i.__e!=l&&b(i)),r.length>t&&r.sort(u));C.__r=0}function x(n,t,e,_,r,o,i,u,l,s){var f,p,h,v,y,b,k,C=_&&_.__k||a,x=C.length;for(e.__k=[],f=0;f<t.length;f++)if(null!=(v=e.__k[f]=null==(v=t[f])||"boolean"==typeof v||"function"==typeof v?null:"string"==typeof v||"number"==typeof v||"bigint"==typeof v?d(null,v,null,null,v):Array.isArray(v)?d(m,{children:v},null,null,null):v.__b>0?d(v.type,v.props,v.key,v.ref?v.ref:null,v.__v):v)){if(v.__=e,v.__b=e.__b+1,null===(h=C[f])||h&&v.key==h.key&&v.type===h.type)C[f]=void 0;else for(p=0;p<x;p++){if((h=C[p])&&v.key==h.key&&v.type===h.type){C[p]=void 0;break}h=null}T(n,v,h=h||c,r,o,i,u,l,s),y=v.__e,(p=v.ref)&&h.ref!=p&&(k||(k=[]),h.ref&&k.push(h.ref,null,v),k.push(p,v.__c||y,v)),null!=y?(null==b&&(b=y),"function"==typeof v.type&&v.__k===h.__k?v.__d=l=E(v,l,n):l=U(n,v,h,C,y,l),"function"==typeof e.type&&(e.__d=l)):l&&h.__e==l&&l.parentNode!=n&&(l=g(h))}for(e.__e=b,f=x;f--;)null!=C[f]&&("function"==typeof e.type&&null!=C[f].__e&&C[f].__e==e.__d&&(e.__d=A(_).nextSibling),W(C[f],C[f]));if(k)for(f=0;f<k.length;f++)M(k[f],k[++f],k[++f])}function E(n,t,e){for(var _,r=n.__k,o=0;r&&o<r.length;o++)(_=r[o])&&(_.__=n,t="function"==typeof _.type?E(_,t,e):U(e,_,_,r,_.__e,t));return t}function H(n,t){return t=t||[],null==n||"boolean"==typeof n||(Array.isArray(n)?n.some((function(n){H(n,t)})):t.push(n)),t}function U(n,t,e,_,r,o){var i,u,l;if(void 0!==t.__d)i=t.__d,t.__d=void 0;else if(null==e||r!=o||null==r.parentNode)n:if(null==o||o.parentNode!==n)n.appendChild(r),i=null;else{for(u=o,l=0;(u=u.nextSibling)&&l<_.length;l+=1)if(u==r)break n;n.insertBefore(r,o),i=o}return void 0!==i?i:r.nextSibling}function A(n){var t,e,_;if(null==n.type||"string"==typeof n.type)return n.__e;if(n.__k)for(t=n.__k.length-1;t>=0;t--)if((e=n.__k[t])&&(_=A(e)))return _;return null}function P(n,t,e,_,r){var o;for(o in e)"children"===o||"key"===o||o in t||N(n,o,null,e[o],_);for(o in t)r&&"function"!=typeof t[o]||"children"===o||"key"===o||"value"===o||"checked"===o||e[o]===t[o]||N(n,o,t[o],e[o],_)}function S(n,t,e){"-"===t[0]?n.setProperty(t,null==e?"":e):n[t]=null==e?"":"number"!=typeof e||s.test(t)?e:e+"px"}function N(n,t,e,_,r){var o;n:if("style"===t)if("string"==typeof e)n.style.cssText=e;else{if("string"==typeof _&&(n.style.cssText=_=""),_)for(t in _)e&&t in e||S(n.style,t,"");if(e)for(t in e)_&&e[t]===_[t]||S(n.style,t,e[t])}else if("o"===t[0]&&"n"===t[1])o=t!==(t=t.replace(/Capture$/,"")),t=t.toLowerCase()in n?t.toLowerCase().slice(2):t.slice(2),n.l||(n.l={}),n.l[t+o]=e,e?_||n.addEventListener(t,o?D:w,o):n.removeEventListener(t,o?D:w,o);else if("dangerouslySetInnerHTML"!==t){if(r)t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if("width"!==t&&"height"!==t&&"href"!==t&&"list"!==t&&"form"!==t&&"tabIndex"!==t&&"download"!==t&&t in n)try{n[t]=null==e?"":e;break n}catch(n){}"function"==typeof e||(null==e||!1===e&&"-"!==t[4]?n.removeAttribute(t):n.setAttribute(t,e))}}function w(n){return this.l[n.type+!1](t.event?t.event(n):n)}function D(n){return this.l[n.type+!0](t.event?t.event(n):n)}function T(n,e,_,r,o,i,u,l,c){var a,s,p,h,d,v,g,b,k,C,E,H,U,A,P,S=e.type;if(void 0!==e.constructor)return null;null!=_.__h&&(c=_.__h,l=e.__e=_.__e,e.__h=null,i=[l]),(a=t.__b)&&a(e);try{n:if("function"==typeof S){if(b=e.props,k=(a=S.contextType)&&r[a.__c],C=a?k?k.props.value:a.__:r,_.__c?g=(s=e.__c=_.__c).__=s.__E:("prototype"in S&&S.prototype.render?e.__c=s=new S(b,C):(e.__c=s=new y(b,C),s.constructor=S,s.rLine truncated
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
'use strict';
|
||||||
|
import { h, render, useState, useEffect, useRef, html, Router } from './bundle.js';
|
||||||
|
|
||||||
|
// Helper function that returns a promise that resolves after delay
|
||||||
|
const Delay = (ms, val) => new Promise(resolve => setTimeout(resolve, ms, val));
|
||||||
|
|
||||||
|
export const Icons = {
|
||||||
|
heart: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path></svg>`,
|
||||||
|
downArrowBox: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15M9 12l3 3m0 0l3-3m-3 3V2.25" /> </svg>`,
|
||||||
|
upArrowBox: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15m0-3l-3-3m0 0l-3 3m3-3V15" /> </svg>`,
|
||||||
|
cog: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg>`,
|
||||||
|
settingsH: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" /> </svg>`,
|
||||||
|
settingsV: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6 13.5V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m12-3V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m-6-9V3.75m0 3.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 9.75V10.5" /> </svg>`,
|
||||||
|
scan: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 3.75H6A2.25 2.25 0 003.75 6v1.5M16.5 3.75H18A2.25 2.25 0 0120.25 6v1.5m0 9V18A2.25 2.25 0 0118 20.25h-1.5m-9 0H6A2.25 2.25 0 013.75 18v-1.5M15 12a3 3 0 11-6 0 3 3 0 016 0z" /> </svg> `,
|
||||||
|
desktop: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 17.25v1.007a3 3 0 01-.879 2.122L7.5 21h9l-.621-.621A3 3 0 0115 18.257V17.25m6-12V15a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 15V5.25m18 0A2.25 2.25 0 0018.75 3H5.25A2.25 2.25 0 003 5.25m18 0V12a2.25 2.25 0 01-2.25 2.25H5.25A2.25 2.25 0 013 12V5.25" /> </svg>`,
|
||||||
|
alert: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5" /> </svg>`,
|
||||||
|
bell: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5" /> </svg>`,
|
||||||
|
refresh: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" /> </svg> `,
|
||||||
|
bars4: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 5.25h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5m-16.5 4.5h16.5" /> </svg>`,
|
||||||
|
bars3: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" /> </svg>`,
|
||||||
|
logout: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12.75 15l3-3m0 0l-3-3m3 3h-7.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>`,
|
||||||
|
save: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" /> </svg>`,
|
||||||
|
email: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 01-2.25 2.25h-15a2.25 2.25 0 01-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25m19.5 0v.243a2.25 2.25 0 01-1.07 1.916l-7.5 4.615a2.25 2.25 0 01-2.36 0L3.32 8.91a2.25 2.25 0 01-1.07-1.916V6.75" /> </svg>`,
|
||||||
|
expand: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15" /> </svg>`,
|
||||||
|
shrink: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 9V4.5M9 9H4.5M9 9L3.75 3.75M9 15v4.5M9 15H4.5M9 15l-5.25 5.25M15 9h4.5M15 9V4.5M15 9l5.25-5.25M15 15h4.5M15 15v4.5m0-4.5l5.25 5.25" /> </svg>`,
|
||||||
|
ok: props => html`<svg class=${props.class} fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>`,
|
||||||
|
fail: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> </svg>`,
|
||||||
|
upload: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5" /> </svg> `,
|
||||||
|
download: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" /> </svg> `,
|
||||||
|
bolt: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 13.5l10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75z" /> </svg>`,
|
||||||
|
home: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" /> </svg> `,
|
||||||
|
link: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M13.19 8.688a4.5 4.5 0 011.242 7.244l-4.5 4.5a4.5 4.5 0 01-6.364-6.364l1.757-1.757m13.35-.622l1.757-1.757a4.5 4.5 0 00-6.364-6.364l-4.5 4.5a4.5 4.5 0 001.242 7.244" /> </svg> `,
|
||||||
|
shield: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z" /> </svg> `,
|
||||||
|
barsdown: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M3 4.5h14.25M3 9h9.75M3 13.5h9.75m4.5-4.5v12m0 0l-3.75-3.75M17.25 21L21 17.25" /> </svg> `,
|
||||||
|
arrowdown: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m0 0l6.75-6.75M12 19.5l-6.75-6.75" /> </svg> `,
|
||||||
|
arrowup: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 19.5v-15m0 0l-6.75 6.75M12 4.5l6.75 6.75" /> </svg>`,
|
||||||
|
warn: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> </svg>`,
|
||||||
|
info: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" /> </svg>`,
|
||||||
|
exclamationTriangle: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z" /> </svg>`,
|
||||||
|
thumbUp: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6.633 10.5c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75A2.25 2.25 0 0116.5 4.5c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23H5.904M14.25 9h2.25M5.904 18.75c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 01-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 10.203 4.167 9.75 5 9.75h1.053c.472 0 .745.556.5.96a8.958 8.958 0 00-1.302 4.665c0 1.194.232 2.333.654 3.375z" /> </svg>`,
|
||||||
|
backward: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M21 16.811c0 .864-.933 1.405-1.683.977l-7.108-4.062a1.125 1.125 0 010-1.953l7.108-4.062A1.125 1.125 0 0121 8.688v8.123zM11.25 16.811c0 .864-.933 1.405-1.683.977l-7.108-4.062a1.125 1.125 0 010-1.953L9.567 7.71a1.125 1.125 0 011.683.977v8.123z" /> </svg>`,
|
||||||
|
chip: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M8.25 3v1.5M4.5 8.25H3m18 0h-1.5M4.5 12H3m18 0h-1.5m-15 3.75H3m18 0h-1.5M8.25 19.5V21M12 3v1.5m0 15V21m3.75-18v1.5m0 15V21m-9-1.5h10.5a2.25 2.25 0 002.25-2.25V6.75a2.25 2.25 0 00-2.25-2.25H6.75A2.25 2.25 0 004.5 6.75v10.5a2.25 2.25 0 002.25 2.25zm.75-12h9v9h-9v-9z" /> </svg>`,
|
||||||
|
camera: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M6.827 6.175A2.31 2.31 0 015.186 7.23c-.38.054-.757.112-1.134.175C2.999 7.58 2.25 8.507 2.25 9.574V18a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9.574c0-1.067-.75-1.994-1.802-2.169a47.865 47.865 0 00-1.134-.175 2.31 2.31 0 01-1.64-1.055l-.822-1.316a2.192 2.192 0 00-1.736-1.039 48.774 48.774 0 00-5.232 0 2.192 2.192 0 00-1.736 1.039l-.821 1.316z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M16.5 12.75a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zM18.75 10.5h.008v.008h-.008V10.5z" /> </svg>`,
|
||||||
|
arrows: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-13.5L21 7.5m0 0L16.5 12M21 7.5H7.5" /> </svg>`,
|
||||||
|
doc: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z" /></svg>`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const tipColors = {
|
||||||
|
green: 'bg-green-100 text-green-900 ring-green-300',
|
||||||
|
yellow: 'bg-yellow-100 text-yellow-900 ring-yellow-300',
|
||||||
|
red: 'bg-red-100 text-red-900 ring-red-300',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Button({title, onclick, disabled, cls, icon, ref, colors, hovercolor, disabledcolor}) {
|
||||||
|
const [spin, setSpin] = useState(false);
|
||||||
|
const cb = function(ev) {
|
||||||
|
const res = onclick ? onclick() : null;
|
||||||
|
if (res && typeof (res.catch) === 'function') {
|
||||||
|
setSpin(true);
|
||||||
|
res.catch(() => false).then(() => setSpin(false));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (!colors) colors = 'bg-blue-600 hover:bg-blue-500 disabled:bg-blue-400';
|
||||||
|
return html`
|
||||||
|
<button type="button" class="inline-flex justify-center items-center gap-2 rounded px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm ${colors} ${cls}"
|
||||||
|
ref=${ref} onclick=${cb} disabled=${disabled || spin} >
|
||||||
|
${title}
|
||||||
|
<${spin ? Icons.refresh : icon} class="w-4 ${spin ? 'animate-spin' : ''}" />
|
||||||
|
<//>`
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Notification({ok, text, close}) {
|
||||||
|
const closebtn = useRef(null);
|
||||||
|
const from = 'translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2';
|
||||||
|
const to = 'translate-y-0 opacity-100 sm:translate-x-0';
|
||||||
|
const [tr, setTr] = useState(from);
|
||||||
|
useEffect(function() {
|
||||||
|
setTr(to);
|
||||||
|
setTimeout(ev => closebtn && closebtn.current.click && closebtn.current.click(), 1500);
|
||||||
|
}, []);
|
||||||
|
const onclose = ev => { setTr(from); setTimeout(close, 300); };
|
||||||
|
return html`
|
||||||
|
<div aria-live="assertive" class="z-10 pointer-events-none absolute inset-0 flex items-end px-4 py-6 sm:items-start sm:p-6">
|
||||||
|
<div class="flex w-full flex-col items-center space-y-4 sm:items-end">
|
||||||
|
<div class="pointer-events-auto w-full max-w-sm overflow-hidden rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5 transform ease-out duration-300 transition ${tr}">
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="flex items-start">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<${ok ? Icons.ok : Icons.fail} class="h-6 w-6 ${ok ? 'text-green-400' : 'text-red-400'}" />
|
||||||
|
<//>
|
||||||
|
<div class="ml-3 w-0 flex-1 pt-0.5">
|
||||||
|
<p class="text-sm font-medium text-gray-900">${text}</p>
|
||||||
|
<p class="hidden mt-1 text-sm text-gray-500">Anyone with a link can now view this file.</p>
|
||||||
|
<//>
|
||||||
|
<div class="ml-4 flex flex-shrink-0">
|
||||||
|
<button type="button" ref=${closebtn} onclick=${onclose} class="inline-flex rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none">
|
||||||
|
<span class="sr-only">Close</span>
|
||||||
|
<svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z" />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Login({loginFn, logoIcon, title, tipText}) {
|
||||||
|
const [user, setUser] = useState('');
|
||||||
|
const [pass, setPass] = useState('');
|
||||||
|
const onsubmit = function(ev) {
|
||||||
|
const authhdr = 'Basic ' + btoa(user + ':' + pass);
|
||||||
|
const headers = {Authorization: authhdr};
|
||||||
|
return fetch('api/login', {headers}).then(loginFn).finally(r => setPass(''));
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<div class="h-full flex items-center justify-center bg-slate-200">
|
||||||
|
<div class="border rounded bg-white w-96 p-5">
|
||||||
|
<div class="my-5 py-2 flex items-center justify-center gap-x-4">
|
||||||
|
<${logoIcon} class="h-12 stroke-cyan-600 stroke-1" />
|
||||||
|
<h1 class="font-bold text-xl">${title || 'Login'}<//>
|
||||||
|
<//>
|
||||||
|
<div class="my-3">
|
||||||
|
<label class="block text-sm mb-1 dark:text-white">Username</label>
|
||||||
|
<input type="text" autocomplete="current-user" required
|
||||||
|
class="font-normal bg-white rounded border border-gray-300 w-full
|
||||||
|
flex-1 py-0.5 px-2 text-gray-900 placeholder:text-gray-400
|
||||||
|
focus:outline-none sm:text-sm sm:leading-6 disabled:cursor-not-allowed
|
||||||
|
disabled:bg-gray-100 disabled:text-gray-500"
|
||||||
|
oninput=${ev => setUser(ev.target.value)} value=${user} />
|
||||||
|
<//>
|
||||||
|
<div class="my-3">
|
||||||
|
<label class="block text-sm mb-1 dark:text-white">Password</label>
|
||||||
|
<input type="password" autocomplete="current-password" required
|
||||||
|
class="font-normal bg-white rounded border border-gray-300 w-full flex-1 py-0.5 px-2 text-gray-900 placeholder:text-gray-400 focus:outline-none sm:text-sm sm:leading-6 disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-gray-500"
|
||||||
|
oninput=${ev => setPass(ev.target.value)}
|
||||||
|
value=${pass} onchange=${onsubmit} />
|
||||||
|
<//>
|
||||||
|
<div class="mt-7">
|
||||||
|
<${Button} title="Sign In" icon=${Icons.logout} onclick=${onsubmit} cls="flex w-full justify-center" />
|
||||||
|
<//>
|
||||||
|
<div class="mt-5 text-slate-400 text-xs">${tipText}<//>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Colored({icon, text, colors}) {
|
||||||
|
colors ||= 'bg-slate-100 text-slate-900';
|
||||||
|
return html`
|
||||||
|
<span class="inline-flex items-center gap-1.5 py-0.5">
|
||||||
|
${icon && html`<${icon} class="w-5 h-5" />`}
|
||||||
|
<span class="inline-block font-medium rounded-md px-2 py-1 text-xs ring-1 ring-inset ${colors}">${text}<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Stat({title, text, tipText, tipIcon, tipColors, colors}) {
|
||||||
|
return html`
|
||||||
|
<div class="flex flex-col bg-white border shadow-sm rounded-xl dark:bg-slate-900 dark:border-gray-800">
|
||||||
|
<div class="overflow-auto rounded-lg bg-white px-4 py-2 ">
|
||||||
|
<div class="flex items-center gap-x-2">
|
||||||
|
<p class="text-sm truncate text-gray-500 font-medium"> ${title} </p>
|
||||||
|
<//>
|
||||||
|
<div class="mt-1 flex items-center gap-x-2">
|
||||||
|
<h3 class="text-xl truncate font-semibold tracking-tight ${colors || 'text-gray-800 dark:text-gray-200'}">
|
||||||
|
${text}
|
||||||
|
<//>
|
||||||
|
<span class="flex items-center ${tipText || 'hidden'}">
|
||||||
|
<${Colored} text=${tipText} icon=${tipIcon} colors=${tipColors} />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function TextValue({value, setfn, disabled, placeholder, type, addonRight, addonLeft, attr, min, max, step, mult}) {
|
||||||
|
const [bg, setBg] = useState('bg-white');
|
||||||
|
useEffect(() => { if (type == 'number') checkval(+min, +max, +value); }, []);
|
||||||
|
step ||= '1', mult ||= 1;
|
||||||
|
const checkval = function(min, max, v) {
|
||||||
|
setBg('bg-white');
|
||||||
|
if (min && v < min) setBg('bg-red-100 border-red-200');
|
||||||
|
if (max && v > max) setBg('bg-red-100 border-red-200');
|
||||||
|
};
|
||||||
|
const m = step.match(/^.+\.(.+)/);
|
||||||
|
const digits = m ? m[1].length : 0;
|
||||||
|
const onchange = ev => {
|
||||||
|
let v = ev.target.value;
|
||||||
|
if (type == 'number') {
|
||||||
|
checkval(+min, +max, +v);
|
||||||
|
v = +(parseFloat(v) / mult).toFixed(digits);
|
||||||
|
}
|
||||||
|
setfn(v);
|
||||||
|
};
|
||||||
|
if (type == 'number') value = +(value * mult).toFixed(digits);
|
||||||
|
return html`
|
||||||
|
<div class="flex w-full items-center rounded border shadow-sm ${bg}">
|
||||||
|
${addonLeft && html`<span class="inline-flex font-normal truncate py-1 border-r bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs">${addonLeft}<//>` }
|
||||||
|
<input type=${type || 'text'} disabled=${disabled} value=${value}
|
||||||
|
step=${step} min=${min} max=${max}
|
||||||
|
onchange=${onchange} ...${attr}
|
||||||
|
class="${bg} font-normal text-sm rounded w-full flex-1 py-0.5 px-2 text-gray-700 placeholder:text-gray-400 focus:outline-none disabled:cursor-not-allowed disabled:bg-gray-100 disabled:text-gray-500" placeholder=${placeholder} />
|
||||||
|
${addonRight && html`<span class="inline-flex font-normal truncate py-1 border-l bg-slate-100 items-center border-gray-300 px-2 text-gray-500 text-xs overflow-scroll" style="min-width: 50%;">${addonRight}<//>` }
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SelectValue({value, setfn, options, disabled}) {
|
||||||
|
const toInt = x => x == parseInt(x) ? parseInt(x) : x;
|
||||||
|
const onchange = ev => setfn(toInt(ev.target.value));
|
||||||
|
return html`
|
||||||
|
<select onchange=${onchange} class="w-full rounded font-normal border py-0.5 px-1 text-gray-600 focus:outline-none text-sm disabled:cursor-not-allowed" disabled=${disabled}>
|
||||||
|
${options.map(v => html`<option value=${v[0]} selected=${v[0] == value}>${v[1]}<//>`) }
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function SwitchValue({value, setfn}) {
|
||||||
|
const onclick = ev => setfn(!value);
|
||||||
|
const bg = !!value ? 'bg-blue-600' : 'bg-gray-200';
|
||||||
|
const tr = !!value ? 'translate-x-5' : 'translate-x-0';
|
||||||
|
return html`
|
||||||
|
<button type="button" onclick=${onclick} class="${bg} inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-0 ring-0" role="switch" aria-checked=${!!value}>
|
||||||
|
<span aria-hidden="true" class="${tr} pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 focus:ring-0 transition duration-200 ease-in-out"></span>
|
||||||
|
</button>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Setting(props) {
|
||||||
|
let input = TextValue;
|
||||||
|
if (props.type == 'switch') input = SwitchValue;
|
||||||
|
if (props.type == 'select') input = SelectValue;
|
||||||
|
return html`
|
||||||
|
<div class=${props.cls || 'grid grid-cols-2 gap-2 my-1'}>
|
||||||
|
<label class="flex items-center text-sm text-gray-700 mr-2 font-medium ${props.title || 'hidden'}">${props.title}<//>
|
||||||
|
<div class="flex items-center">${h(input, props)}<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Pagination({ totalItems, itemsPerPage, currentPage, setPageFn, colors }) {
|
||||||
|
const totalPages = Math.ceil(totalItems / itemsPerPage);
|
||||||
|
const maxPageRange = 2;
|
||||||
|
const lessThanSymbol = "<";
|
||||||
|
const greaterThanSymbol = ">";
|
||||||
|
const whiteSpace = " ";
|
||||||
|
const itemcls = 'relative inline-flex items-center px-3 py-1 text-sm focus:z-20 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-0 focus-visible:outline-blue-600';
|
||||||
|
colors ||= 'bg-blue-600';
|
||||||
|
|
||||||
|
const PageItem = ({ page, isActive }) => (
|
||||||
|
html`<a
|
||||||
|
onClick=${() => setPageFn(page)}
|
||||||
|
class="${itemcls} ${isActive ? `${colors} text-white` : 'cursor-pointer text-gray-700 ring-1 ring-inset ring-gray-300 hover:bg-gray-50'}"
|
||||||
|
>
|
||||||
|
${page}
|
||||||
|
</a>`
|
||||||
|
);
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="flex items-center justify-between bg-white px-3 py-2">
|
||||||
|
<div class="sm:flex sm:flex-1 sm:items-center sm:justify-between space-x-4 whitespace-nowrap select-none">
|
||||||
|
<p class="text-sm text-slate-500 font-medium">
|
||||||
|
showing <span class="font-bold text-slate-700">${(currentPage - 1) * itemsPerPage + 1}</span> - <span class="font-medium">${Math.min(currentPage * itemsPerPage, totalItems)}</span> of ${whiteSpace}
|
||||||
|
<span class="font-bold text-slate-700">${totalItems}</span> results
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<nav class="isolate inline-flex -space-x-px rounded-md" aria-label="Pagination">
|
||||||
|
<a
|
||||||
|
onClick=${() => setPageFn(Math.max(currentPage - 1, 1))}
|
||||||
|
class="relative inline-flex px-3 items-center text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 ${currentPage != 1 ? 'cursor-pointer' : ''} focus:z-20 focus:outline-offset-0">
|
||||||
|
${lessThanSymbol}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<${PageItem} page=${1} isActive=${currentPage === 1} />
|
||||||
|
${currentPage > maxPageRange + 2 ? html`<span class="${itemcls} ring-1 ring-inset ring-gray-300 text-slate-300">...</span>` : ''}
|
||||||
|
${Array.from({length: Math.min(totalPages, maxPageRange * 2 + 1)}, (_, i) => Math.max(2, currentPage - maxPageRange) + i).map(page => page > 1 && page < totalPages && html`<${PageItem} page=${page} isActive=${currentPage === page} />`)}
|
||||||
|
${currentPage < totalPages - (maxPageRange + 1) ? html`<span class="${itemcls} ring-1 ring-inset ring-gray-300 text-slate-300">...</span>` : ''}
|
||||||
|
${totalPages > 1 ? html`<${PageItem} page=${totalPages} isActive=${currentPage === totalPages} />` : ''}
|
||||||
|
|
||||||
|
<a
|
||||||
|
onClick=${() => setPageFn(Math.min(currentPage + 1, totalPages))}
|
||||||
|
class="relative inline-flex px-3 items-center text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 ${currentPage != totalPages ? 'cursor-pointer' : ''} focus:z-20 focus:outline-offset-0">
|
||||||
|
${greaterThanSymbol}
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function UploadFileButton(props) {
|
||||||
|
const [upload, setUpload] = useState(null); // Upload promise
|
||||||
|
const [status, setStatus] = useState(''); // Current upload status
|
||||||
|
const btn = useRef(null);
|
||||||
|
const input = useRef(null);
|
||||||
|
|
||||||
|
// Send a large file chunk by chunk
|
||||||
|
const sendFileData = function(url, fileName, fileData, chunkSize) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
const finish = ok => {
|
||||||
|
setUpload(null);
|
||||||
|
const res = props.onupload ? props.onupload(ok, fileName, fileData.length) : null;
|
||||||
|
if (res && typeof (res.catch) === 'function') {
|
||||||
|
res.catch(() => false).then(() => ok ? resolve() : reject());
|
||||||
|
} else {
|
||||||
|
ok ? resolve() : reject();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const sendChunk = function(offset) {
|
||||||
|
var chunk = fileData.subarray(offset, offset + chunkSize) || '';
|
||||||
|
var opts = {method: 'POST', body: chunk};
|
||||||
|
var fullUrl = url + '?offset=' + offset +
|
||||||
|
'&total=' + fileData.length +
|
||||||
|
'&name=' + encodeURIComponent(fileName);
|
||||||
|
var ok;
|
||||||
|
setStatus('Uploading ' + fileName + ', bytes ' + offset + '..' +
|
||||||
|
(offset + chunk.length) + ' of ' + fileData.length);
|
||||||
|
fetch(fullUrl, opts)
|
||||||
|
.then(function(res) {
|
||||||
|
if (res.ok && chunk.length > 0) sendChunk(offset + chunk.length);
|
||||||
|
ok = res.ok;
|
||||||
|
return res.text();
|
||||||
|
})
|
||||||
|
.then(function(text) {
|
||||||
|
if (!ok) setStatus('Error: ' + text), finish(ok); // Fail
|
||||||
|
if (chunk.length > 0) return; // More chunks to send
|
||||||
|
setStatus(x => x + '. Done, resetting device...');
|
||||||
|
finish(ok); // All chunks sent
|
||||||
|
});
|
||||||
|
};
|
||||||
|
sendChunk(0);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onchange = function(ev) {
|
||||||
|
if (!ev.target.files[0]) return;
|
||||||
|
let r = new FileReader(), f = ev.target.files[0];
|
||||||
|
r.readAsArrayBuffer(f);
|
||||||
|
r.onload = function() {
|
||||||
|
setUpload(sendFileData(props.url, f.name, new Uint8Array(r.result), 2048));
|
||||||
|
ev.target.value = '';
|
||||||
|
ev.preventDefault();
|
||||||
|
btn && btn.current.base.click();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const onclick = function(ev) {
|
||||||
|
let fn; setUpload(x => fn = x);
|
||||||
|
if (!fn) input.current.click(); // No upload in progress, show file dialog
|
||||||
|
return fn;
|
||||||
|
};
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="inline-flex flex-col ${props.class}">
|
||||||
|
<input class="hidden" type="file" ref=${input} onchange=${onchange} accept=${props.accept} />
|
||||||
|
<${Button} title=${props.title} icon=${Icons.download} onclick=${onclick} ref=${btn} colors=${props.colors} />
|
||||||
|
<div class="pt-2 text-sm text-slate-400 ${status || 'hidden'}">${status}<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
!function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.History=n():t.History=n()}(this,function(){return function(t){function n(o){if(e[o])return e[o].exports;var r=e[o]={exports:{},id:o,loaded:!1};return t[o].call(r.exports,r,r.exports,n),r.loaded=!0,r.exports}var e={};return n.m=t,n.c=e,n.p="",n(0)}([function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0,n.createPath=n.parsePath=n.locationsAreEqual=n.createLocation=n.createMemoryHistory=n.createHashHistory=n.createBrowserHistory=void 0;var r=e(2);Object.defineProperty(n,"createLocation",{enumerable:!0,get:function(){return r.createLocation}}),Object.defineProperty(n,"locationsAreEqual",{enumerable:!0,get:function(){return r.locationsAreEqual}});var i=e(1);Object.defineProperty(n,"parsePath",{enumerable:!0,get:function(){return i.parsePath}}),Object.defineProperty(n,"createPath",{enumerable:!0,get:function(){return i.createPath}});var a=e(7),c=o(a),u=e(8),s=o(u),f=e(9),l=o(f);n.createBrowserHistory=c.default,n.createHashHistory=s.default,n.createMemoryHistory=l.default},function(t,n){"use strict";n.__esModule=!0;n.addLeadingSlash=function(t){return"/"===t.charAt(0)?t:"/"+t},n.stripLeadingSlash=function(t){return"/"===t.charAt(0)?t.substr(1):t},n.stripPrefix=function(t,n){return 0===t.indexOf(n)?t.substr(n.length):t},n.stripTrailingSlash=function(t){return"/"===t.charAt(t.length-1)?t.slice(0,-1):t},n.parsePath=function(t){var n=t||"/",e="",o="",r=n.indexOf("#");r!==-1&&(o=n.substr(r),n=n.substr(0,r));var i=n.indexOf("?");return i!==-1&&(e=n.substr(i),n=n.substr(0,i)),n=decodeURI(n),{pathname:n,search:"?"===e?"":e,hash:"#"===o?"":o}},n.createPath=function(t){var n=t.pathname,e=t.search,o=t.hash,r=encodeURI(n||"/");return e&&"?"!==e&&(r+="?"===e.charAt(0)?e:"?"+e),o&&"#"!==o&&(r+="#"===o.charAt(0)?o:"#"+o),r}},function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0,n.locationsAreEqual=n.createLocation=void 0;var r=Object.assign||function(t){for(var n=1;n<arguments.length;n++){var e=arguments[n];for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}return t},i=e(10),a=o(i),c=e(11),u=o(c),s=e(1);n.createLocation=function(t,n,e,o){var i=void 0;return"string"==typeof t?(i=(0,s.parsePath)(t),i.state=n):(i=r({},t),void 0===i.pathname&&(i.pathname=""),i.search?"?"!==i.search.charAt(0)&&(i.search="?"+i.search):i.search="",i.hash?"#"!==i.hash.charAt(0)&&(i.hash="#"+i.hash):i.hash="",void 0!==n&&void 0===i.state&&(i.state=n)),i.key=e,o&&(i.pathname?"/"!==i.pathname.charAt(0)&&(i.pathname=(0,a.default)(i.pathname,o.pathname)):i.pathname=o.pathname),i},n.locationsAreEqual=function(t,n){return t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash&&t.key===n.key&&(0,u.default)(t.state,n.state)}},function(t,n,e){"use strict";var o=function(){};t.exports=o},function(t,n,e){"use strict";function o(t){return t&&t.__esModule?t:{default:t}}n.__esModule=!0;var r=e(3),i=(o(r),function(){var t=null,n=function(n){return t=n,function(){t===n&&(t=null)}},e=function(n,e,o,r){if(null!=t){var i="function"==typeof t?t(n,e):t;"string"==typeof i?"function"==typeof o?o(i,r):r(!0):r(i!==!1)}else r(!0)},o=[],r=function(t){var n=!0,e=function(){n&&t.apply(void 0,arguments)};return o.push(e),function(){n=!1,o=o.filter(function(t){return t!==e})}},i=function(){for(var t=arguments.length,n=Array(t),e=0;e<t;e++)n[e]=arguments[e];o.forEach(function(t){return t.apply(void 0,n)})};return{setPrompt:n,confirmTransitionTo:e,appendListener:r,notifyListeners:i}});n.default=i},function(t,n){"use strict";n.__esModule=!0;n.canUseDOM=!("undefined"==typeof window||!window.document||!window.document.createElement),n.addEventListener=function(t,n,e){return t.addEventListener?t.addEventListener(n,e,!1):t.attachEvent("on"+n,e)},n.removeEventListener=function(t,n,e){return t.removeEventListener?t.removeEventListener(n,e,!1):t.detachEvent("on"+n,e)},n.getConfirmation=function(t,n){return n(window.confirm(t))},n.supportsHistory=function(){var t=window.navigator.userAgent;return(t.indexOf("Android 2.")===-1&&t.indexOf("Android 4.0")===-1||t.indexOf("Mobile Safari")===-1||t.indexOf("Chrome")!==-1||t.indexOf("Windows Phone")!==-1)&&(window.history&&"pushState"in window.history)},n.supportsPopStateOnHashChange=function(){return window.navigator.userAgent.indexOf("Trident")===-1},n.supportsGoWithoutReloadUsingHash=function(){return window.navigator.userAgent.indexOf("Firefox")===-1},n.isExtraneousPopstateEvent=function(t){return void 0===t.state&&navigator.userAgent.indexOf("CriOS")===-1}},function(t,n,e){"use strict";var o=function(t,n,e,o,r,i,a,c){if(!t){var u;if(void 0===n)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var s=[e,o,r,i,a,c],f=0;u=new Error(n.replace(/%s/g,function(){return s[f++]})),u.name="InLine truncated
|
||||||
@@ -1,12 +1,15 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en" class="h-full bg-white">
|
||||||
<head>
|
<head>
|
||||||
<title>Device Dashboard</title>
|
<title></title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="stylesheet" href="style.css" />
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='currentColor'> <path stroke-linecap='round' stroke-linejoin='round' d='M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0' /> </svg>" />
|
||||||
|
<link href="main.css" rel="stylesheet" />
|
||||||
|
<link href="https://rsms.me/inter/inter.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body class="h-full"></body>
|
||||||
|
<script src="history.min.js"></script>
|
||||||
<script type="module" src="main.js"></script>
|
<script type="module" src="main.js"></script>
|
||||||
</html>
|
</html>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/*! tailwindcss v3.3.2 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter var,Helvetica,sans-serif;font-feature-settings:"cv11","ss01";font-variation-settings:"opsz" 32}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.left-0{left:0}.right-auto{right:auto}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-\[48\]{z-index:48}.z-\[60\]{z-index:60}.col-span-2{grid-column:span 2/span 2}.m-4{margin:1rem}.mx-auto{margin-left:auto;margin-right:auto}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.my-5{margin-top:1.25rem;margin-bottom:1.25rem}.mb-1{margin-bottom:.25rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.mr-4{margin-right:1rem}.mt-1{margin-top:.25rem}.mt-3{margin-top:.75rem}.mt-5{margin-top:1.25rem}.mt-7{margin-top:1.75rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-12{height:3rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-0{width:0}.w-11{width:2.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-72{width:18rem}.w-96{width:24rem}.w-full{width:100%}.min-w-full{min-width:100%}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.grow-0{flex-grow:0}.basis-\[30px\]{flex-basis:30px}.border-separate{border-collapse:initial}.border-spacing-0Line truncated
|
||||||
@@ -1,378 +1,376 @@
|
|||||||
|
// NOTE: API calls must start with 'api/' in order to serve the app at any URI
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
import {Component, h, html, render, useEffect, useState, useRef} from './preact.min.js';
|
import { h, render, useState, useEffect, useRef, html, Router } from './bundle.js';
|
||||||
|
import { Icons, Login, Setting, Button, Stat, tipColors, Colored, Notification, Pagination, UploadFileButton } from './components.js';
|
||||||
|
|
||||||
const MaxMetricsDataPoints = 50;
|
const Logo = props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12.87 12.85"><defs><style>.ll-cls-1{fill:none;stroke:#000;stroke-miterlimit:10;stroke-width:0.5px;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><path class="ll-cls-1" d="M12.62,1.82V8.91A1.58,1.58,0,0,1,11,10.48H4a1.44,1.44,0,0,1-1-.37A.69.69,0,0,1,2.84,10l-.1-.12a.81.81,0,0,1-.15-.48V5.57a.87.87,0,0,1,.86-.86H4.73V7.28a.86.86,0,0,0,.86.85H9.42a.85.85,0,0,0,.85-.85V3.45A.86.86,0,0,0,10.13,3,.76.76,0,0,0,10,2.84a.29.29,0,0,0-.12-.1,1.49,1.49,0,0,0-1-.37H2.39V1.82A1.57,1.57,0,0,1,4,.25H11A1.57,1.57,0,0,1,12.62,1.82Z"/><path class="ll-cls-1" d="M10.48,10.48V11A1.58,1.58,0,0,1,8.9,12.6H1.82A1.57,1.57,0,0,1,.25,11V3.94A1.57,1.57,0,0,1,1.82,2.37H8.9a1.49,1.49,0,0,1,1,.37l.12.1a.76.76,0,0,1,.11.14.86.86,0,0,1,.14.47V7.28a.85.85,0,0,1-.85.85H8.13V5.57a.86.86,0,0,0-.85-.86H3.45a.87.87,0,0,0-.86.86V9.4a.81.81,0,0,0,.15.48l.1.12a.69.69,0,0,0,.13.11,1.44,1.44,0,0,0,1,.37Z"/></g></g></svg>`;
|
||||||
|
|
||||||
// This simple publish/subscribe is used to pass notifications that were
|
function Header({logout, user, setShowSidebar, showSidebar}) {
|
||||||
// received from the server, to all child components of the app.
|
|
||||||
var PubSub = (function() {
|
|
||||||
var handlers = {}, id = 0;
|
|
||||||
return {
|
|
||||||
subscribe: function(fn) {
|
|
||||||
handlers[id++] = fn;
|
|
||||||
},
|
|
||||||
unsubscribe: function(id) {
|
|
||||||
delete handlers[id];
|
|
||||||
},
|
|
||||||
publish: function(data) {
|
|
||||||
for (var k in handlers) handlers[k](data);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
const Nav = props => html`
|
|
||||||
<div style="background: #333; padding: 0.5em; color: #fff;">
|
|
||||||
<div class="container d-flex">
|
|
||||||
<div style="flex: 1 1 auto; display: flex; align-items: center;">
|
|
||||||
<b>Your Product</b>
|
|
||||||
</div>
|
|
||||||
<div style="display: flex; align-items: center; flex: 0 0 auto; ">
|
|
||||||
<span>Logged in as:</span>
|
|
||||||
<span style="padding: 0 0.5em;"><img src="user.png" height="22" /></span>
|
|
||||||
<span>${props.user}</span>
|
|
||||||
<a class="btn" onclick=${props.logout}
|
|
||||||
style="margin-left: 1em; font-size: 0.8em; background: #8aa;">logout</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
|
|
||||||
const Hero = props => html`
|
|
||||||
<div class="section">
|
|
||||||
<div style="margin-top: 1em; background: #eee; padding: 1em; border-radius: 0.5em; color: #777; ">
|
|
||||||
<h1 style="margin: 0.2em 0;">Interactive Device Dashboard</h1>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This device dashboard is developed using the modern and compact Preact framework,
|
|
||||||
in order to fit on very small devices. This is
|
|
||||||
a <a href="https://mongoose.ws/tutorials/http-server/">hybrid server</a> which
|
|
||||||
provides both static and dynamic content. Static files, like CSS/JS/HTML
|
|
||||||
or images, are compiled into the server binary.
|
|
||||||
|
|
||||||
This UI uses the REST API implemented by the device, which you can examine
|
|
||||||
using <code>curl</code> command-line utility:
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div><code>curl -u admin:pass0 localhost:8000/api/config/get</code> </div>
|
|
||||||
<div><code>curl -u admin:pass0 localhost:8000/api/config/set -d 'pub=mg/topic'</code> </div>
|
|
||||||
<div><code>curl -u admin:pass0 localhost:8000/api/message/send -d 'message=hello'</code> </div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
The device can send notifications to this dashboard at anytime. Notifications
|
|
||||||
are sent over WebSocket at URI <code>/api/watch</code> as JSON strings: <code>{"name": "..", "data": ...}</code>
|
|
||||||
<div>Try <code>wscat --auth user1:pass1 --connect ws://localhost:8000/api/watch</code></div>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
const Login = function(props) {
|
|
||||||
const [user, setUser] = useState('');
|
|
||||||
const [pass, setPass] = useState('');
|
|
||||||
const login = ev =>
|
|
||||||
fetch(
|
|
||||||
'/api/login',
|
|
||||||
{headers: {Authorization: 'Basic ' + btoa(user + ':' + pass)}})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(r => r && props.login(r))
|
|
||||||
.catch(err => err);
|
|
||||||
return html`
|
return html`
|
||||||
<div class="rounded border" style="max-width: 480px; margin: 0 auto; margin-top: 5em; background: #eee; ">
|
<div class="bg-white sticky top-0 z-[48] xw-full border-b py-2 ${showSidebar && 'pl-72'} transition-all duration-300 transform">
|
||||||
<div style="padding: 2em; ">
|
<div class="px-2 w-full py-0 my-0 flex items-center">
|
||||||
<h1 style="color: #666;">Device Dashboard Login </h1>
|
<button type="button" onclick=${ev => setShowSidebar(v => !v)} class="text-slate-400">
|
||||||
<div style="margin: 0.5em 0;">
|
<${Icons.bars3} class="h-6" />
|
||||||
<input type='text' placeholder='Name' style="width: 100%;"
|
<//>
|
||||||
oninput=${ev => setUser(ev.target.value)} value=${user} />
|
<div class="flex flex-1 gap-x-4 self-stretch lg:gap-x-6">
|
||||||
</div>
|
<div class="relative flex flex-1"><//>
|
||||||
<div style="margin: 0.5em 0;">
|
<div class="flex items-center gap-x-4 lg:gap-x-6">
|
||||||
<input type="password" placeholder="Password" style="width: 100%;"
|
<span class="text-sm text-slate-400">logged in as: ${user}<//>
|
||||||
oninput=${ev => setPass(ev.target.value)} value=${pass}
|
<div class="hidden lg:block lg:h-4 lg:w-px lg:bg-gray-200" aria-hidden="true"><//>
|
||||||
onchange=${login} />
|
<${Button} title="Logout" icon=${Icons.logout} onclick=${logout} />
|
||||||
</div>
|
<//>
|
||||||
<div style="margin: 1em 0;">
|
<//>
|
||||||
<button class="btn" style="width: 100%; background: #8aa;"
|
<//>
|
||||||
disabled=${!user || !pass} onclick=${login}> Login </button>
|
<//>`;
|
||||||
</div>
|
|
||||||
<div style="color: #777; margin-top: 2em;">
|
|
||||||
Valid logins: admin:pass0, user1:pass1, user2:pass2
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function Sidebar({url, show}) {
|
||||||
const Configuration = function(props) {
|
const NavLink = ({title, icon, href, url}) => html`
|
||||||
const [url, setUrl] = useState(props.config.url || '');
|
|
||||||
const [pub, setPub] = useState(props.config.pub || '');
|
|
||||||
const [sub, setSub] = useState(props.config.sub || '');
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setUrl(props.config.url);
|
|
||||||
setPub(props.config.pub);
|
|
||||||
setSub(props.config.sub);
|
|
||||||
}, [props.config]);
|
|
||||||
|
|
||||||
const update = (name, val) => fetch('/api/config/set', {
|
|
||||||
method: 'post',
|
|
||||||
body: `${name}=${encodeURIComponent(val)}`
|
|
||||||
}).catch(err => err);
|
|
||||||
const updateurl = ev => update('url', url);
|
|
||||||
const updatepub = ev => update('pub', pub);
|
|
||||||
const updatesub = ev => update('sub', sub);
|
|
||||||
|
|
||||||
// console.log(props, [url, pub, sub]);
|
|
||||||
return html`
|
|
||||||
<div class="section">
|
|
||||||
<h3 style="background: #c03434; color: #fff; padding: 0.4em;">
|
|
||||||
Device Configuration</h3>
|
|
||||||
<div style="margin: 0.5em 0; display: flex;">
|
|
||||||
<span class="addon nowrap">MQTT server:</span>
|
|
||||||
<input type="text" style="flex: 1 100%;"
|
|
||||||
value=${url} onchange=${updateurl}
|
|
||||||
oninput=${ev => setUrl(ev.target.value)} />
|
|
||||||
<button class="btn" disabled=${!url} onclick=${updateurl}
|
|
||||||
style="margin-left: 1em; background: #8aa;">Update</button>
|
|
||||||
</div>
|
|
||||||
<div style="margin: 0.5em 0; display: flex; ">
|
|
||||||
<span class="addon nowrap">Subscribe topic:</span>
|
|
||||||
<input type="text" style="flex: 1 100%;"
|
|
||||||
value=${sub} onchange=${updatesub}
|
|
||||||
oninput=${ev => setSub(ev.target.value)} />
|
|
||||||
<button class="btn" disabled=${!sub} onclick=${updatesub}
|
|
||||||
style="margin-left: 1em; background: #8aa;">Update</button>
|
|
||||||
</div>
|
|
||||||
<div style="margin: 0.5em 0; display: flex;">
|
|
||||||
<span class="addon nowrap">Publish topic:</span>
|
|
||||||
<input type="text" style="flex: 1 100%;"
|
|
||||||
value=${pub} onchange=${updatepub}
|
|
||||||
oninput=${ev => setPub(ev.target.value)} />
|
|
||||||
<button class="btn" disabled=${!pub} onclick=${updatepub}
|
|
||||||
style="margin-left: 1em; background: #8aa;">Update</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
You can use <a href="http://www.hivemq.com/demos/websocket-client/">
|
<a href="#${href}" class="${href == url ? 'bg-slate-50 text-blue-600 group' : 'text-gray-700 hover:text-blue-600 hover:bg-gray-50 group'} flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold">
|
||||||
HiveMQ Websocket web client</a> to send messages to this console.
|
<${icon} class="w-6 h-6"/>
|
||||||
</div>
|
${title}
|
||||||
<div class="msg">
|
<///>
|
||||||
The device keeps a persistent connection to the configured MQTT server.
|
<//>`;
|
||||||
Changes to this configuration are propagated to all dashboards: try
|
return html`
|
||||||
changing them in this dashboard and observe changes in other opened
|
<div class="bg-violet-100 hs-overlay hs-overlay-open:translate-x-0
|
||||||
dashboards.
|
-translate-x-full transition-all duration-300 transform
|
||||||
</div><div class="msg">
|
fixed top-0 left-0 bottom-0 z-[60] w-72 bg-white border-r
|
||||||
Note: administrators can see this section and can change device
|
border-gray-200 overflow-y-auto scrollbar-y
|
||||||
configuration, whilst users cannot.
|
${show && 'translate-x-0'} right-auto bottom-0">
|
||||||
</div>
|
<div class="flex flex-col m-4 gap-y-6">
|
||||||
</div>`;
|
<div class="flex h-10 shrink-0 items-center gap-x-4 font-bold text-xl text-slate-500">
|
||||||
|
<${Logo} class="h-full"/> Your Brand
|
||||||
|
<//>
|
||||||
|
<div class="flex flex-1 flex-col">
|
||||||
|
<${NavLink} title="Dashboard" icon=${Icons.home} href="/" url=${url} />
|
||||||
|
<${NavLink} title="Settings" icon=${Icons.cog} href="/settings" url=${url} />
|
||||||
|
<${NavLink} title="Firmware Update" icon=${Icons.download} href="/update" url=${url} />
|
||||||
|
<${NavLink} title="Events" icon=${Icons.alert} href="/events" url=${url} />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function Events({}) {
|
||||||
|
const [events, setEvents] = useState([]);
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
|
||||||
const Message = m => html`<div style="margin: 0.5em 0;">
|
const refresh = () =>
|
||||||
<span class="qos">qos: ${m.message.qos} </span>
|
fetch('api/events/get', {
|
||||||
<span class="topic">topic: ${m.message.topic} </span>
|
method: 'POST', body: JSON.stringify({page: page}),
|
||||||
<span class="data">data: ${m.message.data}</span>
|
}).then(r => r.json())
|
||||||
</div>`;
|
.then(r => setEvents(r));
|
||||||
|
|
||||||
const Messages = function(props) {
|
useEffect(refresh, [page]);
|
||||||
const [messages, setMessages] = useState([]);
|
|
||||||
const [txt, setTxt] = useState('');
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const id = PubSub.subscribe(function(msg) {
|
setPage(JSON.parse(localStorage.getItem('page')));
|
||||||
if (msg.name == 'message') setMessages(x => x.concat([msg.data]));
|
}, []);
|
||||||
});
|
|
||||||
return PubSub.unsubscribe(id);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const sendmessage = ev => fetch('/api/message/send', {
|
|
||||||
method: 'post',
|
|
||||||
body: `message=${encodeURIComponent(txt)}`
|
|
||||||
}).then(r => setTxt(''));
|
|
||||||
const connstatus = props.config.connected ? 'connected' : 'disconnected';
|
|
||||||
return html`
|
|
||||||
<div class="section">
|
|
||||||
<h3 style="background: #30c040; color: #fff; padding: 0.4em;">MQTT messages</h3>
|
|
||||||
<div>
|
|
||||||
MQTT server status: <b>${connstatus}</b>
|
|
||||||
</div>
|
|
||||||
<div style="height: 10em; overflow: auto; padding: 0.5em; " class="border">
|
|
||||||
${messages.map(message => h(Message, {message}))}
|
|
||||||
</div>
|
|
||||||
<div style="margin: 0.5em 0; display: flex">
|
|
||||||
<span class="addon nowrap">Publish message:</span>
|
|
||||||
<input placeholder="type and press enter..." style="flex: 1 100%;"
|
|
||||||
value=${txt} onchange=${sendmessage}
|
|
||||||
oninput=${ev => setTxt(ev.target.value)} />
|
|
||||||
</div>
|
|
||||||
<div class="msg">
|
|
||||||
The message gets passed to the device via REST. Then the device sends it to
|
|
||||||
the MQTT server over MQTT. All MQTT messages on a subscribed topic
|
|
||||||
received by the device, are propagated to this dashboard via /api/watch.
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Expected arguments:
|
|
||||||
// data: timeseries, e.g. [ [1654361352, 19], [1654361353, 18], ... ]
|
|
||||||
// width, height, yticks, xticks, ymin, ymax, xmin, xmax
|
|
||||||
const SVG = function(props) {
|
|
||||||
// w
|
|
||||||
// +---------------------+
|
|
||||||
// | h1 |
|
|
||||||
// | +-----------+ |
|
|
||||||
// | | | | h
|
|
||||||
// | w1 | | w2 |
|
|
||||||
// | +-----------+ |
|
|
||||||
// | h2 |
|
|
||||||
// +---------------------+
|
|
||||||
//
|
|
||||||
let w = props.width, h = props.height, w1 = 30, w2 = 0, h1 = 8, h2 = 18;
|
|
||||||
let yticks = props.yticks || 4, xticks = props.xticks || 5;
|
|
||||||
let data = props.data || [];
|
|
||||||
let ymin = props.ymin || 0;
|
|
||||||
let ymax = props.ymax || Math.max.apply(null, data.map(p => p[1]));
|
|
||||||
let xmin = props.xmin || Math.min.apply(null, data.map(p => p[0]));
|
|
||||||
let xmax = props.xmax || Math.max.apply(null, data.map(p => p[0]));
|
|
||||||
|
|
||||||
// Y-axis tick lines and labels
|
|
||||||
let yta = (new Array(yticks + 1)).fill(0).map((_, i) => i); // indices
|
|
||||||
let yti = i => h - h2 - (h - h1 - h2) * i / yticks; // index's Y
|
|
||||||
let ytv = i => (ymax - ymin) * i / yticks;
|
|
||||||
let ytl = y => html`<line x1=${w1} y1=${y} x2=${w} y2=${y} class="tick"/>`;
|
|
||||||
let ytt = (y, v) => html`<text x=0 y=${y + 5} class="label">${v}</text>`;
|
|
||||||
|
|
||||||
// X-axis tick lines and labels
|
|
||||||
let datefmt = unix => (new Date(unix * 1000)).toISOString().substr(14, 5);
|
|
||||||
let xta = (new Array(xticks + 1)).fill(0).map((_, i) => i); // indices
|
|
||||||
let xti = i => w1 + (w - w1 - w2) * i / xticks; // index's X
|
|
||||||
let xtv = i => datefmt(xmin + (xmax - xmin) * i / xticks);
|
|
||||||
let xtl = x => html`<path d="M ${x},${h1} L ${x},${h - h2}" class="tick"/>`;
|
|
||||||
let xtt = (x, v) =>
|
|
||||||
html`<text x=${x - 15} y=${h - 2} class="label">${v}</text>`;
|
|
||||||
|
|
||||||
// Transform data points array into coordinate
|
|
||||||
let dx = v => w1 + (v - xmin) / ((xmax - xmin) || 1) * (w - w1 - w2);
|
|
||||||
let dy = v => h - h2 - (v - ymin) / ((ymax - ymin) || 1) * (h - h1 - h2);
|
|
||||||
let dd = data.map(p => [Math.round(dx(p[0])), Math.round(dy(p[1]))]);
|
|
||||||
let ddl = dd.length;
|
|
||||||
// And plot the data as <path> element
|
|
||||||
let begin0 = ddl ? `M ${dd[0][0]},${dd[0][1]}` : `M 0,0`;
|
|
||||||
let begin = `M ${w1},${h - h2}`; // Initial point
|
|
||||||
let end = ddl ? `L ${dd[ddl - 1][0]},${h - h2}` : `L ${w1},${h - h2}`;
|
|
||||||
let series = ddl ? dd.map(p => `L ${p[0]} ${p[1]}`) : [];
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<svg viewBox="0 0 ${w} ${h}">
|
|
||||||
<style>
|
|
||||||
.axis { stroke: #aaa; fill: none; }
|
|
||||||
.label { stroke: #aaa; font-size: 13px; }
|
|
||||||
.tick { stroke: #ccc; fill: none; stroke-dasharray: 5; }
|
|
||||||
.seriesbg { stroke: none; fill: rgba(200,225,255, 0.25)}
|
|
||||||
.series { stroke: #25a; fill: none; }
|
|
||||||
</style>
|
|
||||||
${yta.map(i => ytl(yti(i)))}
|
|
||||||
${yta.map(i => ytt(yti(i), ytv(i)))}
|
|
||||||
${xta.map(i => xtl(xti(i)))}
|
|
||||||
${data.length ? xta.map(i => xtt(xti(i), xtv(i))) : ''}
|
|
||||||
<path d="${begin} ${series.join(' ')} ${end}" class="seriesbg" />
|
|
||||||
<path d="${begin0} ${series.join(' ')}" class="series" />
|
|
||||||
</svg>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const Chart = function(props) {
|
|
||||||
const [data, setData] = useState([]);
|
|
||||||
useEffect(() => {
|
|
||||||
const id = PubSub.subscribe(function(msg) {
|
|
||||||
if (msg.name != 'metrics') return;
|
|
||||||
setData(x => x.concat([msg.data]).splice(-MaxMetricsDataPoints));
|
|
||||||
});
|
|
||||||
return PubSub.unsubscribe(id);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
let xmax = 0, missing = MaxMetricsDataPoints - data.length;
|
|
||||||
if (missing > 0) xmax = Math.round(Date.now() / 1000) + missing;
|
|
||||||
return html`
|
|
||||||
<div class="section">
|
|
||||||
<h3 style="background: #ec3; color: #fff; padding: 0.4em;">Data Chart</h3>
|
|
||||||
<div style="overflow: auto; padding: 0.5em;" class="">
|
|
||||||
<${SVG} height=240 width=600 ymin=0 ymax=20 xmax=${xmax} data=${data} />
|
|
||||||
</div>
|
|
||||||
<div class="msg">
|
|
||||||
This chart plots live sensor data, sent by the device via /api/watch.
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const App = function(props) {
|
|
||||||
const [user, setUser] = useState('');
|
|
||||||
const [config, setConfig] = useState({});
|
|
||||||
|
|
||||||
const getconfig = () =>
|
|
||||||
fetch('/api/config/get', {headers: {Authorization: ''}})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(r => setConfig(r))
|
|
||||||
.catch(err => console.log(err));
|
|
||||||
|
|
||||||
// Watch for notifications. As soon as a notification arrives, pass it on
|
|
||||||
// to all subscribed components
|
|
||||||
const watch = function() {
|
|
||||||
var l = window.location, proto = l.protocol.replace('http', 'ws');
|
|
||||||
var tid, wsURI = proto + '//' + l.host + '/api/watch'
|
|
||||||
var reconnect = function() {
|
|
||||||
var ws = new WebSocket(wsURI);
|
|
||||||
// ws.onopen = () => console.log('ws connected');
|
|
||||||
ws.onmessage = function(ev) {
|
|
||||||
try {
|
|
||||||
var msg = JSON.parse(ev.data);
|
|
||||||
PubSub.publish(msg);
|
|
||||||
// if (msg.name != 'metrics') console.log('ws->', msg);
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Invalid ws frame:', ev.data); // eslint-disable-line
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ws.onclose = function() {
|
|
||||||
clearTimeout(tid);
|
|
||||||
tid = setTimeout(reconnect, 1000);
|
|
||||||
console.log('ws disconnected');
|
|
||||||
};
|
|
||||||
};
|
|
||||||
reconnect();
|
|
||||||
};
|
|
||||||
|
|
||||||
const login = function(u) {
|
|
||||||
document.cookie = `access_token=${u.token}; Secure, HttpOnly; SameSite=Lax; path=/; max-age=3600`;
|
|
||||||
setUser(u.user);
|
|
||||||
watch();
|
|
||||||
return getconfig();
|
|
||||||
};
|
|
||||||
|
|
||||||
const logout = ev => {
|
|
||||||
document.cookie = `access_token=; Secure, HttpOnly; SameSite=Lax; path=/; max-age=0`;
|
|
||||||
setUser('');
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Called once at init time
|
localStorage.setItem('page', page.toString());
|
||||||
PubSub.subscribe(msg => msg.name == 'config' && getconfig());
|
}, [page]);
|
||||||
fetch('/api/login', {headers: {Authorization: ''}})
|
|
||||||
.then(r => r.json())
|
|
||||||
.then(r => login(r))
|
|
||||||
.catch(err => setUser(''));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (!user) return html`<${Login} login=${login} />`;
|
const Th = props => html`<th scope="col" class="sticky top-0 z-10 border-b border-slate-300 bg-white bg-opacity-75 py-1.5 px-4 text-left text-sm font-semibold text-slate-900 backdrop-blur backdrop-filter">${props.title}</th>`;
|
||||||
|
const Td = props => html`<td class="whitespace-nowrap border-b border-slate-200 py-2 px-4 pr-3 text-sm text-slate-900">${props.text}</td>`;
|
||||||
|
const Prio = ({prio}) => {
|
||||||
|
const text = ['high', 'medium', 'low'][prio];
|
||||||
|
const colors = [tipColors.red, tipColors.yellow, tipColors.green][prio];
|
||||||
|
return html`<${Colored} colors=${colors} text=${text} />`;
|
||||||
|
};
|
||||||
|
|
||||||
return html`
|
const Event = ({e}) => html`
|
||||||
<${Nav} user=${user} logout=${logout} />
|
<tr>
|
||||||
<div class="container">
|
<${Td} text=${['power', 'hardware', 'tier3', 'tier4'][e.type]} />
|
||||||
<div class="row">
|
<${Td} text=${html`<${Prio} prio=${e.prio}/>`} />
|
||||||
<div class="col col-6"><${Hero} /></div>
|
<${Td} text=${e.time ? (new Date(e.time * 1000)).toLocaleString() : '1970-01-01'} />
|
||||||
<div class="col col-6"><${Chart} /></div>
|
<${Td} text=${e.text} />
|
||||||
<div class="col col-6">
|
<//>`;
|
||||||
${user == 'admin' && h(Configuration, {config})}
|
|
||||||
|
return html`
|
||||||
|
<div class="m-4 divide-y divide-gray-200 overflow-auto rounded bg-white">
|
||||||
|
<div class="font-semibold flex items-center text-gray-600 px-3 justify-between whitespace-nowrap">
|
||||||
|
<div class="font-semibold flex items-center text-gray-600">
|
||||||
|
<div class="mr-4">EVENT LOG</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col col-6"><${Messages} config=${config} /></div>
|
<${Pagination} currentPage=${page} setPageFn=${setPage} totalItems=400 itemsPerPage=20 />
|
||||||
</div>
|
<//>
|
||||||
</div>`;
|
<div class="inline-block min-w-full align-middle" style="max-height: 82vh; overflow: auto;">
|
||||||
|
<table class="min-w-full border-separate border-spacing-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<${Th} title="Type" />
|
||||||
|
<${Th} title="Prio" />
|
||||||
|
<${Th} title="Time" />
|
||||||
|
<${Th} title="Description" />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${(events.arr ? events.arr : []).map(e => h(Event, {e}))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Chart({data}) {
|
||||||
|
const n = data.length /* entries */, w = 20 /* entry width */, ls = 15/* left space */;
|
||||||
|
const h = 100 /* graph height */, yticks = 5 /* Y axis ticks */, bs = 10 /* bottom space */;
|
||||||
|
const ymax = 25;
|
||||||
|
const yt = i => (h - bs) / yticks * (i + 1);
|
||||||
|
const bh = p => (h - bs) * p / 100; // Bar height
|
||||||
|
const by = p => (h - bs) - bh(p);
|
||||||
|
const range = (start, size, step) => Array.from({length: size}, (_, i) => i * (step || 1) + start);
|
||||||
|
// console.log(ds);
|
||||||
|
return html`
|
||||||
|
<div class="my-4 divide-y divide-gray-200 overflow-auto rounded bg-white">
|
||||||
|
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
|
||||||
|
Temperature, last 24h
|
||||||
|
<//>
|
||||||
|
<div class="relative">
|
||||||
|
<svg class="bg-yellow-x50 w-full p-4" viewBox="0 0 ${n*w+ls} ${h}">
|
||||||
|
${range(0, yticks).map(i => html`
|
||||||
|
<line x1=0 y1=${yt(i)} x2=${ls+n*w} y2=${yt(i)} stroke-width=0.3 class="stroke-slate-300" stroke-dasharray="1,1" />
|
||||||
|
<text x=0 y=${yt(i)-2} class="text-[6px] fill-slate-400">${ymax-ymax/yticks*(i+1)}<//>
|
||||||
|
`)}
|
||||||
|
${range(0, n).map(x => html`
|
||||||
|
<rect x=${ls+x*w} y=${by(data[x]*100/ymax)} width=12 height=${bh(data[x]*100/ymax)} rx=2 class="fill-cyan-500" />
|
||||||
|
<text x=${ls+x*w} y=100 class="text-[6px] fill-slate-400">${x*2}:00<//>
|
||||||
|
`)}
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
function DeveloperNote({text, children}) {
|
||||||
|
return html`
|
||||||
|
<div class="flex p-4 gap-2">
|
||||||
|
<div class="text-sm text-slate-500">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<${Icons.info} class="self-start basis-[30px] grow-0 shrink-0 text-green-600 mr-2" />
|
||||||
|
<div class="font-semibold">Developer Note<//>
|
||||||
|
<//>
|
||||||
|
${(text || '').split('.').map(v => html` <p class="my-2 ">${v}<//>`)}
|
||||||
|
${children}
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Main({}) {
|
||||||
|
const [stats, setStats] = useState(null);
|
||||||
|
const refresh = () => fetch('api/stats/get').then(r => r.json()).then(r => setStats(r));
|
||||||
|
useEffect(refresh, []);
|
||||||
|
if (!stats) return '';
|
||||||
|
return html`
|
||||||
|
<div class="p-2">
|
||||||
|
<div class="p-4 sm:p-2 mx-auto grid grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
|
<${Stat} title="Temperature" text="${stats.temperature} °C" tipText="good" tipIcon=${Icons.ok} tipColors=${tipColors.green} />
|
||||||
|
<${Stat} title="Humidity" text="${stats.humidity} %" tipText="warn" tipIcon=${Icons.warn} tipColors=${tipColors.yellow} />
|
||||||
|
<div class="bg-white col-span-2 border rounded-md shadow-lg" role="alert">
|
||||||
|
<${DeveloperNote} text="Stats data is received from the Mongoose backend" />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<div class="p-4 sm:p-2 mx-auto grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||||
|
|
||||||
|
<${Chart} data=${stats.points} />
|
||||||
|
|
||||||
|
<div class="my-4 hx-24 bg-white border rounded-md shadow-lg" role="alert">
|
||||||
|
<${DeveloperNote}
|
||||||
|
text="This chart is an SVG image, generated on the fly from the
|
||||||
|
data returned by the api/stats/get API call" />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
function FirmwareStatus({title, info, children}) {
|
||||||
|
const state = ['UNAVAILABLE', 'FIRST_BOOT', 'NOT_COMMITTED', 'COMMITTED'][(info.status || 0) % 4];
|
||||||
|
const valid = info.status > 0;
|
||||||
|
return html`
|
||||||
|
<div class="bg-white py-1 divide-y border rounded">
|
||||||
|
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
|
||||||
|
${title}
|
||||||
|
<//>
|
||||||
|
<div class="px-4 py-2 relative">
|
||||||
|
<div class="my-1">Status: ${state}<//>
|
||||||
|
<div class="my-1">CRC32: ${valid ? info.crc32.toString(16) : 'n/a'}<//>
|
||||||
|
<div class="my-1">Size: ${valid ? info.size : 'n/a'}<//>
|
||||||
|
<div class="my-1">Flashed at: ${valid ? new Date(info.timestamp * 1000).toLocaleString() : 'n/a'}<//>
|
||||||
|
${children}
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function FirmwareUpdate({}) {
|
||||||
|
const [info, setInfo] = useState([{}, {}]);
|
||||||
|
const refresh = () => fetch('api/firmware/status').then(r => r.json()).then(r => setInfo(r));
|
||||||
|
useEffect(refresh, []);
|
||||||
|
const oncommit = ev => fetch('api/firmware/commit')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(refresh);
|
||||||
|
const onreboot = ev => fetch('api/device/reset')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(r => new Promise(r => setTimeout(ev => { refresh(); r(); }, 3000)));
|
||||||
|
const onrollback = ev => fetch('api/firmware/rollback')
|
||||||
|
.then(onreboot);
|
||||||
|
const onerase = ev => fetch('api/device/eraselast').then(refresh);
|
||||||
|
const onupload = function(ok, name, size) {
|
||||||
|
if (!ok) return false;
|
||||||
|
return new Promise(r => setTimeout(ev => { refresh(); r(); }, 3000));
|
||||||
|
};
|
||||||
|
return html`
|
||||||
|
<div class="m-4 gap-4 grid grid-cols-1 lg:grid-cols-3">
|
||||||
|
<${FirmwareStatus} title="Current firmware image" info=${info[0]}>
|
||||||
|
<div class="flex flex-wrap gap-2">
|
||||||
|
<${Button} title="Commit this firmware" onclick=${oncommit}
|
||||||
|
icon=${Icons.thumbUp} disabled=${info[0].status == 3} cls="w-full" />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<${FirmwareStatus} title="Previous firmware image" info=${info[1]}>
|
||||||
|
<${Button} title="Rollback to this firmware" onclick=${onrollback}
|
||||||
|
icon=${Icons.backward} disabled=${info[1].status == 0} cls="w-full" />
|
||||||
|
<//>
|
||||||
|
<div class="bg-white xm-4 divide-y border rounded flex flex-col">
|
||||||
|
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
|
||||||
|
Device control
|
||||||
|
<//>
|
||||||
|
<div class="px-4 py-3 flex flex-col gap-2 grow">
|
||||||
|
<${UploadFileButton}
|
||||||
|
title="Upload new firmware .bin file" onupload=${onupload}
|
||||||
|
url="api/firmware/upload" accept=".bin,.uf2" />
|
||||||
|
<div class="grow"><//>
|
||||||
|
<${Button} title="Reboot device" onclick=${onreboot} icon=${Icons.refresh} cls="w-full" />
|
||||||
|
<${Button} title="Erase last sector" onclick=${onerase} icon=${Icons.doc} cls="w-full hidden" />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="m-4 gap-4 grid grid-cols-1 lg:grid-cols-2">
|
||||||
|
<div class="bg-white border shadow-lg">
|
||||||
|
<${DeveloperNote}>
|
||||||
|
<div class="my-2">
|
||||||
|
Firmware status and other information is stored in the last sector
|
||||||
|
of flash
|
||||||
|
<//>
|
||||||
|
<div class="my-2">
|
||||||
|
Firmware status can be FIRST_BOOT, UNCOMMITTED or COMMITTED. If no
|
||||||
|
information is available, it is UNAVAILABLE.
|
||||||
|
<//>
|
||||||
|
<div class="my-2">
|
||||||
|
This GUI loads a firmware file and sends it chunk by chunk to the
|
||||||
|
device, passing current chunk offset, total firmware size and a file name:
|
||||||
|
api/firmware/upload?offset=X&total=Y&name=Z
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
|
||||||
|
<div class="bg-white border shadow-lg">
|
||||||
|
<${DeveloperNote}>
|
||||||
|
<div>
|
||||||
|
Firmware update mechanism defines 3 API functions that the target
|
||||||
|
device must implement: mg_ota_begin(), mg_ota_write() and mg_ota_end()
|
||||||
|
<//>
|
||||||
|
<div class="my-2">
|
||||||
|
RESTful API handlers use ota_xxx() API to save firmware to flash.
|
||||||
|
The last 0-length chunk triggers ota_end() which performs firmware
|
||||||
|
update using saved firmware image
|
||||||
|
<//>
|
||||||
|
<div class="my-2">
|
||||||
|
<a class="link text-blue-600 underline"
|
||||||
|
href="https://mongoose.ws/webinars/">Join our free webinar</a> to
|
||||||
|
get detailed explanations about possible firmware updates strategies
|
||||||
|
and implementation demo
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
function Settings({}) {
|
||||||
|
const [settings, setSettings] = useState(null);
|
||||||
|
const [saveResult, setSaveResult] = useState(null);
|
||||||
|
const refresh = () => fetch('api/settings/get')
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(r => setSettings(r));
|
||||||
|
useEffect(refresh, []);
|
||||||
|
|
||||||
|
const mksetfn = k => (v => setSettings(x => Object.assign({}, x, {[k]: v})));
|
||||||
|
const onsave = ev => fetch('api/settings/set', {
|
||||||
|
method: 'post', body: JSON.stringify(settings)
|
||||||
|
}).then(r => r.json())
|
||||||
|
.then(r => setSaveResult(r))
|
||||||
|
.then(refresh);
|
||||||
|
|
||||||
|
if (!settings) return '';
|
||||||
|
const logOptions = [[0, 'Disable'], [1, 'Error'], [2, 'Info'], [3, 'Debug']];
|
||||||
|
return html`
|
||||||
|
<div class="m-4 grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
|
|
||||||
|
<div class="py-1 divide-y border rounded bg-white flex flex-col">
|
||||||
|
<div class="font-light uppercase flex items-center text-gray-600 px-4 py-2">
|
||||||
|
Device Settings
|
||||||
|
<//>
|
||||||
|
<div class="py-2 px-5 flex-1 flex flex-col relative">
|
||||||
|
${saveResult && html`<${Notification} ok=${saveResult.status}
|
||||||
|
text=${saveResult.message} close=${() => setSaveResult(null)} />`}
|
||||||
|
|
||||||
|
<${Setting} title="Enable Logs" value=${settings.log_enabled} setfn=${mksetfn('log_enabled')} type="switch" />
|
||||||
|
<${Setting} title="Log Level" value=${settings.log_level} setfn=${mksetfn('log_level')} type="select" addonLeft="0-3" disabled=${!settings.log_enabled} options=${logOptions}/>
|
||||||
|
<${Setting} title="Brightness" value=${settings.brightness} setfn=${mksetfn('brightness')} type="number" addonRight="%" />
|
||||||
|
<${Setting} title="Device Name" value=${settings.device_name} setfn=${mksetfn('device_name')} type="" />
|
||||||
|
<div class="mb-1 mt-3 flex place-content-end"><${Button} icon=${Icons.save} onclick=${onsave} title="Save Settings" /><//>
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
|
||||||
|
<div class="bg-white border rounded-md text-ellipsis overflow-auto" role="alert">
|
||||||
|
<${DeveloperNote}
|
||||||
|
text="A variety of controls are pre-defined to ease the development:
|
||||||
|
toggle button, dropdown select, input field with left and right
|
||||||
|
addons. Device settings are received by calling
|
||||||
|
api/settings/get API call, which returns settings JSON object.
|
||||||
|
Clicking on the save button calls api/settings/set
|
||||||
|
API call" />
|
||||||
|
<//>
|
||||||
|
|
||||||
|
<//>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const App = function({}) {
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [url, setUrl] = useState('/');
|
||||||
|
const [user, setUser] = useState('');
|
||||||
|
const [showSidebar, setShowSidebar] = useState(true);
|
||||||
|
|
||||||
|
const logout = () => fetch('api/logout').then(r => setUser(''));
|
||||||
|
const login = r => !r.ok ? setLoading(false) && setUser(null) : r.json()
|
||||||
|
.then(r => setUser(r.user))
|
||||||
|
.finally(r => setLoading(false));
|
||||||
|
|
||||||
|
useEffect(() => fetch('api/login').then(login), []);
|
||||||
|
|
||||||
|
if (loading) return ''; // Show blank page on initial load
|
||||||
|
if (!user) return html`<${Login} loginFn=${login} logoIcon=${Logo}
|
||||||
|
title="Device Dashboard Login"
|
||||||
|
tipText="To login, use: admin/admin, user1/user1, user2/user2" />`; // If not logged in, show login screen
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="min-h-screen bg-slate-100">
|
||||||
|
<${Sidebar} url=${url} show=${showSidebar} />
|
||||||
|
<${Header} logout=${logout} user=${user} showSidebar=${showSidebar} setShowSidebar=${setShowSidebar} />
|
||||||
|
<div class="${showSidebar && 'pl-72'} transition-all duration-300 transform">
|
||||||
|
<${Router} onChange=${ev => setUrl(ev.url)} history=${History.createHashHistory()} >
|
||||||
|
<${Main} default=${true} />
|
||||||
|
<${Settings} path="settings" />
|
||||||
|
<${FirmwareUpdate} path="update" />
|
||||||
|
<${Events} path="events" />
|
||||||
|
<//>
|
||||||
|
<//>
|
||||||
|
<//>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
window.onload = () => render(h(App), document.body);
|
window.onload = () => render(h(App), document.body);
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
PROG ?= example
|
|
||||||
SOURCES ?= ../../mongoose.c main.c packed_fs.c
|
|
||||||
CFLAGS ?= -I../.. -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_LINES=1 $(EXTRA)
|
|
||||||
FILES_TO_EMBED ?= $(wildcard web_root/*)
|
|
||||||
ROOT ?= $(realpath $(CURDIR)/../../..)
|
|
||||||
DOCKER ?= docker run --rm -e Tmp=. -e WINEDEBUG=-all -v $(ROOT):$(ROOT) -w $(CURDIR)
|
|
||||||
VC98 ?= $(DOCKER) mdashnet/vc98 wine
|
|
||||||
MINGW ?= $(DOCKER) mdashnet/mingw
|
|
||||||
|
|
||||||
all: $(PROG)
|
|
||||||
$(RUN) ./$(PROG)
|
|
||||||
|
|
||||||
$(PROG): $(SOURCES) $(FILES_TO_EMBED)
|
|
||||||
$(CC) ../../test/pack.c -o pack
|
|
||||||
./pack $(FILES_TO_EMBED) > packed_fs.c
|
|
||||||
$(CC) -W -Wall -Wextra -O0 -g3 $(CFLAGS) -o $(PROG) $(SOURCES)
|
|
||||||
|
|
||||||
|
|
||||||
mingw: $(SOURCES) $(FILES_TO_EMBED)
|
|
||||||
$(MINGW) i686-w64-mingw32-gcc $(CFLAGS) ../../test/pack.c -o pack.exe
|
|
||||||
$(MINGW) wine cmd /c 'pack.exe $(FILES_TO_EMBED) > packed_fs.c'
|
|
||||||
$(MINGW) i686-w64-mingw32-gcc $(CFLAGS) $(SOURCES) -lws2_32 -o $(PROG).exe
|
|
||||||
$(MINGW) wine $(PROG).exe
|
|
||||||
|
|
||||||
vc98: $(SOURCES) $(FILES_TO_EMBED)
|
|
||||||
$(VC98) cl.exe /nologo $(CFLAGS) ../../test/pack.c /Fepack.exe
|
|
||||||
$(VC98) cmd /c 'pack.exe $(FILES_TO_EMBED) > packed_fs.c'
|
|
||||||
$(VC98) cl.exe /nologo /O2 $(CFLAGS) $(SOURCES) /Fe$(PROG).exe
|
|
||||||
$(VC98) $(PROG).exe
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb log.txt pack
|
|
||||||
|
|
||||||
.PHONY: compress expand gzipped plain all
|
|
||||||
|
|
||||||
gzipped: compress
|
|
||||||
$(MAKE) all
|
|
||||||
|
|
||||||
plain: expand
|
|
||||||
$(MAKE) all
|
|
||||||
|
|
||||||
compress:
|
|
||||||
for file in $(FILES_TO_EMBED) ; do \
|
|
||||||
gzip -q $$file ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
expand:
|
|
||||||
for file in $(FILES_TO_EMBED) ; do \
|
|
||||||
gunzip -q $$file ; \
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -35,4 +35,4 @@ flash3:
|
|||||||
cd build && $(ESPTOOL) --chip esp32 -p $(PORT) -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x100000 mongoose-esp32-example.bin
|
cd build && $(ESPTOOL) --chip esp32 -p $(PORT) -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x100000 mongoose-esp32-example.bin
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(DOCKER) rm -rf build sdkconfig
|
test -d build && $(DOCKER) rm -rf build sdkconfig || true
|
||||||
@@ -3,5 +3,5 @@ idf_component_register(SRCS "main.c"
|
|||||||
"net.c"
|
"net.c"
|
||||||
"packed_fs.c"
|
"packed_fs.c"
|
||||||
"mongoose.c")
|
"mongoose.c")
|
||||||
component_compile_options(-DMG_ENABLE_LINES)
|
component_compile_options(-DHTTP_URL="http://0.0.0.0:80")
|
||||||
component_compile_options(-DMG_ENABLE_PACKED_FS)
|
component_compile_options(-DHTTPS_URL="https://0.0.0.0:443")
|
||||||
@@ -1,25 +1,13 @@
|
|||||||
// Copyright (c) 2020 Cesanta Software Limited
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
// All rights reserved
|
// All rights reserved
|
||||||
|
|
||||||
#include "esp_spiffs.h"
|
|
||||||
//#include "freertos/FreeRTOS.h"
|
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
#include "net.h"
|
||||||
const char *s_listening_url = "http://0.0.0.0:80";
|
|
||||||
void device_dashboard_fn(struct mg_connection *, int, void *, void *);
|
|
||||||
|
|
||||||
#define WIFI_SSID "YOUR_WIFI_NETWORK_NAME" // SET THIS!
|
#define WIFI_SSID "YOUR_WIFI_NETWORK_NAME" // SET THIS!
|
||||||
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
|
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
|
||||||
#define FS_ROOT "/spiffs"
|
|
||||||
|
|
||||||
void app_main(void) {
|
void app_main(void) {
|
||||||
// Mount filesystem
|
|
||||||
esp_vfs_spiffs_conf_t conf = {
|
|
||||||
.base_path = FS_ROOT, .max_files = 20, .format_if_mount_failed = true};
|
|
||||||
int res = esp_vfs_spiffs_register(&conf);
|
|
||||||
MG_INFO(("FS %s, %d", conf.base_path, res));
|
|
||||||
mg_file_printf(&mg_fs_posix, FS_ROOT "/hello.txt", "%s", "hello from ESP");
|
|
||||||
|
|
||||||
// Setup wifi. This function is implemented in wifi.c
|
// Setup wifi. This function is implemented in wifi.c
|
||||||
// It blocks until connected to the configured WiFi network
|
// It blocks until connected to the configured WiFi network
|
||||||
void wifi_init(const char *ssid, const char *pass);
|
void wifi_init(const char *ssid, const char *pass);
|
||||||
@@ -29,7 +17,249 @@ void app_main(void) {
|
|||||||
struct mg_mgr mgr;
|
struct mg_mgr mgr;
|
||||||
mg_log_set(MG_LL_DEBUG); // Set log level
|
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
MG_INFO(("Mongoose v%s on %s", MG_VERSION, s_listening_url));
|
MG_INFO(("Mongoose version : v%s", MG_VERSION));
|
||||||
mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, &mgr);
|
MG_INFO(("Listening on : %s", HTTP_URL));
|
||||||
|
#if MG_ENABLE_MBEDTLS
|
||||||
|
MG_INFO(("Listening on : %s", HTTPS_URL));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
web_init(&mgr);
|
||||||
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MG_DEVICE == MG_DEVICE_CUSTOM
|
||||||
|
void *mg_flash_start(void) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size_t mg_flash_size(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t mg_flash_sector_size(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
size_t mg_flash_write_align(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int mg_flash_bank(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool mg_flash_erase(void *location) {
|
||||||
|
(void) location;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool mg_flash_swap_bank(void) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool mg_flash_write(void *addr, const void *buf, size_t len) {
|
||||||
|
(void) addr, (void) buf, (void) len;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void mg_device_reset(void) {
|
||||||
|
esp_restart();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_OTA == MG_OTA_CUSTOM
|
||||||
|
#include "esp_app_format.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
|
||||||
|
static size_t s_size = 0; // Firmware size to flash. In-progress indicator
|
||||||
|
static bool rx_checked = false; // Whether firmware being received has been checked as valid
|
||||||
|
const esp_partition_t * update_partition = NULL; // The partition the update is being applied to
|
||||||
|
esp_ota_handle_t update_handle = 0; // Handle of the current update process
|
||||||
|
|
||||||
|
const esp_partition_t * get_partition_from_fw(int fw) {
|
||||||
|
if (MG_FIRMWARE_CURRENT == fw) {
|
||||||
|
return esp_ota_get_running_partition();
|
||||||
|
}
|
||||||
|
const esp_partition_t * p = esp_ota_get_last_invalid_partition();
|
||||||
|
if (NULL == p) {
|
||||||
|
p = esp_ota_get_next_update_partition(NULL);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the data buffer contains the header of a valid firmware
|
||||||
|
const size_t fw_size_required = sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t);
|
||||||
|
bool check_fw_header(const void* buf, size_t len) {
|
||||||
|
// Ensure we have received enough data to do the check
|
||||||
|
if (len < fw_size_required) {
|
||||||
|
MG_ERROR(("Insufficient data to check firmware header - %d bytes, require %d bytes", len, fw_size_required));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the magic word of the received firmare
|
||||||
|
esp_app_desc_t* rx_app_info = (esp_app_desc_t*)(((char*)buf) + sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t));
|
||||||
|
if (ESP_APP_DESC_MAGIC_WORD != rx_app_info->magic_word) {
|
||||||
|
MG_ERROR(("Invalid app - invalid magic word"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MG_INFO(("Received firmware: %s %s", rx_app_info->project_name, rx_app_info->version));
|
||||||
|
|
||||||
|
// Get the name/version of the running firmware
|
||||||
|
const esp_partition_t *current = esp_ota_get_running_partition();
|
||||||
|
esp_app_desc_t curr_app_info;
|
||||||
|
esp_err_t res = esp_ota_get_partition_description(current, &curr_app_info);
|
||||||
|
if (ESP_OK != res) {
|
||||||
|
MG_ERROR(("Unable to get name/version of running firmware"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MG_INFO(("Running firmware: %s %s", curr_app_info.project_name, curr_app_info.version));
|
||||||
|
|
||||||
|
// Check the name of the new firmware is the same as the old firmware
|
||||||
|
if (memcmp(curr_app_info.project_name, rx_app_info->project_name, sizeof(curr_app_info.project_name)) != 0) {
|
||||||
|
MG_ERROR(("Firmware name is different. Wrong firmware uploaded! Current %s Uploaded %s", curr_app_info.project_name, rx_app_info->project_name));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the version of the new firmware is different from the old firmware
|
||||||
|
if (memcmp(curr_app_info.version, rx_app_info->version, sizeof(curr_app_info.version)) == 0) {
|
||||||
|
MG_ERROR(("Firmware version is the same. Wrong firmware uploaded! Current %s, Uploaded %s", curr_app_info.version, rx_app_info->version));
|
||||||
|
//return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_ota_begin(size_t new_firmware_size) {
|
||||||
|
rx_checked = false;
|
||||||
|
if (s_size) {
|
||||||
|
MG_ERROR(("OTA already in progress. Call mg_ota_end()"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int partition_size = mg_ota_size(MG_FIRMWARE_PREVIOUS);
|
||||||
|
if (new_firmware_size > partition_size) {
|
||||||
|
MG_ERROR(("Firmware %lu bytes, max %lu", new_firmware_size, partition_size));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
update_partition = esp_ota_get_next_update_partition(NULL);
|
||||||
|
if (NULL == update_partition) {
|
||||||
|
MG_ERROR(("esp_ota_get_next_update_partition returned NULL"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
esp_err_t res = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle);
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
esp_ota_abort(update_handle);
|
||||||
|
MG_ERROR(("esp_ota_begin failed (%s)", esp_err_to_name(res)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s_size = new_firmware_size;
|
||||||
|
MG_INFO(("Starting OTA, firmware size %lu", s_size));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_ota_write(const void *buf, size_t len) {
|
||||||
|
if (s_size == 0) {
|
||||||
|
MG_ERROR(("OTA is not started, call mg_ota_begin()"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!rx_checked) {
|
||||||
|
if (!check_fw_header(buf, len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rx_checked = true;
|
||||||
|
}
|
||||||
|
esp_err_t res = esp_ota_write(update_handle, buf, len);
|
||||||
|
if (res != ESP_OK) {
|
||||||
|
esp_ota_abort(update_handle);
|
||||||
|
MG_ERROR(("esp_ota_write FAILED (%s)", esp_err_to_name(res)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_ota_end(void) {
|
||||||
|
if (0 == s_size) {
|
||||||
|
MG_INFO(("Finishing OTA: fail"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
s_size = 0;
|
||||||
|
esp_err_t err = esp_ota_end(update_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
MG_ERROR(("esp_ota_end failed (%s)!", esp_err_to_name(err)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
err = esp_ota_set_boot_partition(update_partition);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
MG_ERROR(("esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_ota_commit(void) {
|
||||||
|
esp_ota_mark_app_valid_cancel_rollback();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_ota_rollback(void) {
|
||||||
|
if(esp_ota_check_rollback_is_possible()) {
|
||||||
|
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
MG_ERROR(("Rollback NOT possible"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mg_ota_status(int fw) {
|
||||||
|
const esp_partition_t *p = get_partition_from_fw(fw);
|
||||||
|
if (NULL == p) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int status = MG_OTA_UNAVAILABLE;
|
||||||
|
|
||||||
|
esp_ota_img_states_t img_state = ESP_OTA_IMG_UNDEFINED;
|
||||||
|
esp_err_t res = esp_ota_get_state_partition(p, &img_state);
|
||||||
|
if (ESP_OK == res) {
|
||||||
|
if (ESP_OTA_IMG_VALID == img_state) {
|
||||||
|
status = MG_OTA_COMMITTED;
|
||||||
|
} else if (ESP_OTA_IMG_UNDEFINED == img_state) {
|
||||||
|
status = MG_OTA_UNCOMMITTED;
|
||||||
|
} else if (ESP_OTA_IMG_INVALID == img_state) {
|
||||||
|
status = MG_OTA_UNAVAILABLE;
|
||||||
|
} else if (ESP_OTA_IMG_ABORTED == img_state) {
|
||||||
|
status = MG_OTA_UNAVAILABLE;
|
||||||
|
} else if (ESP_OTA_IMG_NEW == img_state) {
|
||||||
|
status = MG_OTA_FIRST_BOOT;
|
||||||
|
} else if (ESP_OTA_IMG_PENDING_VERIFY == img_state) {
|
||||||
|
status = MG_OTA_UNCOMMITTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t mg_ota_crc32(int fw) {
|
||||||
|
(void) fw;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t mg_ota_timestamp(int fw) {
|
||||||
|
const esp_partition_t *p = get_partition_from_fw(fw);
|
||||||
|
|
||||||
|
esp_app_desc_t app;
|
||||||
|
esp_err_t res = esp_ota_get_partition_description(p, &app);
|
||||||
|
if (ESP_OK != res)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tm datetime = {};
|
||||||
|
if (NULL == strptime(app.date, "%b %d %Y", &datetime))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (NULL == strptime(app.time, "%H:%M:%S", &datetime))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return mktime(&datetime);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t mg_ota_size(int fw) {
|
||||||
|
const esp_partition_t *p = get_partition_from_fw(fw);
|
||||||
|
if (NULL == p) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return p->size;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#define MG_ARCH MG_ARCH_ESP32
|
||||||
|
|
||||||
|
#define MG_ENABLE_PACKED_FS 1
|
||||||
|
#define MG_TLS MG_TLS_NONE // change to 'MG_TLS_MBED' to enable TLS
|
||||||
|
#define MG_OTA MG_OTA_CUSTOM
|
||||||
|
#define MG_DEVICE MG_DEVICE_CUSTOM
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../device-dashboard/net.h
|
||||||
@@ -32,7 +32,7 @@ static void event_handler(void *arg, esp_event_base_t event_base,
|
|||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
} else if (event_base == WIFI_EVENT &&
|
} else if (event_base == WIFI_EVENT &&
|
||||||
event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||||
if (s_retry_num < 3) {
|
if (s_retry_num < 10) {
|
||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
s_retry_num++;
|
s_retry_num++;
|
||||||
MG_INFO(("retry to connect to the AP"));
|
MG_INFO(("retry to connect to the AP"));
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
nvs, data, nvs, 0x9000, 0x6000,
|
nvs, data, nvs, , 0x6000
|
||||||
phy_init, data, phy, 0xf000, 0x1000,
|
otadata, data, ota, , 0x2000,
|
||||||
storage, data, spiffs, 0x10000, 0x10000,
|
phy_init, data, phy, , 0x1000,
|
||||||
factory, app, factory, 0x100000, 1M,
|
ota_0, app, ota_0, , 948K,
|
||||||
|
ota_1, app, ota_1, , 948K,
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||||
|
CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y
|
||||||
#CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
#CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
THISDIR = $(realpath $(CURDIR))
|
||||||
|
ROOTDIR = $(realpath $(CURDIR)/../../..)
|
||||||
|
PORT ?= /dev/ttyUSB0
|
||||||
|
DOCKER ?= docker run --rm $(DA) -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) espressif/idf:v5.0.4
|
||||||
|
# Note that the esp32 port needs the extra .. for relative paths due to the location of its main CMakeLists.txt file
|
||||||
|
CMD ?= bash -c '$(MAKE) -C micropython/ports/esp32 submodules && $(MAKE) -C micropython/ports/esp32 USER_C_MODULES=../../../../mongoose/micropython.cmake'
|
||||||
|
|
||||||
|
all: example
|
||||||
|
|
||||||
|
example:
|
||||||
|
true
|
||||||
|
|
||||||
|
build: micropython
|
||||||
|
$(DOCKER) $(CMD)
|
||||||
|
|
||||||
|
micropython:
|
||||||
|
$(DOCKER) git clone --depth 1 -b v1.22.2 https://github.com/micropython/micropython.git
|
||||||
|
|
||||||
|
clean:
|
||||||
|
test -d micropython && $(DOCKER) rm -rf micropython || true
|
||||||
|
|
||||||
|
flash:
|
||||||
|
flash: DA = --device $(PORT)
|
||||||
|
flash: CMD = bash -c '$(MAKE) -C micropython/ports/esp32 erase deploy'
|
||||||
|
flash: build
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Mongoose as a MicroPython user module on the ESP32
|
||||||
|
|
||||||
|
The most basic usage is:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import network
|
||||||
|
import mongoose
|
||||||
|
|
||||||
|
sta_if = network.WLAN(network.STA_IF)
|
||||||
|
sta_if.active(True)
|
||||||
|
sta_if.connect("<SSID>", "<PASSWORD>")
|
||||||
|
while not sta_if.isconnected():
|
||||||
|
pass
|
||||||
|
|
||||||
|
mongoose.init()
|
||||||
|
while True:
|
||||||
|
mongoose.poll(1000)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Check [_thread](https://docs.micropython.org/en/latest/library/_thread.html) support for more advanced usage
|
||||||
|
|
||||||
|
https://docs.micropython.org/en/latest/develop/cmodules.html
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2022 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
static void t_fn(void *arg) { // Tick periodically
|
||||||
|
MG_INFO(("tick"));
|
||||||
|
(void) arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fn(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "hi\n");
|
||||||
|
(void) ev_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mg_mgr mgr;
|
||||||
|
|
||||||
|
void mgmp_init(void) {
|
||||||
|
mg_mgr_init(&mgr); // Mongoose event manager
|
||||||
|
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||||
|
|
||||||
|
mg_timer_add(&mgr, 1000, MG_TIMER_REPEAT, t_fn, &mgr);
|
||||||
|
mg_http_listen(&mgr, "http://0.0.0.0:80", fn, &mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mgmp_poll(int t) {
|
||||||
|
mg_mgr_poll(&mgr, t);
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../micropython/mongoose/micropython.cmake
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../micropython/mongoose/micropython.mk
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../micropython/mongoose/module.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../../mongoose.h
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#define MG_ARCH MG_ARCH_ESP32
|
||||||
@@ -1,30 +1,10 @@
|
|||||||
# A UART to network bridge for ESP32
|
# A UART to network bridge for ESP32
|
||||||
|
|
||||||
This example is a demonstration of how Mongoose Library could be integrated
|
|
||||||
into an embedded device and provide a UART-to-Network bridge capability:
|
|
||||||
|
|
||||||
- A device opens listening TCP port and Websocket port and waits for connections
|
|
||||||
- When a client connects, data is exchanged with the device's UART
|
|
||||||
- Everything that client send, is sent to the UART
|
|
||||||
- Everything that is read from the UART, gets sent to the client
|
|
||||||
- Multiple clients are allowed
|
|
||||||
- Live UART console allows to talk to the UART from the web page
|
|
||||||
- Web UI is hardcoded into the binary and does not need a filesystem
|
|
||||||
|
|
||||||
# Screenshots
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
# Build and flash
|
- See detailed tutorial at https://mongoose.ws/tutorials/esp32/uart-bridge/
|
||||||
|
|
||||||
Build requires Docker installed, and uses Espressif's ESP-IDF docker image:
|
## Flash pre-built firmware
|
||||||
|
|
||||||
```sh
|
|
||||||
make build
|
|
||||||
make flash PORT=/dev/YOURSERIAL
|
|
||||||
```
|
|
||||||
|
|
||||||
# Flash pre-built firmware
|
|
||||||
|
|
||||||
You can flash a pre-built firmware to the ESP32 device using the following
|
You can flash a pre-built firmware to the ESP32 device using the following
|
||||||
instructions:
|
instructions:
|
||||||
|
|||||||
@@ -5,6 +5,4 @@ idf_component_register(SRCS "main.c"
|
|||||||
"net.c"
|
"net.c"
|
||||||
"packed_fs.c"
|
"packed_fs.c"
|
||||||
"mongoose.c")
|
"mongoose.c")
|
||||||
component_compile_options(-DMG_ENABLE_LINES=1)
|
|
||||||
component_compile_options(-DMG_ENABLE_PACKED_FS=1)
|
|
||||||
component_compile_options(-DUART_API_IMPLEMENTED=1)
|
component_compile_options(-DUART_API_IMPLEMENTED=1)
|
||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
static void cli_wifi(const char *ssid, const char *pass) {
|
static void cli_wifi(const char *ssid, const char *pass) {
|
||||||
if (wifi_init(ssid, pass)) {
|
if (wifi_init(ssid, pass)) {
|
||||||
mg_file_printf(&mg_fs_posix, WIFI_FILE, "{%Q:%Q,%Q:%Q}\n", "ssid", ssid,
|
mg_file_printf(&mg_fs_posix, WIFI_FILE, "{%m:%m,%m:%m}\n", mg_print_esc, 0,
|
||||||
"pass", pass);
|
"ssid", mg_print_esc, 0, ssid, mg_print_esc, 0, "pass",
|
||||||
|
mg_print_esc, 0, pass);
|
||||||
MG_INFO(("Reboot now"));
|
MG_INFO(("Reboot now"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
const char *s_listening_url = "http://0.0.0.0:80";
|
const char *s_listening_url = "http://0.0.0.0:80";
|
||||||
|
|
||||||
char *config_read(void) {
|
struct mg_str config_read(void) {
|
||||||
return mg_file_read(&mg_fs_posix, FS_ROOT "/config.json", NULL);
|
return mg_file_read(&mg_fs_posix, FS_ROOT "/config.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
void config_write(struct mg_str config) {
|
void config_write(struct mg_str config) {
|
||||||
mg_file_write(&mg_fs_posix, FS_ROOT "/config.json", config.ptr, config.len);
|
mg_file_write(&mg_fs_posix, FS_ROOT "/config.json", config.buf, config.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_main(void) {
|
void app_main(void) {
|
||||||
@@ -21,14 +21,14 @@ void app_main(void) {
|
|||||||
MG_INFO(("FS at %s initialised, status: %d", conf.base_path, res));
|
MG_INFO(("FS at %s initialised, status: %d", conf.base_path, res));
|
||||||
|
|
||||||
// Try to connect to wifi by using saved WiFi credentials
|
// Try to connect to wifi by using saved WiFi credentials
|
||||||
char *json = mg_file_read(&mg_fs_posix, WIFI_FILE, NULL);
|
struct mg_str json = mg_file_read(&mg_fs_posix, WIFI_FILE);
|
||||||
if (json != NULL) {
|
if (json.buf != NULL) {
|
||||||
char *ssid = mg_json_get_str(mg_str(json), "$.ssid");
|
char *ssid = mg_json_get_str(json, "$.ssid");
|
||||||
char *pass = mg_json_get_str(mg_str(json), "$.pass");
|
char *pass = mg_json_get_str(json, "$.pass");
|
||||||
while (!wifi_init(ssid, pass)) (void) 0;
|
while (!wifi_init(ssid, pass)) (void) 0;
|
||||||
free(ssid);
|
free(ssid);
|
||||||
free(pass);
|
free(pass);
|
||||||
free(json);
|
free((void *) json.buf);
|
||||||
} else {
|
} else {
|
||||||
// If WiFi is not configured, run CLI until configured
|
// If WiFi is not configured, run CLI until configured
|
||||||
MG_INFO(("WiFi is not configured, running CLI. Press enter"));
|
MG_INFO(("WiFi is not configured, running CLI. Press enter"));
|
||||||
@@ -45,6 +45,6 @@ void app_main(void) {
|
|||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
mg_log_set(MG_LL_DEBUG); // Set log level
|
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||||
MG_INFO(("Mongoose v%s on %s", MG_VERSION, s_listening_url));
|
MG_INFO(("Mongoose v%s on %s", MG_VERSION, s_listening_url));
|
||||||
mg_http_listen(&mgr, s_listening_url, uart_bridge_fn, &mgr);
|
mg_http_listen(&mgr, s_listening_url, uart_bridge_fn, NULL);
|
||||||
for (;;) mg_mgr_poll(&mgr, 10); // Infinite event loop
|
for (;;) mg_mgr_poll(&mgr, 10); // Infinite event loop
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
#define WIFI_FILE FS_ROOT "/wifi.json"
|
#define WIFI_FILE FS_ROOT "/wifi.json"
|
||||||
#define UART_NO 1
|
#define UART_NO 1
|
||||||
|
|
||||||
void uart_bridge_fn(struct mg_connection *, int, void *, void *);
|
void uart_bridge_fn(struct mg_connection *, int, void *);
|
||||||
int uart_read(void *buf, size_t len);
|
int uart_read(void *buf, size_t len);
|
||||||
bool wifi_init(const char *ssid, const char *pass);
|
bool wifi_init(const char *ssid, const char *pass);
|
||||||
void cli(uint8_t ch);
|
void cli(uint8_t ch);
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#define MG_ARCH MG_ARCH_ESP32
|
||||||
|
|
||||||
|
#define MG_ENABLE_PACKED_FS 1
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# An example ESP8266 application
|
|
||||||
|
|
||||||
To build this application, follow these steps:
|
|
||||||
|
|
||||||
1. Make sure you have Docker installed
|
|
||||||
2. Clone whole mongoose repository on your machine:
|
|
||||||
```sh
|
|
||||||
git clone https://github.com/cesanta/mongoose.git
|
|
||||||
```
|
|
||||||
3. Start command line or terminal, and go into the example's directory:
|
|
||||||
```sh
|
|
||||||
cd mongoose/examples/esp8266
|
|
||||||
```
|
|
||||||
4. Run `make`. This invokes a Docker-based build. A firmware will be built
|
|
||||||
in the `src/build/` directory:
|
|
||||||
```sh
|
|
||||||
make build
|
|
||||||
```
|
|
||||||
5. Flash your ESP8266. If you have esptool.py installed, the build process will end telling you the command to flash your device. You can just run `make` again to use Docker:
|
|
||||||
```sh
|
|
||||||
make flash PORT=/your/serial
|
|
||||||
```
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
THISDIR = $(realpath $(CURDIR))
|
THISDIR = $(realpath $(CURDIR))
|
||||||
ROOTDIR = $(realpath $(CURDIR)/../..)
|
ROOTDIR = $(realpath $(CURDIR)/../../..)
|
||||||
DOCKER ?= docker run --rm $(DA) -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) docker.io/mdashnet/8266
|
DOCKER ?= docker run --rm $(DA) -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) docker.io/mdashnet/8266
|
||||||
CMD ?= make -C src defconfig app
|
CMD ?= make -C src defconfig app
|
||||||
PORT ?= /dev/ttyUSB0
|
PORT ?= /dev/ttyUSB0
|
||||||
@@ -41,6 +41,5 @@ monitor: build
|
|||||||
.PHONY: build
|
.PHONY: build
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
clean: CMD = rm -rf src/build
|
test -d src/build && $(DOCKER) rm -rf src/build || true
|
||||||
clean: build
|
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See detailed tutorial at https://mongoose.ws/tutorials/esp8266/http-client-server/
|
||||||
@@ -7,4 +7,3 @@
|
|||||||
# please read the ESP-IDF documents if you need to do this.
|
# please read the ESP-IDF documents if you need to do this.
|
||||||
#
|
#
|
||||||
|
|
||||||
COMPONENT_INCLUDES += ../../../../..
|
|
||||||
@@ -9,8 +9,8 @@
|
|||||||
#define SERVER_URL "http://0.0.0.0:80"
|
#define SERVER_URL "http://0.0.0.0:80"
|
||||||
#define CLIENT_URL "http://info.cern.ch"
|
#define CLIENT_URL "http://info.cern.ch"
|
||||||
|
|
||||||
// Event handler for an server (accepted) connection
|
// Event handler for a server (accepted) connection
|
||||||
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
static void cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
if (ev == MG_EV_HTTP_MSG) {
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
mg_http_reply(c, 200, "", "Hello from ESP!\n");
|
mg_http_reply(c, 200, "", "Hello from ESP!\n");
|
||||||
}
|
}
|
||||||
@@ -20,14 +20,14 @@ static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
// To enable TLS for HTTP,
|
// To enable TLS for HTTP,
|
||||||
// 1. Copy "ca.pem" file to the ESP8266 flash FS
|
// 1. Copy "ca.pem" file to the ESP8266 flash FS
|
||||||
// 2. Add TLS init snippet for the connection, see examples/http-client
|
// 2. Add TLS init snippet for the connection, see examples/http-client
|
||||||
static void cb2(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
static void cb2(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
if (ev == MG_EV_CONNECT) {
|
if (ev == MG_EV_CONNECT) {
|
||||||
struct mg_str s = mg_url_host(CLIENT_URL);
|
struct mg_str s = mg_url_host(CLIENT_URL);
|
||||||
mg_printf(c, "GET / HTTP/1.0\r\nHost: %.*s\r\n\r\n", (int) s.len, s.ptr);
|
mg_printf(c, "GET / HTTP/1.0\r\nHost: %.*s\r\n\r\n", (int) s.len, s.buf);
|
||||||
} else if (ev == MG_EV_HTTP_MSG) {
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
struct mg_http_message *hm = ev_data; // Print HTTP response
|
struct mg_http_message *hm = ev_data; // Print HTTP response
|
||||||
MG_INFO(("Fetched:\n%.*s", (int) hm->message.len, hm->message.ptr));
|
MG_INFO(("Fetched:\n%.*s", (int) hm->message.len, hm->message.buf));
|
||||||
c->is_closing = 1;
|
c->is_draining = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../../../mongoose.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../../../mongoose.h
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#define MG_ARCH MG_ARCH_ESP8266
|
||||||
|
|
||||||
@@ -0,0 +1,524 @@
|
|||||||
|
#
|
||||||
|
# Automatically generated file. DO NOT EDIT.
|
||||||
|
# Espressif IoT Development Framework (ESP-IDF) Project Configuration
|
||||||
|
#
|
||||||
|
CONFIG_IDF_TARGET_ESP8266=y
|
||||||
|
CONFIG_IDF_TARGET="esp8266"
|
||||||
|
|
||||||
|
#
|
||||||
|
# SDK tool configuration
|
||||||
|
#
|
||||||
|
CONFIG_SDK_TOOLPREFIX="xtensa-lx106-elf-"
|
||||||
|
CONFIG_SDK_PYTHON="python"
|
||||||
|
# CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES is not set
|
||||||
|
CONFIG_BOOTLOADER_INIT_SPI_FLASH=y
|
||||||
|
# CONFIG_BOOTLOADER_DISABLE_JTAG_IO is not set
|
||||||
|
# CONFIG_BOOTLOADER_FAST_BOOT is not set
|
||||||
|
# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set
|
||||||
|
# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set
|
||||||
|
# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set
|
||||||
|
CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y
|
||||||
|
# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set
|
||||||
|
# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
|
||||||
|
CONFIG_LOG_BOOTLOADER_LEVEL=3
|
||||||
|
# CONFIG_BOOTLOADER_APP_TEST is not set
|
||||||
|
CONFIG_BOOTLOADER_STORE_OFFSET=0x0
|
||||||
|
CONFIG_ESPTOOLPY_PORT="/dev/ttyACM0"
|
||||||
|
CONFIG_ESPTOOLPY_BAUD_115200B=y
|
||||||
|
# CONFIG_ESPTOOLPY_BAUD_230400B is not set
|
||||||
|
# CONFIG_ESPTOOLPY_BAUD_921600B is not set
|
||||||
|
# CONFIG_ESPTOOLPY_BAUD_2MB is not set
|
||||||
|
# CONFIG_ESPTOOLPY_BAUD_OTHER is not set
|
||||||
|
CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
|
||||||
|
CONFIG_ESPTOOLPY_BAUD=115200
|
||||||
|
CONFIG_ESPTOOLPY_COMPRESSED=y
|
||||||
|
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHMODE_DIO is not set
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set
|
||||||
|
CONFIG_ESPTOOLPY_FLASHMODE="dio"
|
||||||
|
CONFIG_SPI_FLASH_MODE=0x0
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set
|
||||||
|
CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
||||||
|
CONFIG_ESPTOOLPY_FLASHFREQ="40m"
|
||||||
|
CONFIG_SPI_FLASH_FREQ=0x0
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
|
||||||
|
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
|
||||||
|
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
||||||
|
CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
|
||||||
|
CONFIG_SPI_FLASH_SIZE=0x400000
|
||||||
|
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
||||||
|
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
||||||
|
CONFIG_ESPTOOLPY_BEFORE="default_reset"
|
||||||
|
CONFIG_ESPTOOLPY_AFTER_HARD_RESET=y
|
||||||
|
# CONFIG_ESPTOOLPY_AFTER_SOFT_RESET is not set
|
||||||
|
# CONFIG_ESPTOOLPY_AFTER_NORESET is not set
|
||||||
|
CONFIG_ESPTOOLPY_AFTER="hard_reset"
|
||||||
|
# CONFIG_ESPTOOLPY_MONITOR_BAUD_9600B is not set
|
||||||
|
# CONFIG_ESPTOOLPY_MONITOR_BAUD_57600B is not set
|
||||||
|
# CONFIG_ESPTOOLPY_MONITOR_BAUD_74880B is not set
|
||||||
|
CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y
|
||||||
|
# CONFIG_ESPTOOLPY_MONITOR_BAUD_230400B is not set
|
||||||
|
# CONFIG_ESPTOOLPY_MONITOR_BAUD_921600B is not set
|
||||||
|
# CONFIG_ESPTOOLPY_MONITOR_BAUD_2MB is not set
|
||||||
|
# CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER is not set
|
||||||
|
CONFIG_ESPTOOLPY_MONITOR_BAUD_OTHER_VAL=74880
|
||||||
|
CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
||||||
|
CONFIG_PARTITION_TABLE_SINGLE_APP=y
|
||||||
|
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
|
||||||
|
# CONFIG_PARTITION_TABLE_CUSTOM is not set
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
||||||
|
CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv"
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y
|
||||||
|
# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
|
||||||
|
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
|
||||||
|
# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set
|
||||||
|
# CONFIG_COMPILER_CXX_EXCEPTIONS is not set
|
||||||
|
CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
|
||||||
|
# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set
|
||||||
|
# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set
|
||||||
|
# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set
|
||||||
|
# CONFIG_COMPILER_STACK_CHECK is not set
|
||||||
|
# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set
|
||||||
|
CONFIG_APP_UPDATE_CHECK_APP_SUM=y
|
||||||
|
# CONFIG_APP_UPDATE_CHECK_APP_HASH is not set
|
||||||
|
CONFIG_APP_COMPILE_TIME_DATE=y
|
||||||
|
# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set
|
||||||
|
# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set
|
||||||
|
# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set
|
||||||
|
# CONFIG_ENABLE_COAP is not set
|
||||||
|
CONFIG_ESP_TLS_USING_MBEDTLS=y
|
||||||
|
# CONFIG_ESP_TLS_USING_WOLFSSL is not set
|
||||||
|
# CONFIG_ESP_TLS_SERVER is not set
|
||||||
|
# CONFIG_ESP_TLS_PSK_VERIFICATION is not set
|
||||||
|
# CONFIG_ESP_WOLFSSL_INTERNAL is not set
|
||||||
|
# CONFIG_WOLFSSL_DEBUG is not set
|
||||||
|
CONFIG_ESP8266_NMI_WDT=y
|
||||||
|
# CONFIG_ESP8266_XTAL_FREQ_40 is not set
|
||||||
|
CONFIG_ESP8266_XTAL_FREQ_26=y
|
||||||
|
CONFIG_ESP8266_XTAL_FREQ=26
|
||||||
|
# CONFIG_ESP8266_DEFAULT_CPU_FREQ_80 is not set
|
||||||
|
CONFIG_ESP8266_DEFAULT_CPU_FREQ_160=y
|
||||||
|
CONFIG_ESP8266_DEFAULT_CPU_FREQ_MHZ=160
|
||||||
|
CONFIG_ESP_FILENAME_MACRO_NO_PATH=y
|
||||||
|
# CONFIG_ESP_FILENAME_MACRO_RAW is not set
|
||||||
|
# CONFIG_ESP_FILENAME_MACRO_NULL is not set
|
||||||
|
CONFIG_USING_NEW_ETS_VPRINTF=y
|
||||||
|
# CONFIG_LINK_ETS_PRINTF_TO_IRAM is not set
|
||||||
|
CONFIG_ETS_PRINTF_EXIT_WHEN_FLASH_RW=y
|
||||||
|
# CONFIG_SOC_FULL_ICACHE is not set
|
||||||
|
CONFIG_SOC_IRAM_SIZE=0xC000
|
||||||
|
# CONFIG_DISABLE_ROM_UART_PRINT is not set
|
||||||
|
# CONFIG_ESP_PANIC_PRINT_HALT is not set
|
||||||
|
CONFIG_ESP_PANIC_PRINT_REBOOT=y
|
||||||
|
# CONFIG_ESP_PANIC_SILENT_REBOOT is not set
|
||||||
|
# CONFIG_ESP_PANIC_GDBSTUB is not set
|
||||||
|
CONFIG_RESET_REASON=y
|
||||||
|
CONFIG_WIFI_PPT_TASKSTACK_SIZE=5120
|
||||||
|
CONFIG_ESP8266_CORE_GLOBAL_DATA_LINK_IRAM=y
|
||||||
|
# CONFIG_ESP8266_OTA_FROM_OLD is not set
|
||||||
|
# CONFIG_ESP8266_BOOT_COPY_APP is not set
|
||||||
|
CONFIG_ESP8266_TIME_SYSCALL_USE_FRC1=y
|
||||||
|
# CONFIG_ESP8266_TIME_SYSCALL_USE_NONE is not set
|
||||||
|
# CONFIG_PM_ENABLE is not set
|
||||||
|
CONFIG_SCAN_AP_MAX=99
|
||||||
|
CONFIG_WIFI_TX_RATE_SEQUENCE_FROM_HIGH=y
|
||||||
|
# CONFIG_ESP8266_WIFI_QOS_ENABLED is not set
|
||||||
|
# CONFIG_ESP8266_WIFI_AMPDU_RX_ENABLED is not set
|
||||||
|
# CONFIG_ESP8266_WIFI_AMSDU_ENABLED is not set
|
||||||
|
CONFIG_ESP8266_WIFI_RX_BUFFER_NUM=16
|
||||||
|
CONFIG_ESP8266_WIFI_LEFT_CONTINUOUS_RX_BUFFER_NUM=16
|
||||||
|
CONFIG_ESP8266_WIFI_RX_PKT_NUM=7
|
||||||
|
CONFIG_ESP8266_WIFI_TX_PKT_NUM=6
|
||||||
|
CONFIG_ESP8266_WIFI_NVS_ENABLED=y
|
||||||
|
CONFIG_ESP8266_WIFI_CONNECT_OPEN_ROUTER_WHEN_PWD_IS_SET=y
|
||||||
|
CONFIG_ESP8266_WIFI_ENABLE_WPA3_SAE=y
|
||||||
|
# CONFIG_ESP8266_WIFI_DEBUG_LOG_ENABLE is not set
|
||||||
|
CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y
|
||||||
|
# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set
|
||||||
|
CONFIG_ESP_PHY_INIT_DATA_VDD33_CONST=33
|
||||||
|
CONFIG_ESP8266_PHY_MAX_WIFI_TX_POWER=20
|
||||||
|
# CONFIG_ESP8266_HSPI_HIGH_THROUGHPUT is not set
|
||||||
|
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
|
||||||
|
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
|
||||||
|
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2048
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584
|
||||||
|
CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584
|
||||||
|
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
|
||||||
|
# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set
|
||||||
|
# CONFIG_ESP_CONSOLE_UART_NONE is not set
|
||||||
|
CONFIG_ESP_CONSOLE_UART_NUM=0
|
||||||
|
CONFIG_ESP_CONSOLE_UART_BAUDRATE=74880
|
||||||
|
# CONFIG_ESP_UART0_SWAP_IO is not set
|
||||||
|
CONFIG_ESP_TASK_WDT=y
|
||||||
|
CONFIG_ESP_TASK_WDT_PANIC=y
|
||||||
|
# CONFIG_ESP_TASK_WDT_TIMEOUT_13N is not set
|
||||||
|
# CONFIG_ESP_TASK_WDT_TIMEOUT_14N is not set
|
||||||
|
CONFIG_ESP_TASK_WDT_TIMEOUT_15N=y
|
||||||
|
CONFIG_ESP_TASK_WDT_TIMEOUT_S=15
|
||||||
|
# CONFIG_ESP_EVENT_LOOP_PROFILING is not set
|
||||||
|
CONFIG_ESP_EVENT_POST_FROM_ISR=y
|
||||||
|
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y
|
||||||
|
# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set
|
||||||
|
CONFIG_HTTP_BUF_SIZE=512
|
||||||
|
CONFIG_HTTPD_MAX_REQ_HDR_LEN=512
|
||||||
|
CONFIG_HTTPD_MAX_URI_LEN=512
|
||||||
|
CONFIG_OTA_BUF_SIZE=256
|
||||||
|
# CONFIG_OTA_ALLOW_HTTP is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set
|
||||||
|
CONFIG_FATFS_CODEPAGE_437=y
|
||||||
|
# CONFIG_FATFS_CODEPAGE_720 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_737 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_771 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_775 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_850 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_852 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_855 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_857 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_860 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_861 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_862 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_863 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_864 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_865 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_866 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_869 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_932 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_936 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_949 is not set
|
||||||
|
# CONFIG_FATFS_CODEPAGE_950 is not set
|
||||||
|
CONFIG_FATFS_CODEPAGE=437
|
||||||
|
CONFIG_FATFS_LFN_NONE=y
|
||||||
|
# CONFIG_FATFS_LFN_HEAP is not set
|
||||||
|
# CONFIG_FATFS_LFN_STACK is not set
|
||||||
|
CONFIG_FATFS_FS_LOCK=0
|
||||||
|
CONFIG_FATFS_TIMEOUT_MS=10000
|
||||||
|
CONFIG_FATFS_PER_FILE_CACHE=y
|
||||||
|
CONFIG_FMB_COMM_MODE_TCP_EN=y
|
||||||
|
CONFIG_FMB_TCP_PORT_DEFAULT=502
|
||||||
|
CONFIG_FMB_TCP_PORT_MAX_CONN=5
|
||||||
|
CONFIG_FMB_TCP_CONNECTION_TOUT_SEC=20
|
||||||
|
CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND=150
|
||||||
|
CONFIG_FMB_MASTER_DELAY_MS_CONVERT=200
|
||||||
|
CONFIG_FMB_QUEUE_LENGTH=20
|
||||||
|
CONFIG_FMB_PORT_TASK_STACK_SIZE=4096
|
||||||
|
CONFIG_FMB_SERIAL_BUF_SIZE=256
|
||||||
|
CONFIG_FMB_PORT_TASK_PRIO=10
|
||||||
|
CONFIG_FMB_CONTROLLER_SLAVE_ID_SUPPORT=y
|
||||||
|
CONFIG_FMB_CONTROLLER_SLAVE_ID=0x00112233
|
||||||
|
CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT=20
|
||||||
|
CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
|
||||||
|
CONFIG_FMB_CONTROLLER_STACK_SIZE=4096
|
||||||
|
CONFIG_FMB_EVENT_QUEUE_TIMEOUT=20
|
||||||
|
CONFIG_FMB_TIMER_GROUP=0
|
||||||
|
CONFIG_FMB_TIMER_INDEX=0
|
||||||
|
# CONFIG_FMB_TIMER_ISR_IN_IRAM is not set
|
||||||
|
# CONFIG_DISABLE_FREERTOS is not set
|
||||||
|
CONFIG_FREERTOS_UNICORE=y
|
||||||
|
# CONFIG_FREERTOS_ENABLE_REENT is not set
|
||||||
|
CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
|
||||||
|
CONFIG_FREERTOS_HZ=100
|
||||||
|
CONFIG_FREERTOS_MAX_HOOK=2
|
||||||
|
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024
|
||||||
|
CONFIG_FREERTOS_ISR_STACKSIZE=512
|
||||||
|
# CONFIG_FREERTOS_EXTENED_HOOKS is not set
|
||||||
|
CONFIG_FREERTOS_GLOBAL_DATA_LINK_IRAM=y
|
||||||
|
# CONFIG_FREERTOS_CODE_LINK_TO_IRAM is not set
|
||||||
|
CONFIG_FREERTOS_TIMER_STACKSIZE=2048
|
||||||
|
CONFIG_TASK_SWITCH_FASTER=y
|
||||||
|
# CONFIG_USE_QUEUE_SETS is not set
|
||||||
|
# CONFIG_ENABLE_FREERTOS_SLEEP is not set
|
||||||
|
# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set
|
||||||
|
# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set
|
||||||
|
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
|
||||||
|
# CONFIG_HEAP_DISABLE_IRAM is not set
|
||||||
|
# CONFIG_HEAP_TRACING is not set
|
||||||
|
CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
|
||||||
|
# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set
|
||||||
|
# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set
|
||||||
|
# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
|
||||||
|
# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set
|
||||||
|
# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL=3
|
||||||
|
CONFIG_LOG_COLORS=y
|
||||||
|
# CONFIG_LOG_SET_LEVEL is not set
|
||||||
|
CONFIG_LWIP_LOCAL_HOSTNAME="espressif"
|
||||||
|
CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
|
||||||
|
# CONFIG_LWIP_L2_TO_L3_COPY is not set
|
||||||
|
# CONFIG_LWIP_IRAM_OPTIMIZATION is not set
|
||||||
|
CONFIG_LWIP_TIMERS_ONDEMAND=y
|
||||||
|
CONFIG_LWIP_MAX_SOCKETS=10
|
||||||
|
# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set
|
||||||
|
# CONFIG_LWIP_SO_LINGER is not set
|
||||||
|
CONFIG_LWIP_SO_REUSE=y
|
||||||
|
CONFIG_LWIP_SO_REUSE_RXTOALL=y
|
||||||
|
# CONFIG_LWIP_SO_RCVBUF is not set
|
||||||
|
# CONFIG_LWIP_NETBUF_RECVINFO is not set
|
||||||
|
CONFIG_LWIP_IP4_FRAG=y
|
||||||
|
CONFIG_LWIP_IP6_FRAG=y
|
||||||
|
# CONFIG_LWIP_IP4_REASSEMBLY is not set
|
||||||
|
# CONFIG_LWIP_IP6_REASSEMBLY is not set
|
||||||
|
# CONFIG_LWIP_IP_FORWARD is not set
|
||||||
|
# CONFIG_LWIP_STATS is not set
|
||||||
|
# CONFIG_LWIP_ETHARP_TRUST_IP_MAC is not set
|
||||||
|
CONFIG_LWIP_ESP_GRATUITOUS_ARP=y
|
||||||
|
CONFIG_LWIP_GARP_TMR_INTERVAL=60
|
||||||
|
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32
|
||||||
|
CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y
|
||||||
|
# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set
|
||||||
|
CONFIG_LWIP_DHCPS_LEASE_UNIT=60
|
||||||
|
CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8
|
||||||
|
# CONFIG_LWIP_AUTOIP is not set
|
||||||
|
# CONFIG_LWIP_IPV6_AUTOCONFIG is not set
|
||||||
|
CONFIG_LWIP_NETIF_LOOPBACK=y
|
||||||
|
CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8
|
||||||
|
CONFIG_LWIP_MAX_ACTIVE_TCP=16
|
||||||
|
CONFIG_LWIP_MAX_LISTENING_TCP=16
|
||||||
|
CONFIG_LWIP_TCP_MAXRTX=12
|
||||||
|
CONFIG_LWIP_TCP_SYNMAXRTX=6
|
||||||
|
CONFIG_LWIP_TCP_MSS=1440
|
||||||
|
CONFIG_LWIP_TCP_TMR_INTERVAL=250
|
||||||
|
CONFIG_LWIP_TCP_MSL=60000
|
||||||
|
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=2880
|
||||||
|
CONFIG_LWIP_TCP_WND_DEFAULT=5760
|
||||||
|
CONFIG_LWIP_TCP_RECVMBOX_SIZE=6
|
||||||
|
CONFIG_LWIP_TCP_QUEUE_OOSEQ=y
|
||||||
|
# CONFIG_LWIP_TCP_SACK_OUT is not set
|
||||||
|
# CONFIG_LWIP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
|
||||||
|
CONFIG_LWIP_TCP_OVERSIZE_MSS=y
|
||||||
|
# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set
|
||||||
|
# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set
|
||||||
|
CONFIG_LWIP_TCP_RTO_TIME=3000
|
||||||
|
CONFIG_LWIP_MAX_UDP_PCBS=16
|
||||||
|
CONFIG_LWIP_UDP_RECVMBOX_SIZE=6
|
||||||
|
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2048
|
||||||
|
CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
|
||||||
|
# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set
|
||||||
|
CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF
|
||||||
|
# CONFIG_LWIP_PPP_SUPPORT is not set
|
||||||
|
CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3
|
||||||
|
CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5
|
||||||
|
# CONFIG_LWIP_MULTICAST_PING is not set
|
||||||
|
# CONFIG_LWIP_BROADCAST_PING is not set
|
||||||
|
CONFIG_LWIP_MAX_RAW_PCBS=16
|
||||||
|
# CONFIG_LWIP_IPV6 is not set
|
||||||
|
CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
|
||||||
|
CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000
|
||||||
|
CONFIG_LWIP_ESP_LWIP_ASSERT=y
|
||||||
|
# CONFIG_LWIP_DEBUG is not set
|
||||||
|
CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||||
|
# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
|
||||||
|
# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set
|
||||||
|
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
|
||||||
|
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
|
||||||
|
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
|
||||||
|
# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set
|
||||||
|
# CONFIG_MBEDTLS_DEBUG is not set
|
||||||
|
CONFIG_MBEDTLS_HAVE_TIME=y
|
||||||
|
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
|
||||||
|
CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
|
||||||
|
# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set
|
||||||
|
# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set
|
||||||
|
# CONFIG_MBEDTLS_TLS_DISABLED is not set
|
||||||
|
CONFIG_MBEDTLS_TLS_SERVER=y
|
||||||
|
CONFIG_MBEDTLS_TLS_CLIENT=y
|
||||||
|
CONFIG_MBEDTLS_TLS_ENABLED=y
|
||||||
|
# CONFIG_MBEDTLS_PSK_MODES is not set
|
||||||
|
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
|
||||||
|
CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
|
||||||
|
CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
|
||||||
|
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y
|
||||||
|
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y
|
||||||
|
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y
|
||||||
|
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y
|
||||||
|
CONFIG_MBEDTLS_SSL_RENEGOTIATION=y
|
||||||
|
# CONFIG_MBEDTLS_SSL_PROTO_SSL3 is not set
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1=y
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y
|
||||||
|
CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
|
||||||
|
# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set
|
||||||
|
CONFIG_MBEDTLS_SSL_ALPN=y
|
||||||
|
CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y
|
||||||
|
CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y
|
||||||
|
CONFIG_MBEDTLS_AES_C=y
|
||||||
|
# CONFIG_MBEDTLS_CAMELLIA_C is not set
|
||||||
|
# CONFIG_MBEDTLS_DES_C is not set
|
||||||
|
CONFIG_MBEDTLS_RC4_DISABLED=y
|
||||||
|
# CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT is not set
|
||||||
|
# CONFIG_MBEDTLS_RC4_ENABLED is not set
|
||||||
|
# CONFIG_MBEDTLS_BLOWFISH_C is not set
|
||||||
|
# CONFIG_MBEDTLS_XTEA_C is not set
|
||||||
|
CONFIG_MBEDTLS_CCM_C=y
|
||||||
|
CONFIG_MBEDTLS_GCM_C=y
|
||||||
|
# CONFIG_MBEDTLS_RIPEMD160_C is not set
|
||||||
|
CONFIG_MBEDTLS_PEM_PARSE_C=y
|
||||||
|
CONFIG_MBEDTLS_PEM_WRITE_C=y
|
||||||
|
CONFIG_MBEDTLS_X509_CRL_PARSE_C=y
|
||||||
|
CONFIG_MBEDTLS_X509_CSR_PARSE_C=y
|
||||||
|
CONFIG_MBEDTLS_ECP_C=y
|
||||||
|
CONFIG_MBEDTLS_ECDH_C=y
|
||||||
|
CONFIG_MBEDTLS_ECDSA_C=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y
|
||||||
|
CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
|
||||||
|
# CONFIG_util_assert is not set
|
||||||
|
# CONFIG_ESP_SHA is not set
|
||||||
|
CONFIG_ESP_AES=y
|
||||||
|
CONFIG_ESP_MD5=y
|
||||||
|
CONFIG_ESP_ARC4=y
|
||||||
|
# CONFIG_ENABLE_MDNS is not set
|
||||||
|
CONFIG_MQTT_PROTOCOL_311=y
|
||||||
|
CONFIG_MQTT_TRANSPORT_SSL=y
|
||||||
|
CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
|
||||||
|
CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y
|
||||||
|
# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set
|
||||||
|
# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set
|
||||||
|
# CONFIG_MQTT_CUSTOM_OUTBOX is not set
|
||||||
|
CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
|
||||||
|
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set
|
||||||
|
# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set
|
||||||
|
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||||
|
# CONFIG_OPENSSL_DEBUG is not set
|
||||||
|
CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
|
||||||
|
# CONFIG_OPENSSL_ASSERT_EXIT is not set
|
||||||
|
CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5
|
||||||
|
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
|
||||||
|
CONFIG_PTHREAD_STACK_MIN=768
|
||||||
|
CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread"
|
||||||
|
CONFIG_SPIFFS_MAX_PARTITIONS=3
|
||||||
|
CONFIG_SPIFFS_CACHE=y
|
||||||
|
CONFIG_SPIFFS_CACHE_WR=y
|
||||||
|
# CONFIG_SPIFFS_CACHE_STATS is not set
|
||||||
|
CONFIG_SPIFFS_PAGE_CHECK=y
|
||||||
|
CONFIG_SPIFFS_GC_MAX_RUNS=10
|
||||||
|
# CONFIG_SPIFFS_GC_STATS is not set
|
||||||
|
CONFIG_SPIFFS_PAGE_SIZE=256
|
||||||
|
CONFIG_SPIFFS_OBJ_NAME_LEN=32
|
||||||
|
CONFIG_SPIFFS_USE_MAGIC=y
|
||||||
|
CONFIG_SPIFFS_USE_MAGIC_LENGTH=y
|
||||||
|
CONFIG_SPIFFS_META_LENGTH=4
|
||||||
|
CONFIG_SPIFFS_USE_MTIME=y
|
||||||
|
# CONFIG_SPIFFS_DBG is not set
|
||||||
|
# CONFIG_SPIFFS_API_DBG is not set
|
||||||
|
# CONFIG_SPIFFS_GC_DBG is not set
|
||||||
|
# CONFIG_SPIFFS_CACHE_DBG is not set
|
||||||
|
# CONFIG_SPIFFS_CHECK_DBG is not set
|
||||||
|
# CONFIG_SPIFFS_TEST_VISUALISATION is not set
|
||||||
|
CONFIG_IP_LOST_TIMER_INTERVAL=120
|
||||||
|
CONFIG_TCPIP_ADAPTER_GLOBAL_DATA_LINK_IRAM=y
|
||||||
|
CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y
|
||||||
|
CONFIG_VFS_SUPPORT_TERMIOS=y
|
||||||
|
CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1
|
||||||
|
CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN=128
|
||||||
|
# CONFIG_WL_SECTOR_SIZE_512 is not set
|
||||||
|
CONFIG_WL_SECTOR_SIZE_4096=y
|
||||||
|
CONFIG_WL_SECTOR_SIZE=4096
|
||||||
|
# CONFIG_ENABLE_UNIFIED_PROVISIONING is not set
|
||||||
|
CONFIG_LTM_FAST=y
|
||||||
|
CONFIG_WPA_MBEDTLS_CRYPTO=y
|
||||||
|
# CONFIG_WPA_DEBUG_PRINT is not set
|
||||||
|
# CONFIG_WPA_TESTING_OPTIONS is not set
|
||||||
|
# CONFIG_WPA_WPS_WARS is not set
|
||||||
|
# CONFIG_WPA_11KV_SUPPORT is not set
|
||||||
|
|
||||||
|
# Deprecated options for backward compatibility
|
||||||
|
CONFIG_TARGET_PLATFORM="esp8266"
|
||||||
|
CONFIG_TOOLPREFIX="xtensa-lx106-elf-"
|
||||||
|
# CONFIG_MAKE_WARN_UNDEFINED_VARIABLES is not set
|
||||||
|
CONFIG_FLASHMODE_QIO=y
|
||||||
|
# CONFIG_FLASHMODE_QOUT is not set
|
||||||
|
# CONFIG_FLASHMODE_DIO is not set
|
||||||
|
# CONFIG_FLASHMODE_DOUT is not set
|
||||||
|
# CONFIG_MONITOR_BAUD_9600B is not set
|
||||||
|
# CONFIG_MONITOR_BAUD_57600B is not set
|
||||||
|
# CONFIG_MONITOR_BAUD_74880B is not set
|
||||||
|
CONFIG_MONITOR_BAUD_115200B=y
|
||||||
|
# CONFIG_MONITOR_BAUD_230400B is not set
|
||||||
|
# CONFIG_MONITOR_BAUD_921600B is not set
|
||||||
|
# CONFIG_MONITOR_BAUD_2MB is not set
|
||||||
|
# CONFIG_MONITOR_BAUD_OTHER is not set
|
||||||
|
CONFIG_MONITOR_BAUD_OTHER_VAL=74880
|
||||||
|
CONFIG_MONITOR_BAUD=115200
|
||||||
|
CONFIG_OPTIMIZATION_LEVEL_DEBUG=y
|
||||||
|
# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set
|
||||||
|
CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
|
||||||
|
# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
|
||||||
|
# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set
|
||||||
|
# CONFIG_CXX_EXCEPTIONS is not set
|
||||||
|
CONFIG_STACK_CHECK_NONE=y
|
||||||
|
# CONFIG_STACK_CHECK_NORM is not set
|
||||||
|
# CONFIG_STACK_CHECK_STRONG is not set
|
||||||
|
# CONFIG_STACK_CHECK_ALL is not set
|
||||||
|
# CONFIG_STACK_CHECK is not set
|
||||||
|
# CONFIG_WARN_WRITE_STRINGS is not set
|
||||||
|
CONFIG_MAIN_TASK_STACK_SIZE=3584
|
||||||
|
CONFIG_CONSOLE_UART_DEFAULT=y
|
||||||
|
# CONFIG_CONSOLE_UART_CUSTOM is not set
|
||||||
|
# CONFIG_CONSOLE_UART_NONE is not set
|
||||||
|
CONFIG_CONSOLE_UART_NUM=0
|
||||||
|
CONFIG_CONSOLE_UART_BAUDRATE=74880
|
||||||
|
# CONFIG_UART0_SWAP_IO is not set
|
||||||
|
CONFIG_TASK_WDT=y
|
||||||
|
CONFIG_TASK_WDT_PANIC=y
|
||||||
|
CONFIG_TASK_WDT_TIMEOUT_S=15
|
||||||
|
CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND=150
|
||||||
|
CONFIG_MB_MASTER_DELAY_MS_CONVERT=200
|
||||||
|
CONFIG_MB_QUEUE_LENGTH=20
|
||||||
|
CONFIG_MB_SERIAL_TASK_STACK_SIZE=4096
|
||||||
|
CONFIG_MB_SERIAL_BUF_SIZE=256
|
||||||
|
CONFIG_MB_SERIAL_TASK_PRIO=10
|
||||||
|
CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT=y
|
||||||
|
CONFIG_MB_CONTROLLER_SLAVE_ID=0x00112233
|
||||||
|
CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20
|
||||||
|
CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20
|
||||||
|
CONFIG_MB_CONTROLLER_STACK_SIZE=4096
|
||||||
|
CONFIG_MB_EVENT_QUEUE_TIMEOUT=20
|
||||||
|
CONFIG_MB_TIMER_GROUP=0
|
||||||
|
CONFIG_MB_TIMER_INDEX=0
|
||||||
|
# CONFIG_L2_TO_L3_COPY is not set
|
||||||
|
# CONFIG_USE_ONLY_LWIP_SELECT is not set
|
||||||
|
CONFIG_ESP_GRATUITOUS_ARP=y
|
||||||
|
CONFIG_GARP_TMR_INTERVAL=60
|
||||||
|
CONFIG_TCPIP_RECVMBOX_SIZE=32
|
||||||
|
CONFIG_TCP_MAXRTX=12
|
||||||
|
CONFIG_TCP_SYNMAXRTX=6
|
||||||
|
CONFIG_TCP_MSS=1440
|
||||||
|
CONFIG_TCP_MSL=60000
|
||||||
|
CONFIG_TCP_SND_BUF_DEFAULT=2880
|
||||||
|
CONFIG_TCP_WND_DEFAULT=5760
|
||||||
|
CONFIG_TCP_RECVMBOX_SIZE=6
|
||||||
|
CONFIG_TCP_QUEUE_OOSEQ=y
|
||||||
|
# CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES is not set
|
||||||
|
CONFIG_TCP_OVERSIZE_MSS=y
|
||||||
|
# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set
|
||||||
|
# CONFIG_TCP_OVERSIZE_DISABLE is not set
|
||||||
|
CONFIG_UDP_RECVMBOX_SIZE=6
|
||||||
|
CONFIG_TCPIP_TASK_STACK_SIZE=2048
|
||||||
|
CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
|
||||||
|
# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set
|
||||||
|
CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
|
||||||
|
# CONFIG_PPP_SUPPORT is not set
|
||||||
|
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
|
||||||
|
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072
|
||||||
|
CONFIG_ESP32_PTHREAD_STACK_MIN=768
|
||||||
|
CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
|
||||||
|
CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y
|
||||||
|
CONFIG_SUPPORT_TERMIOS=y
|
||||||
|
# End of deprecated options
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
SPROG ?= server # Program we are building
|
||||||
|
CPROG ?= client # Program we are building
|
||||||
|
DELETE = rm -rf # Command to remove files
|
||||||
|
SOUT ?= -o $(SPROG) # Compiler argument for output file
|
||||||
|
COUT ?= -o $(CPROG) # Compiler argument for output file
|
||||||
|
SSOURCES = server.c mongoose.c # Source code files
|
||||||
|
CSOURCES = client.c mongoose.c # Source code files
|
||||||
|
CFLAGS = -W -Wall -Wextra -g -I. # Build options
|
||||||
|
|
||||||
|
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
|
||||||
|
#CFLAGS_MONGOOSE += -DMG_ENABLE_LINES
|
||||||
|
|
||||||
|
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
|
||||||
|
SPROG ?= server.exe # Use .exe suffix for the binary
|
||||||
|
CPROG ?= client.exe # Use .exe suffix for the binary
|
||||||
|
CC = gcc # Use MinGW gcc compiler
|
||||||
|
CFLAGS += -lws2_32 # Link against Winsock library
|
||||||
|
DELETE = cmd /C del /Q /F /S # Command prompt command to delete files
|
||||||
|
SOUT ?= -o $(SPROG) # Build output
|
||||||
|
COUT ?= -o $(CPROG) # Build output
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: example # Default target. Build all and run server
|
||||||
|
$(RUN) ./$(SPROG) $(SARGS)
|
||||||
|
|
||||||
|
example: $(SPROG) $(CPROG)
|
||||||
|
|
||||||
|
$(SPROG): $(SSOURCES) # Build program from sources
|
||||||
|
$(CC) $(SSOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(SOUT)
|
||||||
|
|
||||||
|
$(CPROG): $(CSOURCES) # Build program from sources
|
||||||
|
$(CC) $(CSOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(COUT)
|
||||||
|
|
||||||
|
clean: # Cleanup. Delete built program and all build artifacts
|
||||||
|
$(DELETE) $(SPROG) $(CPROG) *.o *.obj *.exe *.dSYM
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
# File Transfer
|
||||||
|
|
||||||
|
This example contains minimal HTTP client and server.
|
||||||
|
|
||||||
|
The client uploads a file to the server in a single POST, shaping traffic to send small data chunks.
|
||||||
|
|
||||||
|
The server manually processes requests in order to be able to write as soon as data arrives, to avoid buffering a whole (possibly huge) file not fitting in RAM.
|
||||||
|
|
||||||
|
Uploads are authenticated using Basic Auth. Both client and server have a default user/pass and can be configured using the command line. Only authenticated users can upload a file.
|
||||||
|
|
||||||
|
The server can also accept regular uploads from any HTTP client, for example curl:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
curl -su user:pass http://localhost:8090/upload/foo.txt --data-binary @Makefile
|
||||||
|
```
|
||||||
|
|
||||||
|
- Follow the [Build Tools](../tools/) tutorial to setup your development environment.
|
||||||
|
- Start a terminal in this project directory; and build the example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd mongoose/examples/file-transfer
|
||||||
|
make clean all
|
||||||
|
```
|
||||||
|
|
||||||
|
- Manually start the server, either in background (to reuse the same terminal window) or in foreground; in which case you'll need another terminal to run the client. The server will listen at all interfaces in port 8090
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./server
|
||||||
|
6332b7 2 server.c:157:main Mongoose version : v7.12
|
||||||
|
6332b7 2 server.c:158:main Listening on : http://0.0.0.0:8090
|
||||||
|
6332b7 2 server.c:159:main Web root : [/home/mongoose/examples/file-transfer/web_root]
|
||||||
|
6332b7 2 server.c:160:main Uploading to : [/home/mongoose/examples/file-transfer/upload]
|
||||||
|
```
|
||||||
|
|
||||||
|
- Manually run the client to send a file, default is to send it as "foo.txt" to the server in localhost at port 8090
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./client -f Makefile
|
||||||
|
ok
|
||||||
|
```
|
||||||
|
|
||||||
|
Default operation is to assume hardcoded username and password. Call both server and client with no arguments to see usage instructions
|
||||||
|
|
||||||
|
See detailed tutorials at
|
||||||
|
https://mongoose.ws/tutorials/file-uploads/
|
||||||
|
https://mongoose.ws/tutorials/http-server/
|
||||||
|
https://mongoose.ws/tutorials/http-client/
|
||||||