mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-26 12:14:56 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
236724ea29 | ||
|
|
b503915ca5 | ||
|
|
156db0bc5e | ||
|
|
11b6bd7d9c | ||
|
|
7ca952faa6 | ||
|
|
4fc40f0ffb | ||
|
|
cac4b3e254 | ||
|
|
0d5cb5cbcc | ||
|
|
a35901121b | ||
|
|
e0740fc2ca | ||
|
|
7d22b5fe18 | ||
|
|
d2e66ac58d | ||
|
|
34cc8da87e | ||
|
|
1957ba8ffe | ||
|
|
72758812f5 | ||
|
|
ab5a0c43de | ||
|
|
c8291e4ae9 | ||
|
|
84e9ea76db | ||
|
|
b8994f8bc3 | ||
|
|
b53d8439e5 | ||
|
|
337e8abf2f | ||
|
|
f0bc1c031f | ||
|
|
19d2b93ec7 | ||
|
|
e0304f2b8f | ||
|
|
f7a86f8cf1 | ||
|
|
340f0dbf89 | ||
|
|
d90b62d911 | ||
|
|
d84aff6420 | ||
|
|
b3b73f4751 | ||
|
|
3c7b2dcd6d | ||
|
|
49470f9bd2 | ||
|
|
f7cf4f60ef | ||
|
|
7e0d06689e | ||
|
|
b843957bd2 | ||
|
|
1a0167eb6d | ||
|
|
6ea3b98941 | ||
|
|
4b0b93d4f3 | ||
|
|
64abf061bf | ||
|
|
05d5c68982 | ||
|
|
235dafe646 | ||
|
|
0cc40b0c70 | ||
|
|
07a0d1265b | ||
|
|
967d746574 | ||
|
|
bd12cb1b87 | ||
|
|
a21ca5d40b | ||
|
|
2d399107fb | ||
|
|
03bfa3806b | ||
|
|
6536ae9bcc | ||
|
|
e8fc817a0c | ||
|
|
e621ade392 | ||
|
|
3273c20ca9 | ||
|
|
a6b2124fd5 | ||
|
|
5a1ff125d7 | ||
|
|
ad58a48144 | ||
|
|
a205fd7877 | ||
|
|
776360ca93 | ||
|
|
af7602497d | ||
|
|
0f83c2a6e5 | ||
|
|
0d58748e63 | ||
|
|
01902bb8b9 | ||
|
|
e28e9aa1d7 | ||
|
|
587e79dc05 | ||
|
|
acd65f2340 | ||
|
|
d55fb80746 | ||
|
|
4536694f20 | ||
|
|
2c5a6d4df6 | ||
|
|
4c8e219643 | ||
|
|
daeca8128b | ||
|
|
fe6d357858 | ||
|
|
a99cc3dbaf | ||
|
|
3c4c04199a | ||
|
|
8ca692100f | ||
|
|
0b9f28b8e3 | ||
|
|
1dff394b63 | ||
|
|
f4c35d1036 | ||
|
|
81c166ad74 | ||
|
|
1f56776050 | ||
|
|
b3a0e7b884 | ||
|
|
8594507b5b | ||
|
|
fa811ce12b | ||
|
|
c1ef477ff3 | ||
|
|
4be3a96987 | ||
|
|
387f875aa1 | ||
|
|
cc069e7e5d | ||
|
|
df994df611 | ||
|
|
8f77fd3940 | ||
|
|
7530062e4b | ||
|
|
0e63510708 | ||
|
|
26260a1d88 | ||
|
|
9e82844f10 | ||
|
|
0568b5a75b | ||
|
|
3baabebb34 | ||
|
|
bf4dd15317 | ||
|
|
b0f2f9621a | ||
|
|
04d6d05e9e | ||
|
|
7339c7dfe7 | ||
|
|
c1152f5eeb | ||
|
|
024922d566 | ||
|
|
6f64c8c0de | ||
|
|
2a5ac3c2e5 | ||
|
|
7b0120f0c2 | ||
|
|
7ee1f14a6d | ||
|
|
3aaf7d0da7 | ||
|
|
434f3f8415 | ||
|
|
739d78a45a | ||
|
|
8a62633b2f | ||
|
|
aae1a687a9 | ||
|
|
61285ec418 | ||
|
|
a00b3f1c6c | ||
|
|
2c813f3e72 | ||
|
|
ea68d7a705 | ||
|
|
654f401038 | ||
|
|
ad89122a06 | ||
|
|
73ed158e76 | ||
|
|
548c3dc77f | ||
|
|
c1fa067a1f | ||
|
|
9fd87060f9 | ||
|
|
de0a3b035a | ||
|
|
9f76ea8030 | ||
|
|
76b7356873 | ||
|
|
c24d5aabd8 | ||
|
|
0df6645b90 | ||
|
|
b19cf8654f | ||
|
|
19933a4673 | ||
|
|
76963f7d01 | ||
|
|
e670ea3d61 | ||
|
|
fa33b57e4f | ||
|
|
77e369bc79 | ||
|
|
94ad9767d3 | ||
|
|
aa76f5673b | ||
|
|
81a699c801 | ||
|
|
bd15c456b2 | ||
|
|
10d9e1e9ae | ||
|
|
6a3813f633 | ||
|
|
51fe22a95f | ||
|
|
105762416f | ||
|
|
db7087f455 | ||
|
|
c5693503cb | ||
|
|
b74590a4a5 | ||
|
|
d5eeed48eb | ||
|
|
fc5c0d0964 | ||
|
|
aa2647c0bc | ||
|
|
cef0acdb40 | ||
|
|
2140656acc | ||
|
|
fd0c969f16 | ||
|
|
dfeb929e0e | ||
|
|
d3e67733a6 | ||
|
|
eff74fdc9d | ||
|
|
5e4c40ad09 | ||
|
|
087e6d3142 | ||
|
|
587b074822 | ||
|
|
6aa8c01ac7 | ||
|
|
3bbcd5df3e | ||
|
|
af512c57ef | ||
|
|
58297a7871 | ||
|
|
18a530048c | ||
|
|
f9ed75d6b3 | ||
|
|
3c1f41e575 | ||
|
|
c772936dd1 | ||
|
|
253696be45 | ||
|
|
79b7accc55 | ||
|
|
7a1e846c73 | ||
|
|
ce59ff89c3 | ||
|
|
d31d064d5e | ||
|
|
467fbf4bb4 | ||
|
|
6769223ce1 | ||
|
|
294e483885 | ||
|
|
43513e2d56 | ||
|
|
d1b7687e98 | ||
|
|
9ac09da1d2 | ||
|
|
24a330c750 | ||
|
|
13a9c773f2 | ||
|
|
3cd166d065 | ||
|
|
490066fd17 | ||
|
|
94fce72ade | ||
|
|
eacc64bdd1 | ||
|
|
7b037f4957 | ||
|
|
fa841916c1 | ||
|
|
75c11436ff | ||
|
|
e07a8283ec | ||
|
|
2a174b0d3b | ||
|
|
013993abae | ||
|
|
dccc153c68 | ||
|
|
db0867f435 | ||
|
|
7234121835 | ||
|
|
3aafc073d8 | ||
|
|
b527ed313c | ||
|
|
cd86559685 | ||
|
|
f67e843be6 | ||
|
|
4f9ebd8092 | ||
|
|
6c044d6aeb | ||
|
|
c6ee909aa4 | ||
|
|
393063428e | ||
|
|
1494f5e831 | ||
|
|
8bfd0c2ca3 | ||
|
|
e9de2f3eb1 | ||
|
|
8bf9d09d96 | ||
|
|
67255ce8f5 | ||
|
|
5db89aa264 | ||
|
|
8a9b1d9873 | ||
|
|
c08c1afb1e | ||
|
|
2c7f58aed2 | ||
|
|
b3ee71acbe | ||
|
|
52ab6bc499 | ||
|
|
bf059ad42f | ||
|
|
85df6a6131 | ||
|
|
d840b4a4ee | ||
|
|
a8c2ce544e | ||
|
|
b95022a3b3 | ||
|
|
8c45a9d2c9 | ||
|
|
0fe64fbff9 | ||
|
|
64e806628b | ||
|
|
ccd2b2699f | ||
|
|
0b5c0c9889 | ||
|
|
6293e7dbec | ||
|
|
87325ece82 | ||
|
|
6cbd9b3067 | ||
|
|
aa27fde9d0 | ||
|
|
e854585802 | ||
|
|
2c5aba24cc | ||
|
|
806ee0f2cb | ||
|
|
e72b95fb1c | ||
|
|
471e7ff61a | ||
|
|
3d2de154d1 | ||
|
|
fc551ec2e9 | ||
|
|
f5e2c68c8b | ||
|
|
074ef5197b | ||
|
|
5f1f4a0df8 | ||
|
|
86334e9040 | ||
|
|
f71cc3ebc3 | ||
|
|
00910462e7 | ||
|
|
2fc56dd1d0 | ||
|
|
a5ebe71394 | ||
|
|
0eb8bf6b51 | ||
|
|
3a0fe5288c | ||
|
|
bfca233160 | ||
|
|
acf217601b | ||
|
|
b0d0fbfd9f | ||
|
|
9411f1c7b6 | ||
|
|
d7d7ebf99a | ||
|
|
8072ae2057 | ||
|
|
e529e644ab | ||
|
|
d6fdfe5b1b | ||
|
|
50e15e574f | ||
|
|
58f1533779 | ||
|
|
f4a49829ea | ||
|
|
3efe6641eb | ||
|
|
0459d9e106 | ||
|
|
305d69ee36 | ||
|
|
98e744a9ad | ||
|
|
1d97f2e2b5 | ||
|
|
c92bc4b4ac | ||
|
|
6a3e1e41c4 | ||
|
|
650caface3 | ||
|
|
8b6e02e985 | ||
|
|
3ee6fe45f9 | ||
|
|
e811afd397 | ||
|
|
b197a674e1 | ||
|
|
08f6b99b13 | ||
|
|
b18d0301f3 | ||
|
|
5596621420 | ||
|
|
bd8a66eee7 | ||
|
|
b62ebb3c10 | ||
|
|
45d796fe5b | ||
|
|
d8a3b90cad | ||
|
|
5be9e55425 | ||
|
|
6b6acd3967 | ||
|
|
1b06403a19 | ||
|
|
b740c80855 | ||
|
|
29594283c1 | ||
|
|
51f54f9b7e | ||
|
|
1f48b1ca65 | ||
|
|
fd2d7cccf3 | ||
|
|
5726e680ec | ||
|
|
fadf28adb4 | ||
|
|
a321c2d096 | ||
|
|
bbb07bf6f7 | ||
|
|
a801160bc0 | ||
|
|
662cc27f4f | ||
|
|
ccfe7e0724 | ||
|
|
8061a41b38 | ||
|
|
d01aa01a51 | ||
|
|
39392b3690 | ||
|
|
54d4611eb6 | ||
|
|
34cdce750d | ||
|
|
f3fafb6759 | ||
|
|
0372c97ff5 | ||
|
|
b46136a0af | ||
|
|
ac3d41fb79 | ||
|
|
14be42c868 | ||
|
|
f0ec14543a | ||
|
|
f46c5b7214 | ||
|
|
ccd6bcd95f | ||
|
|
a3b63f3b0d | ||
|
|
f2905a5e10 | ||
|
|
1ef6c6aeb5 | ||
|
|
bd53529b45 | ||
|
|
cc8ecc5a42 | ||
|
|
5a816a1d41 | ||
|
|
9922286c67 | ||
|
|
cdc439bc38 | ||
|
|
ae8422e304 | ||
|
|
539d080346 | ||
|
|
041ec6e1f8 | ||
|
|
f618fe125c | ||
|
|
8ab514fabc | ||
|
|
08ad2c3145 | ||
|
|
c64fd404d4 | ||
|
|
143b0ac126 | ||
|
|
c2e2432010 | ||
|
|
1d2a768184 | ||
|
|
fb099641bc | ||
|
|
6da9afbf29 | ||
|
|
dceb4beb09 | ||
|
|
6f697db49d | ||
|
|
b44193780e | ||
|
|
8e0212c3db | ||
|
|
3861e2e1e7 | ||
|
|
21eefa4b55 | ||
|
|
fb6c6aafeb | ||
|
|
df07426e78 | ||
|
|
5cf1523a13 | ||
|
|
f2fe47e9f7 | ||
|
|
2557ab2e60 | ||
|
|
fbc1708000 | ||
|
|
0539cf1023 | ||
|
|
07b410447b | ||
|
|
fb69016196 | ||
|
|
169cbc044f | ||
|
|
08091d02e5 | ||
|
|
6f2dcf92a7 | ||
|
|
578e52618d | ||
|
|
ec0fe66a17 | ||
|
|
8fee24291a | ||
|
|
05bba2958d | ||
|
|
e656b1c792 | ||
|
|
e0ccbadd25 | ||
|
|
40a2a8822f | ||
|
|
e2ee356a87 | ||
|
|
189bef61d3 | ||
|
|
7d94f9f61b | ||
|
|
e37a0b9056 | ||
|
|
0b57b23951 | ||
|
|
c84826e84e | ||
|
|
064fc6ff7b | ||
|
|
042ea53478 | ||
|
|
900b0acf7a | ||
|
|
dc5f2e295a | ||
|
|
c1849c2b19 | ||
|
|
4eadf3699f | ||
|
|
b30cf6587c | ||
|
|
fbc231f33e | ||
|
|
bc8c839342 | ||
|
|
90a23fe230 | ||
|
|
065027843e | ||
|
|
8906b1ac0f | ||
|
|
05f9e61a41 | ||
|
|
782896b5d3 | ||
|
|
4258f62560 | ||
|
|
537ba64a54 | ||
|
|
25d20b7354 | ||
|
|
04d8362905 | ||
|
|
21266e9a45 | ||
|
|
7304e2171d | ||
|
|
61fc480850 | ||
|
|
562e82f5ac | ||
|
|
d7ff85bb48 | ||
|
|
55bc6105e1 | ||
|
|
306c0b6096 | ||
|
|
024078ae33 | ||
|
|
b5a9ba8390 | ||
|
|
93f36927ca | ||
|
|
1db90cafd1 | ||
|
|
bf23a0def7 | ||
|
|
ea1cbeea9d | ||
|
|
aeda7e5520 | ||
|
|
a7899af8b8 | ||
|
|
b0385f47af | ||
|
|
86c384657c | ||
|
|
6e569110d2 | ||
|
|
3b1024b13c | ||
|
|
b3f5d11275 | ||
|
|
1078ba0a92 | ||
|
|
005c8170d4 | ||
|
|
b8d1d7a10b | ||
|
|
76769fb4d5 | ||
|
|
6ff6f0a4c6 | ||
|
|
72a45d2f6a | ||
|
|
2fe7c8a410 | ||
|
|
5269eb9c39 | ||
|
|
a0d9b6a7e0 |
No files matched your search
@@ -11,17 +11,14 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
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'
|
||||||
@@ -30,7 +27,7 @@ jobs:
|
|||||||
language: c++
|
language: c++
|
||||||
- name: Upload Crash
|
- name: Upload Crash
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
if: env.GO == 1 && failure() && steps.build.outcome == 'success'
|
if: failure() && steps.build.outcome == 'success'
|
||||||
with:
|
with:
|
||||||
name: artifacts
|
name: artifacts
|
||||||
path: ./out/artifacts
|
path: ./out/artifacts
|
||||||
@@ -2,8 +2,8 @@ name: "CodeQL Scanning"
|
|||||||
# https://github.com/github/codeql-action
|
# https://github.com/github/codeql-action
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
#schedule:
|
||||||
- cron: '30 23 * * *' # run at 11:30 PM UTC
|
# - cron: '30 23 * * *' # run at 11:30 PM UTC
|
||||||
# Allow manual runs
|
# Allow manual runs
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
name: Fuzz
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 21 * * *' # run at 9 PM UTC
|
||||||
|
# Allow manual runs
|
||||||
|
workflow_dispatch:
|
||||||
|
env:
|
||||||
|
CC: clang
|
||||||
|
jobs:
|
||||||
|
fuzz:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
target: [fuzz, fuzz_tls]
|
||||||
|
name: ${{ matrix.target }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: make -C test ${{ matrix.target }} ARGS="-max_total_time=7200"
|
||||||
|
|
||||||
|
# as we're not getting access to test units causing a problem, convert from the log:
|
||||||
|
# base64 -d > dataofdeath
|
||||||
|
# then paste the base64 data, enter, Ctrl-D; maybe check with hexdump -C dataofdeath
|
||||||
+148
-179
@@ -33,11 +33,19 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CC: ${{ matrix.cc }}
|
CC: ${{ matrix.cc }}
|
||||||
SSL: ${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
TFLAGS: ${{ matrix.select }}
|
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST -DNO_ABORT
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && make -C test ${{ matrix.target }}
|
- uses: webfactory/ssh-agent@v0.9.1
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
|
||||||
|
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev && test/setup_mqtt_server.sh && make -C test ${{ matrix.target }} > log
|
||||||
|
- if: success() || failure()
|
||||||
|
run: |
|
||||||
|
cat log
|
||||||
|
test/health.awk < log > json
|
||||||
|
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/linux_${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.ssl }}_${{ matrix.select }}_$(date +"%Y%m%d").json"
|
||||||
mip:
|
mip:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -46,14 +54,40 @@ jobs:
|
|||||||
cc: [gcc, clang, g++, clang++]
|
cc: [gcc, clang, g++, clang++]
|
||||||
target: [mip_test, mip_tap_test]
|
target: [mip_test, mip_tap_test]
|
||||||
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||||
|
# #3226: built-in TCP is currently not working with WolfSSL (builds fine)
|
||||||
|
exclude:
|
||||||
|
- ssl: WOLFSSL
|
||||||
|
target: mip_tap_test
|
||||||
name: ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
name: ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
||||||
env:
|
env:
|
||||||
CC: ${{ matrix.cc }}
|
CC: ${{ matrix.cc }}
|
||||||
SSL: ${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST -DNO_ABORT
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
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
|
- uses: webfactory/ssh-agent@v0.9.1
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
|
||||||
|
- 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 > log
|
||||||
|
- if: success() || failure()
|
||||||
|
run: |
|
||||||
|
cat log
|
||||||
|
test/health.awk < log > json
|
||||||
|
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.ssl }}_$(date +"%Y%m%d").json"
|
||||||
|
|
||||||
|
mip89:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
max-parallel: 1 # no parallel runs, to minimize MQTT errors
|
||||||
|
matrix:
|
||||||
|
target: [mip_vc98]
|
||||||
|
name: mip89 ${{ matrix.target }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: make -C test ${{ matrix.target }}
|
||||||
s390:
|
s390:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -61,10 +95,12 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
ssl: ["", BUILTIN]
|
ssl: ["", BUILTIN]
|
||||||
name: S390 SSL=${{ matrix.ssl }}
|
name: S390 SSL=${{ matrix.ssl }}
|
||||||
|
env:
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390 SSL=${{ matrix.ssl }}
|
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390 SSL=${{ matrix.ssl }} MULTIREC=NO
|
||||||
armhf:
|
armhf:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -72,10 +108,12 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
ssl: ["", BUILTIN]
|
ssl: ["", BUILTIN]
|
||||||
name: ArmHF SSL=${{ matrix.ssl }}
|
name: ArmHF SSL=${{ matrix.ssl }}
|
||||||
|
env:
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf SSL=${{ matrix.ssl }}
|
- run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf SSL=${{ matrix.ssl }} MULTIREC=NO
|
||||||
unamalgamated-mg_prefix:
|
unamalgamated-mg_prefix:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -87,7 +125,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev
|
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev
|
||||||
- run: make -C test unamalgamated && make -C test mg_prefix
|
- run: make -C test unamalgamated SSL=${{ matrix.ssl }} && make -C test mg_prefix
|
||||||
valgrind:
|
valgrind:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -95,35 +133,53 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
||||||
name: Valgrind SSL=${{ matrix.ssl }}
|
name: Valgrind SSL=${{ matrix.ssl }}
|
||||||
|
env:
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev valgrind
|
- run: sudo apt -y update ; sudo apt -y install libmbedtls-dev libwolfssl-dev valgrind
|
||||||
- run: make -C test valgrind SSL=${{ matrix.ssl }}
|
- run: ./test/setup_mqtt_server.sh && make -C test valgrind SSL=${{ matrix.ssl }}
|
||||||
macos:
|
macos:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ssl: ["", BUILTIN, MBEDTLS, OPENSSL, WOLFSSL]
|
# Mongoose does not work with WolfSSL version in MacOS
|
||||||
|
ssl: ["", BUILTIN, MBEDTLS, OPENSSL] # , WOLFSSL]
|
||||||
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
|
select: [-DMG_ENABLE_POLL=0, -DMG_ENABLE_POLL=1]
|
||||||
|
include:
|
||||||
|
- ssl: MBEDTLS
|
||||||
|
env:
|
||||||
|
# MbedTLS version in MacOS refuses to validate a certificate without a hostname, causing MQTT tests to fail when using MQTT_LOCALHOST
|
||||||
|
tflags: -DNO_MQTT_TESTS
|
||||||
exclude:
|
exclude:
|
||||||
- ssl: MBEDTLS
|
- ssl: MBEDTLS
|
||||||
select: -DMG_ENABLE_POLL=0
|
select: -DMG_ENABLE_POLL=0
|
||||||
- ssl: OPENSSL
|
- ssl: OPENSSL
|
||||||
select: -DMG_ENABLE_POLL=0
|
select: -DMG_ENABLE_POLL=0
|
||||||
- ssl: WOLFSSL
|
#- ssl: WOLFSSL
|
||||||
select: -DMG_ENABLE_POLL=0
|
# select: -DMG_ENABLE_POLL=0
|
||||||
name: macos SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
name: macos SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||||
env:
|
env:
|
||||||
SSL: ${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
TFLAGS: ${{ matrix.select }} -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
|
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST ${{ matrix.env.tflags }} -Wno-sign-conversion # Workaround for MbedTLS 3.5.0
|
||||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: brew install mbedtls wolfssl # jq openssl already pre-installed
|
- uses: webfactory/ssh-agent@v0.9.1
|
||||||
- run: make -C test test ASAN_OPTIONS= MBEDTLS=$(echo $(brew --cellar)/mbedtls*/*) OPENSSL=$(echo $(brew --cellar)/openssl*/*) WOLFSSL=$(echo $(brew --cellar)/wolfssl*/*)
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
|
||||||
|
- run: brew install mbedtls wolfssl mosquitto gawk # jq openssl already pre-installed
|
||||||
|
- run: /opt/homebrew/opt/mosquitto/sbin/mosquitto -c /Users/runner/work/mongoose/mongoose/test/mosquitto.conf.macos &
|
||||||
|
- run: make -C test test ASAN_OPTIONS= MBEDTLS=$(echo $(brew --cellar)/mbedtls*/*) OPENSSL=$(echo $(brew --cellar)/openssl*/*) WOLFSSL=$(echo $(brew --cellar)/wolfssl*/*) > log
|
||||||
|
- if: success() || failure()
|
||||||
|
run: |
|
||||||
|
cat log
|
||||||
|
test/health.awk < log > json
|
||||||
|
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/macos_test_cc_${{ matrix.ssl }}_${{ matrix.select }}_$(date +"%Y%m%d").json"
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -138,12 +194,21 @@ jobs:
|
|||||||
select: -DMG_ENABLE_POLL=1
|
select: -DMG_ENABLE_POLL=1
|
||||||
name: windows ${{ matrix.target }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
name: windows ${{ matrix.target }} SSL=${{ matrix.ssl }} TFLAGS=${{ matrix.select }}
|
||||||
env:
|
env:
|
||||||
SSL: SSL=${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
TFLAGS: ${{ matrix.select }}
|
TFLAGS: ${{ matrix.select }} -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: make -C test ${{ matrix.target }}
|
- uses: webfactory/ssh-agent@v0.9.1
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
|
||||||
|
- run: ./test/setup_mqtt_server.sh && make -C test ${{ matrix.target }} > log
|
||||||
|
- if: success() || failure()
|
||||||
|
run: |
|
||||||
|
cat log
|
||||||
|
test/health.awk < log > json
|
||||||
|
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/windows_${{ matrix.target }}_${{ matrix.cc }}_${{ matrix.ssl }}_${{ matrix.select }}_$(date +"%Y%m%d").json"
|
||||||
|
|
||||||
arm:
|
arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -165,109 +230,33 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: make -C test riscv SSL=${{ matrix.ssl }}
|
- run: make -C test riscv SSL=${{ matrix.ssl }}
|
||||||
|
|
||||||
examples:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
ssl: [-DMG_TLS=MG_TLS_NONE, -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:
|
tutorials:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
ssl: [-DMG_TLS=MG_TLS_NONE, -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
name: tutorials ${{ matrix.ssl }}
|
name: tutorials ${{ matrix.ssl }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: webfactory/ssh-agent@v0.9.1
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.HEALTH_TESTS_SSH_KEY }}
|
||||||
- run: sudo apt -y install libpcap-dev
|
- run: sudo apt -y install libpcap-dev
|
||||||
- run: make -C test tutorials CFLAGS_EXTRA="${{ matrix.ssl }}"
|
- run: make -C test tutorials CFLAGS_EXTRA="${{ matrix.ssl }}" > log
|
||||||
|
- if: success() || failure()
|
||||||
|
run: |
|
||||||
|
cat log
|
||||||
|
test/health.awk < log > json
|
||||||
|
scp -o "StrictHostKeyChecking=no" json "root@176.9.217.245:/data/downloads/health/tutorials_${{ matrix.ssl }}_$(date +"%Y%m%d").json"
|
||||||
- run: make -C test clean_tutorials
|
- run: make -C test clean_tutorials
|
||||||
|
|
||||||
tutorials_win:
|
tutorials_win:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
ssl: [-DMG_TLS=MG_TLS_NONE, -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
name: tutorials_win ${{ matrix.ssl }}
|
name: tutorials_win ${{ matrix.ssl }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -286,7 +275,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
ssl: [-DMG_TLS=MG_TLS_NONE, -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
name: tutorials_mac ${{ matrix.ssl }}
|
name: tutorials_mac ${{ matrix.ssl }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -300,11 +289,8 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: echo # nothing specific to install or do
|
- run: echo # nothing specific to install or do
|
||||||
- run: make -C examples/arduino arduino-xiao
|
- run: make -C test/arduino
|
||||||
# TODO(): - run: make -C examples/arduino arduino-esp32
|
- run: make -C test/arduino cleanall
|
||||||
# TODO(): - run: make -C examples/arduino arduino-teensy41
|
|
||||||
# - run: make -C examples/arduino arduino-nano
|
|
||||||
- run: make -C examples/arduino clean
|
|
||||||
|
|
||||||
|
|
||||||
# wizard_examples:
|
# wizard_examples:
|
||||||
@@ -322,7 +308,7 @@ jobs:
|
|||||||
# with: { fetch-depth: 2 }
|
# with: { fetch-depth: 2 }
|
||||||
# - run: echo # nothing specific to install or do
|
# - run: echo # nothing specific to install or do
|
||||||
# fi
|
# fi
|
||||||
# - run: make -C examples/${{ matrix.example.path }} build
|
# - run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
wizard_examples_arm:
|
wizard_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -330,7 +316,9 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: infineon/infineon-xmc7200
|
- path: infineon/xmc47_relax-make-baremetal-builtin
|
||||||
|
- path: infineon/xmc_plt2go_4400-make-baremetal-builtin
|
||||||
|
- path: infineon/xmc72_evk-make-baremetal-builtin
|
||||||
- path: nxp/frdm-mcxn947-make-baremetal-builtin
|
- path: nxp/frdm-mcxn947-make-baremetal-builtin
|
||||||
- path: nxp/frdm-mcxn947-make-freertos-builtin
|
- path: nxp/frdm-mcxn947-make-freertos-builtin
|
||||||
- path: nxp/rt1020-evk-make-baremetal-builtin
|
- path: nxp/rt1020-evk-make-baremetal-builtin
|
||||||
@@ -361,7 +349,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
- run: make -C examples/${{ matrix.example.path }} build
|
- run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
|
||||||
generic_examples:
|
generic_examples:
|
||||||
@@ -370,9 +358,9 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: esp32/uart-bridge
|
- path: micropython/esp32
|
||||||
- path: esp32/micropython
|
- path: http/uart-bridge/esp32
|
||||||
- path: esp8266/http-client-server
|
- path: http/http-client/esp8266/http-client-server
|
||||||
name: ${{ matrix.example.path }}
|
name: ${{ matrix.example.path }}
|
||||||
env:
|
env:
|
||||||
GO: 0
|
GO: 0
|
||||||
@@ -380,7 +368,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: echo # nothing specific to install or do
|
- run: echo # nothing specific to install or do
|
||||||
- run: make -C examples/${{ matrix.example.path }} build
|
- run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
generic_examples_arm:
|
generic_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -388,9 +376,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: microchip/same54-xpro/mqtt-client
|
- path: mqtt/mqtt-client/microchip/same54-xpro
|
||||||
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
|
||||||
- path: nxp/nxp-mimxrt1020-azurertos
|
|
||||||
- path: nxp/nxp-frdmk66f-freertos
|
- path: nxp/nxp-frdmk66f-freertos
|
||||||
- path: nxp/nxp-lpcxpresso54s018m-freertos
|
- path: nxp/nxp-lpcxpresso54s018m-freertos
|
||||||
- path: nxp/nxp-mimxrt1020-freertos
|
- path: nxp/nxp-mimxrt1020-freertos
|
||||||
@@ -420,7 +406,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
- run: make -C examples/${{ matrix.example.path }} build
|
- run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
device_dashboard_examples:
|
device_dashboard_examples:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -428,13 +414,14 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: esp32/device-dashboard
|
- path: esp32
|
||||||
name: ${{ matrix.example.path }}
|
name: ${{ matrix.example.path }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: echo # nothing specific to install or do
|
- run: echo # nothing specific to install or do
|
||||||
- run: make -C examples/${{ matrix.example.path }} build
|
- run: make -C tutorials/http/device-dashboard/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
|
||||||
device_dashboard_examples_arm:
|
device_dashboard_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -443,7 +430,7 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
ssl: ["", -DMG_TLS=MG_TLS_BUILTIN]
|
||||||
example:
|
example:
|
||||||
- path: microchip/same54-xpro/device-dashboard
|
- path: http/device-dashboard/microchip/same54-xpro
|
||||||
- path: nxp/rt1020-evk-make-freertos-builtin
|
- path: nxp/rt1020-evk-make-freertos-builtin
|
||||||
- path: nxp/rt1060-evk-make-freertos-builtin
|
- path: nxp/rt1060-evk-make-freertos-builtin
|
||||||
- path: nxp/rt1170-evk-make-freertos-builtin
|
- path: nxp/rt1170-evk-make-freertos-builtin
|
||||||
@@ -458,7 +445,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
- 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 }}"
|
- run: make -C tutorials/${{ matrix.example.path }} build CFLAGS_EXTRA="${{ matrix.ssl }}"
|
||||||
|
|
||||||
# mqtt_dashboard_examples:
|
# mqtt_dashboard_examples:
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
@@ -472,7 +459,7 @@ jobs:
|
|||||||
# - uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
# with: { fetch-depth: 2 }
|
# with: { fetch-depth: 2 }
|
||||||
# - run: echo # nothing specific to install or do
|
# - run: echo # nothing specific to install or do
|
||||||
# - run: make -C examples/${{ matrix.example.path }} build
|
# - run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
mqtt_dashboard_examples_arm:
|
mqtt_dashboard_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -486,7 +473,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
- run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
- run: make -C examples/${{ matrix.example.path }} build
|
- run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
# dual_examples:
|
# dual_examples:
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
@@ -500,8 +487,8 @@ jobs:
|
|||||||
# - uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
# with: { fetch-depth: 2 }
|
# with: { fetch-depth: 2 }
|
||||||
# - run: echo # nothing specific to install or do
|
# - run: echo # nothing specific to install or do
|
||||||
# - run: make -C examples/${{ matrix.example.path }} device_dashboard
|
# - run: make -C tutorials/${{ matrix.example.path }} device_dashboard
|
||||||
# - run: make -C examples/${{ matrix.example.path }} mqtt_dashboard
|
# - run: make -C tutorials/${{ matrix.example.path }} mqtt_dashboard
|
||||||
|
|
||||||
cube_examples:
|
cube_examples:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -511,24 +498,6 @@ jobs:
|
|||||||
- run: sudo pip install yq
|
- run: sudo pip install yq
|
||||||
- run: cd test/cube && make
|
- 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 REPO=zephyrprojectrtos/ci:v0.26.14 # "no space left on device" with newers
|
|
||||||
- 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:
|
test_f7:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -536,14 +505,14 @@ jobs:
|
|||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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 tutorials/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}}
|
- run: make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
- name: Cube
|
- name: Cube
|
||||||
run: echo # nothing specific to install or do
|
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 PROJECTS=../../tutorials/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 PROJECTS=../../tutorials/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
|
- run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
|
||||||
test_f4:
|
test_f4:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -552,13 +521,13 @@ jobs:
|
|||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
- name: Cube
|
- name: Cube
|
||||||
run: echo # nothing specific to install or do
|
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 PROJECTS=../../tutorials/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 PROJECTS=../../tutorials/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
|
- run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
|
|
||||||
test_h743:
|
test_h743:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -567,12 +536,12 @@ jobs:
|
|||||||
with: { fetch-depth: 3 }
|
with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
# - name: Cube
|
# - name: Cube
|
||||||
# run: echo # nothing specific to install or do
|
# 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 PROJECTS=../../tutorials/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
|
# - run: make -C test/cube PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
|
|
||||||
test_h723:
|
test_h723:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -581,8 +550,8 @@ jobs:
|
|||||||
with: { fetch-depth: 3 }
|
with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/stm32/nucleo-h723zg-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_h5:
|
test_h5:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -591,8 +560,8 @@ jobs:
|
|||||||
with: { fetch-depth: 3 }
|
with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/stm32/nucleo-h563zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_rt1020:
|
test_rt1020:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -601,8 +570,8 @@ jobs:
|
|||||||
with: { fetch-depth: 3 }
|
with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/nxp/rt1020-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_rt1060:
|
test_rt1060:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -611,8 +580,8 @@ jobs:
|
|||||||
with: { fetch-depth: 3 }
|
with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/nxp/rt1060-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_rt1170:
|
test_rt1170:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -621,8 +590,8 @@ jobs:
|
|||||||
with: { fetch-depth: 3 }
|
with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/nxp/rt1170-evk-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_ra6m4:
|
test_ra6m4:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -631,8 +600,8 @@ jobs:
|
|||||||
with: { fetch-depth: 3 }
|
with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
# - run: make -C tutorials/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_tm4c:
|
test_tm4c:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -641,8 +610,8 @@ jobs:
|
|||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/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}}
|
- run: make -C tutorials/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_same54:
|
test_same54:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -651,8 +620,8 @@ jobs:
|
|||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- name: baremetal
|
- name: baremetal
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
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 tutorials/http/device-dashboard/microchip/same54-xpro 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}}
|
- run: make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
test_pico_w5500:
|
test_pico_w5500:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -661,5 +630,5 @@ jobs:
|
|||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- name: SDK
|
- name: SDK
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
- run: make -C examples/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
- run: make -C tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
+373
-414
@@ -5,6 +5,8 @@ on:
|
|||||||
- "**Makefile"
|
- "**Makefile"
|
||||||
- "**.c"
|
- "**.c"
|
||||||
- "**.h"
|
- "**.h"
|
||||||
|
# Allow manual runs
|
||||||
|
workflow_dispatch:
|
||||||
env:
|
env:
|
||||||
IPV6: 0
|
IPV6: 0
|
||||||
jobs:
|
jobs:
|
||||||
@@ -20,28 +22,33 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CC: ${{ matrix.cc }}
|
CC: ${{ matrix.cc }}
|
||||||
SSL: ${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C test ${{ matrix.target }}
|
run: if [ "${{ matrix.target }}" == "test" ]; then ./test/setup_mqtt_server.sh ; fi && make -C test ${{ matrix.target }}
|
||||||
s390:
|
s390:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390
|
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test s390
|
||||||
armhf:
|
armhf:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf
|
run: sudo apt -y update ; sudo apt -y install binfmt-support qemu-user-static && ./test/setup_mqtt_server.sh && docker run --rm --privileged multiarch/qemu-user-static --reset -p yes && make -C test armhf
|
||||||
unamalgamated-mg_prefix:
|
unamalgamated-mg_prefix:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -59,14 +66,17 @@ jobs:
|
|||||||
name: macos SSL=${{ matrix.ssl }}
|
name: macos SSL=${{ matrix.ssl }}
|
||||||
env:
|
env:
|
||||||
SSL: ${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
#TFLAGS: -DNO_SNTP_CHECK
|
TFLAGS: -DMQTT_LOCALHOST # -DNO_SNTP_CHECK
|
||||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C test test ASAN_OPTIONS=
|
run: |
|
||||||
|
brew install mosquitto
|
||||||
|
/opt/homebrew/opt/mosquitto/sbin/mosquitto -c /Users/runner/work/mongoose/mongoose/test/mosquitto.conf.macos &
|
||||||
|
make -C test test ASAN_OPTIONS=
|
||||||
windows:
|
windows:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -74,12 +84,14 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
target: [vc98, vc22, mingw++]
|
target: [vc98, vc22, mingw++]
|
||||||
name: windows ${{ matrix.target }}
|
name: windows ${{ matrix.target }}
|
||||||
|
env:
|
||||||
|
TFLAGS: -DMQTT_LOCALHOST
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
- run: if ./test/match_changed_files.sh '^test|^src/.*.[ch]' ; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C test ${{ matrix.target }}
|
run: ./test/setup_mqtt_server.sh && make -C test ${{ matrix.target }}
|
||||||
arm:
|
arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -91,60 +103,6 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: make -C test riscv
|
- 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:
|
tutorials:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
@@ -192,7 +150,7 @@ jobs:
|
|||||||
# # nothing specific to install or do
|
# # nothing specific to install or do
|
||||||
# fi
|
# fi
|
||||||
# - if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
# run: make -C examples/${{ matrix.example.path }} build
|
# run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
wizard_examples_arm:
|
wizard_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -200,7 +158,9 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: infineon/infineon-xmc7200
|
- path: infineon/xmc47_relax-make-baremetal-builtin
|
||||||
|
- path: infineon/xmc_plt2go_4400-make-baremetal-builtin
|
||||||
|
- path: infineon/xmc72_evk-make-baremetal-builtin
|
||||||
- path: nxp/frdm-mcxn947-make-baremetal-builtin
|
- path: nxp/frdm-mcxn947-make-baremetal-builtin
|
||||||
- path: nxp/frdm-mcxn947-make-freertos-builtin
|
- path: nxp/frdm-mcxn947-make-freertos-builtin
|
||||||
- path: nxp/rt1020-evk-make-baremetal-builtin
|
- path: nxp/rt1020-evk-make-baremetal-builtin
|
||||||
@@ -236,7 +196,7 @@ jobs:
|
|||||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
fi
|
fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
|
|
||||||
generic_examples:
|
generic_examples:
|
||||||
@@ -245,20 +205,20 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: esp32/uart-bridge
|
- path: http/uart-bridge/esp32
|
||||||
- path: esp8266/http-client-server
|
- path: http/http-client/esp8266/http-client-server
|
||||||
name: ${{ matrix.example.path }}
|
name: ${{ matrix.example.path }}
|
||||||
env:
|
env:
|
||||||
GO: 0
|
GO: 0
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
- run: if ./test/match_changed_files.sh '^src|^tutorials/http/uart-bridge|^tutorials/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: |
|
run: |
|
||||||
# nothing specific to install or do
|
# nothing specific to install or do
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
generic_examples_arm:
|
generic_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -266,7 +226,6 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
|
||||||
- path: stm32/nucleo-g031-make-baremetal-builtin
|
- path: stm32/nucleo-g031-make-baremetal-builtin
|
||||||
name: ${{ matrix.example.path }}
|
name: ${{ matrix.example.path }}
|
||||||
env:
|
env:
|
||||||
@@ -274,11 +233,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: if ./test/match_changed_files.sh '^src|^examples/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
- run: if ./test/match_changed_files.sh '^src|^tutorials/${{ matrix.example.path }}'; then echo GO=1 >> $GITHUB_ENV ; fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
run: sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
device_dashboard_examples:
|
device_dashboard_examples:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -286,7 +245,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: esp32/device-dashboard
|
- path: esp32
|
||||||
name: ${{ matrix.example.path }}
|
name: ${{ matrix.example.path }}
|
||||||
env:
|
env:
|
||||||
GO: 0
|
GO: 0
|
||||||
@@ -294,12 +253,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: |
|
- run: |
|
||||||
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard'; then
|
||||||
echo GO=1 >> $GITHUB_ENV
|
echo GO=1 >> $GITHUB_ENV
|
||||||
# nothing specific to install or do
|
# nothing specific to install or do
|
||||||
fi
|
fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
run: make -C tutorials/http/device-dashboard/${{ matrix.example.path }} build
|
||||||
|
|
||||||
device_dashboard_examples_arm:
|
device_dashboard_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -307,7 +266,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- path: microchip/same54-xpro/device-dashboard
|
- path: http/device-dashboard/microchip/same54-xpro
|
||||||
- path: nxp/rt1020-evk-make-freertos-builtin
|
- path: nxp/rt1020-evk-make-freertos-builtin
|
||||||
- path: nxp/rt1060-evk-make-freertos-builtin
|
- path: nxp/rt1060-evk-make-freertos-builtin
|
||||||
- path: nxp/rt1170-evk-make-freertos-builtin
|
- path: nxp/rt1170-evk-make-freertos-builtin
|
||||||
@@ -324,12 +283,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: |
|
- run: |
|
||||||
if ./test/match_changed_files.sh '^src|examples/device-dashboard|^examples/${{ matrix.example.path }}'; then
|
if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|^tutorials/${{ matrix.example.path }}'; then
|
||||||
echo GO=1 >> $GITHUB_ENV
|
echo GO=1 >> $GITHUB_ENV
|
||||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
fi
|
fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
# mqtt_dashboard_examples:
|
# mqtt_dashboard_examples:
|
||||||
# runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
@@ -345,12 +304,12 @@ jobs:
|
|||||||
# - uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
# with: { fetch-depth: 2 }
|
# with: { fetch-depth: 2 }
|
||||||
# - run: |
|
# - run: |
|
||||||
# if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
# if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-dashboard/device|^tutorials/${{ matrix.example.path }}'; then
|
||||||
# echo GO=1 >> $GITHUB_ENV
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
# # nothing specific to install or do
|
# # nothing specific to install or do
|
||||||
# fi
|
# fi
|
||||||
# - if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
# run: make -C examples/${{ matrix.example.path }} build
|
# run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
mqtt_dashboard_examples_arm:
|
mqtt_dashboard_examples_arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -366,12 +325,12 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: |
|
- run: |
|
||||||
if ./test/match_changed_files.sh '^src|examples/mqtt-dashboard/device|^examples/${{ matrix.example.path }}'; then
|
if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-dashboard/device|^tutorials/${{ matrix.example.path }}'; then
|
||||||
echo GO=1 >> $GITHUB_ENV
|
echo GO=1 >> $GITHUB_ENV
|
||||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
fi
|
fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
run: make -C tutorials/${{ matrix.example.path }} build
|
||||||
|
|
||||||
cube_examples:
|
cube_examples:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -381,367 +340,367 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
with: { fetch-depth: 2 }
|
||||||
- run: |
|
- run: |
|
||||||
if ./test/match_changed_files.sh '^src|examples/stm32/nucleo-*-cube-*'; then
|
if ./test/match_changed_files.sh '^src|tutorials/stm32/nucleo-*-cube-*'; then
|
||||||
echo GO=1 >> $GITHUB_ENV
|
echo GO=1 >> $GITHUB_ENV
|
||||||
sudo pip install yq
|
sudo pip install yq
|
||||||
fi
|
fi
|
||||||
- if: ${{ env.GO == 1 }}
|
- if: ${{ env.GO == 1 }}
|
||||||
run: cd test/cube && make
|
run: cd test/cube && make
|
||||||
|
|
||||||
test_f7:
|
# test_f7:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
env:
|
# env:
|
||||||
GO: 0
|
# GO: 0
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
# with: { fetch-depth: 2 }
|
||||||
- name: baremetal
|
# - 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: |
|
# run: |
|
||||||
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
|
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f7.*-make-" ; then
|
||||||
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f746zg-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
# 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|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f746zg-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/stm32/nucleo-f746zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
# fi
|
# fi
|
||||||
# - if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
# run: |
|
# run: |
|
||||||
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-f746zg-cube-freertos-builtin'; then
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-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
|
# make -C tutorials/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-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
|
# fi
|
||||||
# - if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
# run: |
|
# run: |
|
||||||
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-f429zi-cube-freertos-builtin'; then
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-make-freertos-tcp'; then
|
||||||
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
# make -C tutorials/stm32/nucleo-f746zg-make-freertos-tcp test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
# fi
|
# 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
|
# - name: Cube
|
||||||
# run: |
|
# run: |
|
||||||
# echo GO=0 >> $GITHUB_ENV
|
# echo GO=0 >> $GITHUB_ENV
|
||||||
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-h74.*-cube-'; then
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f7.*-cube-'; then
|
||||||
# echo GO=1 >> $GITHUB_ENV
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
# # nothing specific to install or do
|
# # nothing specific to install or do
|
||||||
# fi
|
# fi
|
||||||
|
## - if: ${{ env.GO == 1 }}
|
||||||
|
## run: |
|
||||||
|
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-baremetal-builtin'; then
|
||||||
|
## make -C test/cube test PROJECTS=../../tutorials/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 'tutorials/stm32/nucleo-f746zg-cube-freertos-builtin'; then
|
||||||
|
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f746zg-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=5
|
||||||
|
## fi
|
||||||
# - if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
# run: |
|
# run: |
|
||||||
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f746zg-cube-freertos-lwip'; then
|
||||||
# make -C test/cube test PROJECTS=../../examples/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
# make -C test/cube test PROJECTS=../../tutorials/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|tutorials/http/device-dashboard|tutorials/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|tutorials/http/device-dashboard|tutorials/stm32/nucleo-f429zi-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/stm32/nucleo-f429zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
# fi
|
# fi
|
||||||
# - if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
# run: |
|
# run: |
|
||||||
# if ./test/match_changed_files.sh 'examples/stm32/nucleo-h743zi-cube-freertos-builtin'; then
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-make-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
|
# make -C tutorials/stm32/nucleo-f429zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
# fi
|
# fi
|
||||||
|
# - name: Cube
|
||||||
test_h723:
|
# run: |
|
||||||
runs-on: ubuntu-latest
|
# echo GO=0 >> $GITHUB_ENV
|
||||||
env:
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f4.*-cube-'; then
|
||||||
GO: 0
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
steps:
|
# # nothing specific to install or do
|
||||||
- uses: actions/checkout@v4
|
# fi
|
||||||
with: { fetch-depth: 3 }
|
## - if: ${{ env.GO == 1 }}
|
||||||
- name: baremetal
|
## run: |
|
||||||
run: |
|
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin'; then
|
||||||
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/stm32/nucleo-h72.*-make-" ; then
|
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
echo GO=1 >> $GITHUB_ENV
|
## fi
|
||||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
## - if: ${{ env.GO == 1 }}
|
||||||
fi
|
## run: |
|
||||||
- if: ${{ env.GO == 1 }}
|
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-builtin'; then
|
||||||
continue-on-error: true
|
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
run: |
|
## fi
|
||||||
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 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
# run: |
|
# run: |
|
||||||
# if ./test/match_changed_files.sh 'examples/renesas/ek-ra6m4-make-freertos-builtin'; then
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-f429zi-cube-freertos-lwip'; then
|
||||||
# make -C examples/renesas/ek-ra6m4-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
# make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-f429zi-cube-freertos-lwip VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=2
|
||||||
# fi
|
# fi
|
||||||
|
#
|
||||||
test_tm4c:
|
# test_h743:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
env:
|
# env:
|
||||||
GO: 0
|
# GO: 0
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
with: { fetch-depth: 2 }
|
# with: { fetch-depth: 3 }
|
||||||
- name: baremetal
|
# - name: baremetal
|
||||||
run: |
|
# run: |
|
||||||
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/ti/ek-tm4c.*-make-" ; then
|
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h74.*-make-" ; then
|
||||||
echo GO=1 >> $GITHUB_ENV
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
fi
|
# fi
|
||||||
- if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
run: |
|
# continue-on-error: true
|
||||||
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
|
# run: |
|
||||||
make -C examples/ti/ek-tm4c1294xl-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h743zi-make-baremetal-builtin'; then
|
||||||
fi
|
# make -C tutorials/stm32/nucleo-h743zi-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
- if: ${{ env.GO == 1 }}
|
# fi
|
||||||
run: |
|
# - if: ${{ env.GO == 1 }}
|
||||||
if ./test/match_changed_files.sh 'examples/ti/ek-tm4c1294xl-make-freertos-builtin'; then
|
# run: |
|
||||||
make -C examples/ti/ek-tm4c1294xl-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-make-freertos-builtin'; then
|
||||||
fi
|
# make -C tutorials/stm32/nucleo-h743zi-make-freertos-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
# fi
|
||||||
test_same54:
|
## - name: Cube
|
||||||
runs-on: ubuntu-latest
|
## run: |
|
||||||
env:
|
## echo GO=0 >> $GITHUB_ENV
|
||||||
GO: 0
|
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h74.*-cube-'; then
|
||||||
steps:
|
## echo GO=1 >> $GITHUB_ENV
|
||||||
- uses: actions/checkout@v4
|
## # nothing specific to install or do
|
||||||
with: { fetch-depth: 2 }
|
## fi
|
||||||
- name: baremetal
|
## - if: ${{ env.GO == 1 }}
|
||||||
run: |
|
## run: |
|
||||||
if ./test/match_changed_files.sh "^src|examples/device-dashboard|examples/microchip/same54-xpro" ; then
|
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin'; then
|
||||||
echo GO=1 >> $GITHUB_ENV
|
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-baremetal-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
## fi
|
||||||
fi
|
## - if: ${{ env.GO == 1 }}
|
||||||
- if: ${{ env.GO == 1 }}
|
## run: |
|
||||||
run: |
|
## if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h743zi-cube-freertos-builtin'; then
|
||||||
if ./test/match_changed_files.sh '^src|examples/device-dashboard|examples/microchip/same54-xpro/device-dashboard'; then
|
## make -C test/cube test PROJECTS=../../tutorials/stm32/nucleo-h743zi-cube-freertos-builtin VCON_API_KEY=${{secrets.VCON_API_KEY}} DEVICE=6
|
||||||
make -C examples/microchip/same54-xpro/device-dashboard test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
## fi
|
||||||
fi
|
#
|
||||||
- if: ${{ env.GO == 1 }}
|
# test_h723:
|
||||||
run: |
|
# runs-on: ubuntu-latest
|
||||||
if ./test/match_changed_files.sh 'examples/microchip/same54-xpro/mqtt-client'; then
|
# env:
|
||||||
make -C examples/microchip/same54-xpro/mqtt-client test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
# GO: 0
|
||||||
fi
|
# steps:
|
||||||
|
# - uses: actions/checkout@v4
|
||||||
test_pico_w5500:
|
# with: { fetch-depth: 3 }
|
||||||
runs-on: ubuntu-latest
|
# - name: baremetal
|
||||||
env:
|
# run: |
|
||||||
GO: 0
|
# if ./test/match_changed_files.sh "^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h72.*-make-" ; then
|
||||||
steps:
|
# echo GO=1 >> $GITHUB_ENV
|
||||||
- uses: actions/checkout@v4
|
# sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
||||||
with: { fetch-depth: 2 }
|
# fi
|
||||||
- name: SDK
|
# - if: ${{ env.GO == 1 }}
|
||||||
run: |
|
# continue-on-error: true
|
||||||
if ./test/match_changed_files.sh "^src" ; then
|
# run: |
|
||||||
echo GO=1 >> $GITHUB_ENV
|
# if ./test/match_changed_files.sh '^src|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h723zg-make-baremetal-builtin'; then
|
||||||
sudo apt -y update && sudo apt -y install gcc-arm-none-eabi
|
# make -C tutorials/stm32/nucleo-h723zg-make-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
fi
|
# fi
|
||||||
- if: ${{ env.GO == 1 }}
|
# - if: ${{ env.GO == 1 }}
|
||||||
run: make -C examples/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh 'tutorials/stm32/nucleo-h723zg-make-freertos-builtin'; then
|
||||||
|
# make -C tutorials/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|tutorials/http/device-dashboard|tutorials/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|tutorials/http/device-dashboard|tutorials/stm32/nucleo-h563zi-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/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 'tutorials/stm32/nucleo-h563zi-make-freertos-builtin'; then
|
||||||
|
# make -C tutorials/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|tutorials/http/device-dashboard|tutorials/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|tutorials/http/device-dashboard|tutorials/nxp/rt1020-evk-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/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 'tutorials/nxp/rt1020-evk-make-freertos-builtin'; then
|
||||||
|
# make -C tutorials/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|tutorials/http/device-dashboard|tutorials/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|tutorials/http/device-dashboard|tutorials/nxp/rt1060-evk-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/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 'tutorials/nxp/rt1060-evk-make-freertos-builtin'; then
|
||||||
|
# make -C tutorials/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|tutorials/http/device-dashboard|tutorials/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|tutorials/http/device-dashboard|tutorials/nxp/rt1170-evk-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/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 'tutorials/nxp/rt1170-evk-make-freertos-builtin'; then
|
||||||
|
# make -C tutorials/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|tutorials/http/device-dashboard|tutorials/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|tutorials/http/device-dashboard|tutorials/renesas/ek-ra6m4-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/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 'tutorials/renesas/ek-ra6m4-make-freertos-builtin'; then
|
||||||
|
## make -C tutorials/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|tutorials/http/device-dashboard|tutorials/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|tutorials/http/device-dashboard|tutorials/ti/ek-tm4c1294xl-make-baremetal-builtin'; then
|
||||||
|
# make -C tutorials/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 'tutorials/ti/ek-tm4c1294xl-make-freertos-builtin'; then
|
||||||
|
# make -C tutorials/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|tutorials/http/device-dashboard|tutorials/mqtt/mqtt-client" ; 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|tutorials/http/device-dashboard'; then
|
||||||
|
# make -C tutorials/http/device-dashboard/microchip/same54-xpro test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
# fi
|
||||||
|
# - if: ${{ env.GO == 1 }}
|
||||||
|
# run: |
|
||||||
|
# if ./test/match_changed_files.sh '^src|tutorials/mqtt/mqtt-client'; then
|
||||||
|
# make -C tutorials/mqtt/mqtt-client/microchip/same54-xpro 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" ; 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 tutorials/pico-sdk/w5500-evb-pico-picosdk-baremetal-builtin test VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
name: Zephyr
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # run at 12 AM UTC
|
||||||
|
# Allow manual runs
|
||||||
|
workflow_dispatch:
|
||||||
|
jobs:
|
||||||
|
zephyr_examples:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
revno: ["--mr v3.7-branch", "--mr v4.2.0"] # LTS, latest stable
|
||||||
|
name: Zephyr ${{ matrix.revno }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with: { fetch-depth: 2 }
|
||||||
|
- run: test/setup_ga_docker_filesystem.sh
|
||||||
|
- run: make -C tutorials/zephyr init REPO=zephyrprojectrtos/ci REVNO="${{ matrix.revno }}"
|
||||||
|
- run: make -C tutorials/zephyr minify REVNO="${{ matrix.revno }}"
|
||||||
|
- run: make -C tutorials/zephyr update
|
||||||
|
- run: make -C tutorials/zephyr/device-dashboard build
|
||||||
|
- run: make -C tutorials/zephyr/http-client build
|
||||||
|
- run: make -C tutorials/zephyr/http-server build
|
||||||
|
- run: make -C tutorials/zephyr/mqtt-aws-client build
|
||||||
|
- run: make -C tutorials/zephyr/websocket-server build
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
# Mongoose - Embedded Web Server / Embedded Network 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://issues.oss-fuzz.com/issues?sort=-opened&can=1&q=proj:mongoose)
|
||||||
[](https://gurubase.io/g/mongoose)
|
|
||||||
|
|
||||||
Mongoose is a network library for C/C++. It provides event-driven non-blocking
|
Mongoose is a network library for C/C++. It provides event-driven non-blocking
|
||||||
APIs for TCP, UDP, HTTP, WebSocket, MQTT, and other protocols. It is designed
|
APIs for TCP, UDP, HTTP, WebSocket, MQTT, and other protocols. It is designed
|
||||||
@@ -35,6 +34,35 @@ robust, and easy. Features include:
|
|||||||
|
|
||||||
See https://mongoose.ws/ for complete documentation, videos, case studies, etc.
|
See https://mongoose.ws/ for complete documentation, videos, case studies, etc.
|
||||||
|
|
||||||
|
## Supported platforms
|
||||||
|
|
||||||
|
Mongoose can work on top of any TCP/IP stack that supports BSD sockets API.
|
||||||
|
Platforms supported by the 3rd party TCP/IP stacks:
|
||||||
|
|
||||||
|
| TCP/IP stack | Notes |
|
||||||
|
| :-------------- | :------- |
|
||||||
|
| **lwIP** | All devices running lwIP, for example ESP32, ESP32S3, ESP32C3, ESP32C6, etc |
|
||||||
|
| **Zephyr** | All devices supported by Zephyr |
|
||||||
|
| **Other** | Any other TCP/IP stack that supports BSD socket API, for example Amazon FreeRTOS-TCP |
|
||||||
|
| **Linux, Mac, Windows** | Workstations, server, single board computers, embedded Linux devices running on MPUs or FPGAs |
|
||||||
|
|
||||||
|
Optionally, Mongoose provides its own built-in TCP/IP stack, eliminating the
|
||||||
|
need for additional software to implement networking functionality. The
|
||||||
|
built-in stack supports operation in both bare-metal and RTOS environments.
|
||||||
|
Platforms supported by the Mongoose built-in TCP/IP stack:
|
||||||
|
|
||||||
|
| Hardware | Notes |
|
||||||
|
| :------------- | :------- |
|
||||||
|
| **STM32** | All STM32 MCUs with built-in Ethernet: STM32Fxx, STM32H5xx, STM32H7xx |
|
||||||
|
| **NXP** | All NXP MCUs with built-in Ethernet: IMXRT102x, IMXRT104x, IMXRT105x, IMXRT106x, IMXRT117x, RW612, MCXN94x |
|
||||||
|
| **Microchip** | ATSAME54 MCUs with built-int Ethernet |
|
||||||
|
| **Renesas** | RA5M, RA6M, RA8M MCUs with built-in Ethernet |
|
||||||
|
| **Infineon** | XMC4, XMC7 MCUs with built-in Ethernet |
|
||||||
|
| **Texas Instruments** | TM4C, TMS570 MCUs with built-in Ethernet |
|
||||||
|
| **Cypress WiFi** | Any MCU with CY43xx WiFi chips, like RP2040 Pico-W, RP2350 Pico2-W, Arduino Portenta |
|
||||||
|
| **Wiznet Ethernet** | Any MCU that use Wiznet W5500 or Wiznet 5100 MAC+PHY chips |
|
||||||
|
| **Cellular** | NRF9160, SIM800 |
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
|
|
||||||
Below are quick snippets that should give an idea how simple the API is and
|
Below are quick snippets that should give an idea how simple the API is and
|
||||||
@@ -171,6 +199,20 @@ 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).
|
||||||
|
|
||||||
|
|
||||||
|
## Articles
|
||||||
|
|
||||||
|
Technical guides and deep dives into embedded web servers, WebUI integration and embedded networking technologies:
|
||||||
|
- [Embedded Web Server: A Comprehensive Guide for Modern Connected Devices](https://mongoose.ws/articles/embedded-web-server-a-comprehensive-guide-for-modern-connected-devices/)
|
||||||
|
- [Building Embedded Web Device Dashboards](https://mongoose.ws/articles/building-embedded-web-device-dashboard/)
|
||||||
|
- [ESP32 Device Dashboard: A Step-by-Step Guide for Developers](https://mongoose.ws/articles/esp32-device-dashboard/)
|
||||||
|
- [How to build an STM32 Web Dashboard](https://mongoose.ws/articles/stm32-device-dashboard/)
|
||||||
|
- [STM32 WebSocket Guide](https://mongoose.ws/articles/stm32-websocket-guide/)
|
||||||
|
- [Web File Manager on STM32, ESP32 and Embedded Linux](https://mongoose.ws/articles/building-a-web-file-manager-on-stm32-esp32-embedded-linux/)
|
||||||
|
- [Web dashboard on Zephyr RTOS](https://mongoose.ws/articles/web-dashboard-on-zephyr-rtos/)
|
||||||
|
- [Limiting TCP/IP RAM usage on STM32](https://mongoose.ws/articles/limiting-tcpip-ram-usage-on-stm32/)
|
||||||
|
- [STM32 Ethernet explained](https://mongoose.ws/articles/stm32-ethernet-explained/)
|
||||||
|
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
Contributions are welcome! Please follow the guidelines below:
|
Contributions are welcome! Please follow the guidelines below:
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
# 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
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
|
|
||||||
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 sim800-mqtt && ../arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 sim800-mqtt.ino
|
|
||||||
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
|
|
||||||
|
|
||||||
arduino-esp32: arduino
|
|
||||||
# cd esp32-http && ../arduino/arduino --verbose --verify --board esp32-http.ino
|
|
||||||
# esp32-mqtt
|
|
||||||
|
|
||||||
arduino-teensy41: arduino
|
|
||||||
# cd teensy41-http && ../arduino/arduino --verbose --verify --board teensy41-http.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
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.h
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -1 +0,0 @@
|
|||||||
/*! 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 +0,0 @@
|
|||||||
../../../micropython/mongoose/micropython.cmake
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../micropython/mongoose/micropython.mk
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../micropython/mongoose/module.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../uart-bridge/net.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../uart-bridge/packed_fs.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.h
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
NAME ?= $(notdir $(CURDIR))
|
|
||||||
|
|
||||||
build:
|
|
||||||
git clone --depth 1 https://github.com/mongoose-examples/$(NAME)
|
|
||||||
cp ./../../../mongoose.[ch] $(NAME)
|
|
||||||
make -C $(NAME) build
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(NAME)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../device-dashboard/certs
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.h
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -1 +0,0 @@
|
|||||||
/*! tailwindcss v3.3.5 | 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-feature-settings:inherit;font-variation-settings: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}dialog{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}.z-10{z-index:10}.z-\[48\]{z-index:48}.z-\[60\]{z-index:60}.m-4{margin:1rem}.my-0{margin-top:0;margin-bottom:0}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mb-1{margin-bottom:.25rem}.ml-3{margin-left:.75rem}.ml-4{margin-left:1rem}.mr-2{margin-right:.5rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.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%}.max-h-64{max-height:16rem}.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-full{width:100%}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.grow-0{flex-grow:0}.basis-\[30px\]{flex-basis:30px}.-translate-x-full{--tw-translate-x:-100%}.-translate-x-full,.translate-x-0{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x:0px}.translate-x-5{--tw-translate-x:1.25rem}.translate-x-5,.translate-y-0{transform:tranLine truncated
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
all:
|
|
||||||
make -C ../../../tutorials/http/http-server ARGS="-d $(CURDIR)"
|
|
||||||
|
|
||||||
# Bundle JS libraries (preact, preact-router, ...) into a single file
|
|
||||||
bundle.js:
|
|
||||||
curl -s https://npm.reversehttp.com/preact,preact/hooks,htm/preact,preact-router -o $@
|
|
||||||
|
|
||||||
# Create optimised CSS. Prerequisite: npm -g i tailwindcss tailwindcss-font-inter
|
|
||||||
NPX ?= npx
|
|
||||||
main.css: index.html $(wildcard *.js)
|
|
||||||
$(NPX) tailwindcss -o $@ --minify
|
|
||||||
|
|
||||||
clean:
|
|
||||||
true
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/*! 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: }.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.right-4{right:1rem}.top-0{top:0}.top-4{top:1rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-auto{margin-top:auto;margin-bottom:auto}.mb-4{margin-bottom:1rem}.mt-3{margin-top:.75rem}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-full{height:100%}.min-h-screen{min-height:100vh}.w-11{width:2.75rem}.w-24{width:6rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-60{width:15rem}.w-64{width:16rem}.w-96{width:24rem}.w-full{width:100%}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.translate-x-0{--tw-translate-x:0px}.translate-x-0,.translate-x-5{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-5{--tw-translate-x:1.25rem}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse:0;border-top-widtLine truncated
|
|
||||||
@@ -1,618 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
import {h, html, render, useEffect, useRef, useState} from './bundle.js';
|
|
||||||
|
|
||||||
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>`;
|
|
||||||
const DefaultTopic = 'mg_mqtt_dashboard';
|
|
||||||
const DefaultUrl = location.protocol == 'https:'
|
|
||||||
? 'wss://broker.hivemq.com:8884/mqtt'
|
|
||||||
: 'ws://broker.hivemq.com:8000/mqtt';
|
|
||||||
const DefaultDeviceConfig = {pin_map: [], pin_state: [], log_level: 0, pin_count: 0};
|
|
||||||
const Delay = (ms, val) => new Promise(resolve => setTimeout(resolve, ms, val));
|
|
||||||
const handleFetchError = r => r.ok || alert(`Error: ${r.statusText}`);
|
|
||||||
const LabelClass = 'text-sm truncate text-gray-500 font-medium my-auto whitespace-nowrap';
|
|
||||||
const BadgeClass = 'flex-inline text-sm rounded-md rounded px-2 py-0.5 ring-1 ring-inset';
|
|
||||||
const InputClass = '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 rounded border';
|
|
||||||
const TitleClass = 'font-semibold xuppercase xtext-gray-600';
|
|
||||||
const Colors = {
|
|
||||||
green: 'bg-green-100 text-green-900 ring-green-300',
|
|
||||||
yellow: 'bg-yellow-100 text-yellow-900 ring-yellow-300',
|
|
||||||
info: 'bg-zinc-100 text-zinc-900 ring-zinc-300',
|
|
||||||
red: 'bg-red-100 text-red-900 ring-red-300',
|
|
||||||
};
|
|
||||||
|
|
||||||
let MqttClient;
|
|
||||||
|
|
||||||
const Icons = {
|
|
||||||
logo: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="59.1" height="75.7" viewBox="0 0 1514 1182"> <path style="fill: #2f409a;" d="m52.8 572h345.1v346.5h-345.1zm-10.9-434.2c-12.6 6.4-32.2 20.9-35.5 37.9 0 0-6.1 35.9-6.1 36.8-2.1 13.1 10.5 10 15.8 6.7 53.9-31.8 113.9-60.7 168.7-77.5 258.2-78.2 585.9-80.2 643.1 88.8 40.3 117.1-123.6 214.8-216.1 258.4-35.7 16.8-47.6 32.8-50 49.8-2 15.3 3.2 37.8 23.8 68.3 129.7 194.8 515 474 893.1 571.7 15.7 4.2 23.5 2.8 29.9-1.1 3.5-2 7.9-4.8 1.1-8.2-251.1-132.2-490.9-353.9-610.9-525.1-27.4-39.5-34.5-65.9-32.7-87.2 1.7-18.4 18.7-34.5 54.8-51.4 134.1-62.3 270.9-157.1 230-314.9-59.5-226.9-700.5-260.1-1109-53z"/></svg>`,
|
|
||||||
activity: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline></svg>`,
|
|
||||||
refresh: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg>`,
|
|
||||||
info: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>`,
|
|
||||||
login: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path><polyline points="10 17 15 12 10 7"></polyline><line x1="15" y1="12" x2="3" y2="12"></line></svg>`,
|
|
||||||
logout: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>`,
|
|
||||||
menu: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>`,
|
|
||||||
upload: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="17 8 12 3 7 8"></polyline><line x1="12" y1="3" x2="12" y2="15"></line></svg>`,
|
|
||||||
monitor: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect><line x1="8" y1="21" x2="16" y2="21"></line><line x1="12" y1="17" x2="12" y2="21"></line></svg>`,
|
|
||||||
settings: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>`,
|
|
||||||
download: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>`,
|
|
||||||
file: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline></svg>`,
|
|
||||||
check: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>`,
|
|
||||||
rollback: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="11 17 6 12 11 7"></polyline><polyline points="18 17 13 12 18 7"></polyline></svg>`,
|
|
||||||
save: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>`,
|
|
||||||
bolt: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>`,
|
|
||||||
delete: props => html`<svg class=${props.class} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`,
|
|
||||||
};
|
|
||||||
|
|
||||||
export function Button({title, onclick, disabled, extraClass, 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-0.5 text-sm font-semibold text-white shadow-sm ${colors} ${extraClass}"
|
|
||||||
ref=${ref} onclick=${cb} disabled=${disabled || spin} >
|
|
||||||
${title}
|
|
||||||
<${spin ? Icons.refresh : icon} class="w-4 ${spin ? 'animate-spin' : ''}" />
|
|
||||||
<//>`
|
|
||||||
};
|
|
||||||
|
|
||||||
function UploadFileButton({oncomplete, onprogress, onfileselect, url, title, colors, accept, extraClass}) {
|
|
||||||
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 => {
|
|
||||||
input.fn = null;
|
|
||||||
const res = oncomplete ? oncomplete(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 +
|
|
||||||
'&file=' + encodeURIComponent(fileName);
|
|
||||||
onprogress && onprogress(offset, fileData.length, fileName);
|
|
||||||
fetch(fullUrl, opts)
|
|
||||||
.then(function(res) {
|
|
||||||
if (!res.ok) {
|
|
||||||
finish(false);
|
|
||||||
} else if (offset >= fileData.length) {
|
|
||||||
finish(true);
|
|
||||||
} else {
|
|
||||||
sendChunk(offset + chunk.length);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
sendChunk(0);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const onchange = function(ev) {
|
|
||||||
if (!ev.target.files[0]) return;
|
|
||||||
let r = new FileReader(), f = ev.target.files[0];
|
|
||||||
if (onfileselect && !onfileselect(f.name)) {
|
|
||||||
ev.target.value = '';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
r.readAsArrayBuffer(f);
|
|
||||||
r.onload = function() {
|
|
||||||
input.fn = sendFileData(url, f.name, new Uint8Array(r.result), 2048);
|
|
||||||
ev.target.value = '';
|
|
||||||
ev.preventDefault();
|
|
||||||
btn.current && btn.current.base.click();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const onclick = function(ev) {
|
|
||||||
//if (!input.fn) input.current.click(); // No upload in progress, show file dialog
|
|
||||||
};
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="inline-flex flex-col ${extraClass}">
|
|
||||||
<input class="hidden" type="file" ref=${input} onchange=${onchange} accept=${accept} />
|
|
||||||
<${Button} title=${title} icon=${Icons.download} onclick=${onclick} ref=${btn} colors=${colors} />
|
|
||||||
<//>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Toggle({value, onclick, disabled}) {
|
|
||||||
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} disabled=${disabled}
|
|
||||||
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>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Header({topic, setTopic, url, setUrl, connected}) {
|
|
||||||
const forbiddenChars = ['$', '*', '+', '#', '/'];
|
|
||||||
const onClick = () => {
|
|
||||||
const isValidTopic = val => !forbiddenChars.some(char => val.includes(char));
|
|
||||||
if (isValidTopic(topic)) {
|
|
||||||
localStorage.setItem('topic', topic)
|
|
||||||
setTopic(topic);
|
|
||||||
window.location.reload();
|
|
||||||
} else {
|
|
||||||
setSaveResult('Error: The topic cannot contain these characters: ' + forbiddenChars);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="top-0 py-2 border-b-2 bg-stone-100">
|
|
||||||
<div class="flex px-4">
|
|
||||||
<div class="flex grow gap-4">
|
|
||||||
<h1 class="text-2xl font-semibold">IoT Fleet Management Dashboard</h1>
|
|
||||||
<//>
|
|
||||||
<div class="flex gap-2 items-center">
|
|
||||||
<div class="flex w-96 align-center justify-between gap-2">
|
|
||||||
<span class=${LabelClass}>MQTT Server<//>
|
|
||||||
<input disabled=${!connected} value=${url}
|
|
||||||
onchange=${ev => setUrl(ev.target.value)} class=${InputClass} />
|
|
||||||
<//>
|
|
||||||
<div class="flex w-64 align-center justify-between gap-2">
|
|
||||||
<span class=${LabelClass}>Root Topic<//>
|
|
||||||
<input disabled=${!connected} value=${topic}
|
|
||||||
onchange=${ev => setTopic(ev.target.value)} class=${InputClass} />
|
|
||||||
<//>
|
|
||||||
<${Button} icon=${Icons.bolt} onclick=${onClick} title=${connected ? 'Disconnect' : 'Connect'} />
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<//>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Sidebar({devices, onclick}) {
|
|
||||||
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 Device = ({d}) => html`
|
|
||||||
<div class="hover:bg-stone-100 cursor-pointer flex gap-3 px-4 py-2 justify-between"
|
|
||||||
onclick=${ev => onclick(d.id)}>
|
|
||||||
<span>${d.id}</span>
|
|
||||||
<span class="${BadgeClass} ${d.online ? Colors.green : Colors.red}"> ${d.online ? 'online' : 'offline'} <//>
|
|
||||||
<//>`;
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="overflow-auto divide-y">
|
|
||||||
<div class="${TitleClass} flex items-center px-4 py-2 bg-stone-100">
|
|
||||||
Device List
|
|
||||||
<//>
|
|
||||||
${(devices ? devices : []).map(d => h(Device, {d}))}
|
|
||||||
<//>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
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 divide-y border rounded">
|
|
||||||
<div class="${TitleClass} bg-white flex items-center 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 FirmwareUpdatePanel({no, name, current, previous, updated_at, refresh}) {
|
|
||||||
const [color, setColor] = useState(Colors.green);
|
|
||||||
const [otaStatus, setOtaStatus] = useState('up-to-date');
|
|
||||||
const Descr = ({label, value}) => html`
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class=${LabelClass}>${label}<//>
|
|
||||||
<span class="text-sm">${value}<//>
|
|
||||||
<//>`;
|
|
||||||
const onprogress = (len, total) => {
|
|
||||||
setColor(Colors.info);
|
|
||||||
setOtaStatus(`uploading, ${parseInt(len * 100 /total)}% done...`);
|
|
||||||
}
|
|
||||||
const setparam = (key, val) => fetch('api/settings/set', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({key, val}),
|
|
||||||
}).then(handleFetchError);
|
|
||||||
const onupload = function(ok, fileName, fileLength) {
|
|
||||||
if (ok) {
|
|
||||||
return setparam(`ecu.${no}.new`, fileName).then(refresh);
|
|
||||||
} else {
|
|
||||||
setColor(Colors.red), setOtaStatus('upload failed');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const onfileselect = function(fileName, fileLength) {
|
|
||||||
const ok = fileName.startsWith(name);
|
|
||||||
if (!ok) alert(`Firmware file name must be ${name}.VERSION.BIN_OR_HEX`);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
const update = rollback => new Promise(function(resolve, reject) {
|
|
||||||
const opts = {method: 'POST', body: JSON.stringify({no, rollback})};
|
|
||||||
const fail = () => (reject(), setOtaStatus('update error'), setColor(Colors.red));
|
|
||||||
const finish = () => fetch('api/ecu/update/end', opts)
|
|
||||||
.then(r => r.ok ? resolve() : reject())
|
|
||||||
.then(refresh);
|
|
||||||
const write = () => fetch('api/ecu/update/write', opts).then(r => {
|
|
||||||
if (!r.ok) fail();
|
|
||||||
//if (r.ok) r.json().then(r => console.log('Goo', r));
|
|
||||||
if (r.ok) r.json().then(r => r == 1 ? write() : finish());
|
|
||||||
});
|
|
||||||
fetch('api/ecu/update/begin', opts).then(r => r.ok ? write() : fail());
|
|
||||||
});
|
|
||||||
const onflash = ev => update(false);
|
|
||||||
const onrollback = ev => update(true);
|
|
||||||
|
|
||||||
useEffect(function() {
|
|
||||||
//setOtaStatus(anew ? 'update pending' : 'up-to-date');
|
|
||||||
//setColor(anew ? Colors.yellow : Colors.green);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="divide-y border rounded bg-white">
|
|
||||||
<div class="px-4 py-2 flex justify-between items-center rounded">
|
|
||||||
<span class="${TitleClass}">Firmware Update<//>
|
|
||||||
<div class="flex gap-2"><span class=${LabelClass}>Status:</span><span class="${BadgeClass} ${color}">${otaStatus}<//><//>
|
|
||||||
<//>
|
|
||||||
<div class="p-4 flex flex-col gap-1">
|
|
||||||
<${Descr} label="Current firmware:" value=${current || 'n/a'} />
|
|
||||||
<${Descr} label="Updated at:" value=${updated_at || 'n/a'} />
|
|
||||||
<div class="flex items-center justify-between whitespace-nowrap">
|
|
||||||
<span class=${LabelClass}>Previous firmware:<//>
|
|
||||||
<span class="flex gap-1 items-center">
|
|
||||||
<span class="text-sm">${previous}<//>
|
|
||||||
<${Button} title="rollback" icon=${Icons.bolt} onclick=${onrollback}
|
|
||||||
extraClass="w-24" disabled=${!previous} />
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<div class="flex items-center justify-between">
|
|
||||||
<span class=${LabelClass}>New firmware:<//>
|
|
||||||
<span class="flex gap-1 align-center justify-between">
|
|
||||||
<${UploadFileButton} title="upload" url="api/fw/upload"
|
|
||||||
onfileselect=${onfileselect}
|
|
||||||
onprogress=${onprogress} oncomplete=${onupload} />
|
|
||||||
<${Button} title="flash" icon=${Icons.bolt} onclick=${onflash}
|
|
||||||
extraClass="w-24" disabled=${!previous} />
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<//>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function DeviceSettingsPanel({device, publishFn, connected}) {
|
|
||||||
const [config, setConfig] = useState({});
|
|
||||||
const logOptions = [[0, 'Disable'], [1, 'Error'], [2, 'Info'], [3, 'Debug']];
|
|
||||||
|
|
||||||
const onSave = ev => publishFn('config.set', config).then(r => {
|
|
||||||
//setDeviceConfig(device.id, config);
|
|
||||||
}).catch(e => alert('Failure!'));
|
|
||||||
|
|
||||||
// To delete device, set an empty retained message
|
|
||||||
const onforget = function(ev) {
|
|
||||||
MqttClient.publish(device.topic, '', {retain: true});
|
|
||||||
location.reload();
|
|
||||||
};
|
|
||||||
const onloglevelchange = ev => setConfig(x => Object.assign({}, x, {log_level: parseInt(ev.target.value)}));
|
|
||||||
const onpinschange = ev => {
|
|
||||||
const pin_map = ev.target.value.split(/\s*,\s*/).map(x => parseInt(x));
|
|
||||||
setConfig(x => Object.assign({}, x, {
|
|
||||||
pin_map, // Send an updated pin map
|
|
||||||
pin_count: pin_map.length, // And pin count
|
|
||||||
pin_state:[] // Remove pin_state from the request, as pin_map change can invalidate it
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
//console.log('sp', device, config);
|
|
||||||
|
|
||||||
useEffect(() => setConfig(device.config) , [device]);
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="divide-y border rounded bg-white">
|
|
||||||
<div class="px-4 py-2 flex justify-between items-center rounded ${TitleClass}">
|
|
||||||
<div class="flex gap-2 items-center"> Settings <//>
|
|
||||||
<//>
|
|
||||||
<div class="p-4 gap-3">
|
|
||||||
<div class="flex justify-between my-1">
|
|
||||||
<span class=${LabelClass}>Status<//>
|
|
||||||
<span class="${BadgeClass} ${device.online ? Colors.green : Colors.red}"> ${connected ? 'online' : 'offline'} <//>
|
|
||||||
<//>
|
|
||||||
<div class="flex justify-between my-1">
|
|
||||||
<span class=${LabelClass}>Device ID<//>
|
|
||||||
<span class="${LabelClass}">${device.id}<//>
|
|
||||||
<//>
|
|
||||||
<div class="grid grid-cols-2 my-1">
|
|
||||||
<span class="${LabelClass}">Log Level<//>
|
|
||||||
<select onchange=${onloglevelchange} 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=${!connected}>
|
|
||||||
${logOptions.map(v => html`<option value=${v[0]} selected=${v[0] == config.log_level}>${v[1]}<//>`) }
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<div class="grid grid-cols-2 my-1">
|
|
||||||
<span class="${LabelClass}">Show Pins<//>
|
|
||||||
<div class="flex w-full items-center">
|
|
||||||
<input disabled=${!connected} value=${config.pin_map}
|
|
||||||
onchange=${onpinschange} class=${InputClass}
|
|
||||||
placeholder="comma-separated pin numbers" />
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
|
|
||||||
<div class="mt-3 flex justify-between gap-2">
|
|
||||||
<${Button} title="Forget this device"
|
|
||||||
disabled=${device.online || !connected} icon=${Icons.delete}
|
|
||||||
onclick=${onforget}/>
|
|
||||||
<${Button} icon=${Icons.save} onclick=${onSave} title="Save Settings" disabled=${!device.online} />
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<//> `;
|
|
||||||
};
|
|
||||||
|
|
||||||
function DeviceControlPanel({device, config, setConfig, publishFn, connected}) {
|
|
||||||
const onclick = function(i) { // Send request to toggle pin i
|
|
||||||
let configCopy = Object.assign({}, config);
|
|
||||||
configCopy.pin_state[i] = !!configCopy.pin_state[i] ? 0 : 1;
|
|
||||||
return publishFn('config.set', configCopy).catch(e => alert('Failure!'));
|
|
||||||
};
|
|
||||||
|
|
||||||
const Pin = i => html`
|
|
||||||
<div class="inline-block my-1 bg-gray-100 rounded px-1 py-1">
|
|
||||||
<div class="flex align-center justify-between">
|
|
||||||
<span class="${LabelClass}">Pin ${config.pin_map[i]}<//>
|
|
||||||
<${Toggle} onclick=${ev => onclick(i)}
|
|
||||||
disabled=${!device.online || !connected}
|
|
||||||
value=${config.pin_state[i]} />
|
|
||||||
<//>
|
|
||||||
<//>`;
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="divide-y border rounded bg-white xbg-slate-100 my-y">
|
|
||||||
<div class="px-4 py-2 flex justify-between items-center rounded ${TitleClass}">
|
|
||||||
<div class="flex gap-2 items-center">Pin Control Panel<//>
|
|
||||||
<//>
|
|
||||||
<div class="p-4 grid grid-cols-2 lg:grid-cols-3 gap-2">
|
|
||||||
${(config.pin_map || []).map((_, i) => Pin(i))}
|
|
||||||
<div><//>
|
|
||||||
<//>
|
|
||||||
<//> `;
|
|
||||||
};
|
|
||||||
|
|
||||||
function DeviceDashboard({device, setDeviceConfig, publishFn, connected}) {
|
|
||||||
const cfg = device && device.config ? device.config : DefaultDeviceConfig;
|
|
||||||
const [localConfig, setLocalConfig] = useState(cfg);
|
|
||||||
useEffect(() => setLocalConfig(cfg), [device]);
|
|
||||||
|
|
||||||
if (!device || !localConfig) {
|
|
||||||
return html`
|
|
||||||
<div class="flex grow text-gray-400 justify-center items-center text-xl">
|
|
||||||
No device selected. Click on a device on a sidebar
|
|
||||||
<//>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="p-3 grid grid-cols-3 gap-2">
|
|
||||||
<${DeviceSettingsPanel} device=${device} config=${localConfig} setConfig=${setLocalConfig} publishFn=${publishFn} connected=${connected} />
|
|
||||||
<${DeviceControlPanel} device=${device} config=${localConfig} setConfig=${setLocalConfig} publishFn=${publishFn} connected=${connected} />
|
|
||||||
<${FirmwareUpdatePanel} deviceID=${device.id} publishFn=${publishFn}
|
|
||||||
disabled=${!device.online}
|
|
||||||
info=${[localConfig.crnt_fw, localConfig.prev_fw]} />
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const App = function() {
|
|
||||||
const [devices, setDevices] = useState([]);
|
|
||||||
const [currentDevID, setCurrentDevID] = useState(localStorage.getItem('currentDevID') || '');
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [url, setUrl] = useState(localStorage.getItem('url') || DefaultUrl);
|
|
||||||
const [topic, setTopic] = useState(localStorage.getItem('topic') || DefaultTopic);
|
|
||||||
const [error, setError] = useState(null);
|
|
||||||
const [connected, setConnected] = useState(false);
|
|
||||||
const responseHandlers = useRef({});
|
|
||||||
|
|
||||||
function addResponseHandler(correlationId, handler) {
|
|
||||||
responseHandlers[correlationId] = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeResponseHandler(correlationId) {
|
|
||||||
delete responseHandlers[correlationId];
|
|
||||||
}
|
|
||||||
|
|
||||||
const onRefresh = ev => window.location.reload();
|
|
||||||
|
|
||||||
const initConn = () => {
|
|
||||||
MqttClient = mqtt.connect(url, {connectTimeout: 5000, reconnectPeriod: 0});
|
|
||||||
|
|
||||||
MqttClient.on('connect', () => {
|
|
||||||
//console.log('Connected to the broker');
|
|
||||||
setLoading(false);
|
|
||||||
setError(null); // Reset error state upon successful connection
|
|
||||||
setConnected(true);
|
|
||||||
|
|
||||||
const statusTopic = topic + '/+/status'
|
|
||||||
const txTopic = topic + '/+/tx'
|
|
||||||
|
|
||||||
const subscribe = (topic) => {
|
|
||||||
MqttClient.subscribe(topic, (err) => {
|
|
||||||
if (err) {
|
|
||||||
console.error('Error subscribing to topic:', err);
|
|
||||||
setError('Error subscribing to topic');
|
|
||||||
} else {
|
|
||||||
//console.log('Successfully subscribed to ', topic);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
subscribe(statusTopic);
|
|
||||||
subscribe(txTopic);
|
|
||||||
});
|
|
||||||
|
|
||||||
MqttClient.on('message', (topic, message) => {
|
|
||||||
// console.log(`Received message from ${topic}: ${message.toString()}`);
|
|
||||||
if (message.length == 0) return;
|
|
||||||
let response;
|
|
||||||
try {
|
|
||||||
response = JSON.parse(message.toString());
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (topic.endsWith('/status')) {
|
|
||||||
let device = {topic: topic, id: topic.split('/')[1], config: DefaultDeviceConfig};
|
|
||||||
const params = response.params;
|
|
||||||
if (!params) {
|
|
||||||
console.error('Invalid response');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
device.online = params.status === 'online';
|
|
||||||
//setConnected(device.online);
|
|
||||||
if (device.online) {
|
|
||||||
device.config = params;
|
|
||||||
if (!device.config.pins) device.config.pins = [];
|
|
||||||
}
|
|
||||||
setDevice(device)
|
|
||||||
} else if (topic.endsWith('/tx')) {
|
|
||||||
if (!response.id) {
|
|
||||||
console.error('Invalid response');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const handler = responseHandlers[response.id];
|
|
||||||
if (handler) {
|
|
||||||
handler(response);
|
|
||||||
removeResponseHandler(response.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
MqttClient.on('error', (err) => {
|
|
||||||
console.error('Connection error:', err);
|
|
||||||
setError('Connection cannot be established.');
|
|
||||||
});
|
|
||||||
|
|
||||||
MqttClient.on('close', () => {
|
|
||||||
if (!connected) {
|
|
||||||
console.error('Failed to connect to the broker.');
|
|
||||||
setError('Connection cannot be established.');
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => initConn(), []);
|
|
||||||
|
|
||||||
const handlePublish = (methodName, parameters, timeout = 5000) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const randomIdGenerator = function(length) {
|
|
||||||
return Math.random().toString(36).substring(2, length + 2);
|
|
||||||
};
|
|
||||||
const randomID = randomIdGenerator(40);
|
|
||||||
const timeoutID = setTimeout(() => {
|
|
||||||
removeResponseHandler(randomID);
|
|
||||||
reject(new Error('Request timed out'));
|
|
||||||
}, timeout);
|
|
||||||
|
|
||||||
addResponseHandler(randomID, (messageData) => {
|
|
||||||
clearTimeout(timeoutID);
|
|
||||||
resolve(messageData);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (currentDevID) {
|
|
||||||
const rxTopic = topic + `/${currentDevID}/rx`;
|
|
||||||
const rpcPayload = {method: methodName, id: randomID};
|
|
||||||
if (parameters) {
|
|
||||||
rpcPayload.params = parameters;
|
|
||||||
}
|
|
||||||
MqttClient.publish(rxTopic, JSON.stringify(rpcPayload));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDeviceByID = (deviceID) => devices.find(d => d.id === deviceID);
|
|
||||||
|
|
||||||
const setDevice = (devData) => {
|
|
||||||
setDevices(prevDevices => {
|
|
||||||
const devIndex =
|
|
||||||
prevDevices.findIndex(device => device.id === devData.id);
|
|
||||||
if (devIndex !== -1) {
|
|
||||||
if (!devData.online && !devData.config) {
|
|
||||||
const updatedDevices = [...prevDevices];
|
|
||||||
updatedDevices[devIndex].online = false;
|
|
||||||
return updatedDevices;
|
|
||||||
} else {
|
|
||||||
return prevDevices.map(device => device.id === devData.id ? devData : device);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return [...prevDevices, devData];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const setDeviceConfig = (deviceID, config) => {
|
|
||||||
setDevices(prevDevices => {
|
|
||||||
return prevDevices.map(device => {
|
|
||||||
if (device.id === deviceID) {
|
|
||||||
return {...device, config: config};
|
|
||||||
}
|
|
||||||
return device;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const onDeviceClick = (deviceID) => {
|
|
||||||
const device = getDeviceByID(deviceID);
|
|
||||||
if (device) {
|
|
||||||
setCurrentDevID(device.id);
|
|
||||||
localStorage.setItem('currentDevID', device.id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return html`
|
|
||||||
<div class="min-h-screen bg-slate-100 flex flex-col">
|
|
||||||
<${Header}/>
|
|
||||||
<div class="flex-grow flex items-center justify-center">
|
|
||||||
<div class="bg-slate-300 p-8 rounded-lg shadow-md w-full max-w-md">
|
|
||||||
<h1 class="text-2xl font-bold text-gray-700 mb-4 text-center">Connection Error</h1>
|
|
||||||
<p class="text-gray-600 text-center mb-4">
|
|
||||||
Unable to connect to the MQTT broker.
|
|
||||||
</p>
|
|
||||||
<div class="text-center relative">
|
|
||||||
<${Button} title="Retry" onclick=${onRefresh}
|
|
||||||
icon=${Icons.refresh} class="absolute top-4 right-4" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<div class="h-full flex flex-col">
|
|
||||||
<${Header}
|
|
||||||
topic=${topic} setTopic=${setTopic} url=${url}
|
|
||||||
setUrl=${setUrl} connected=${connected}
|
|
||||||
/>
|
|
||||||
<div class="flex grow overflow-auto">
|
|
||||||
<div class="w-60 overflow-auto">
|
|
||||||
<${Sidebar} devices=${devices} onclick=${onDeviceClick} />
|
|
||||||
<//>
|
|
||||||
<div class="grow bg-gray-200">
|
|
||||||
<${DeviceDashboard}
|
|
||||||
device=${getDeviceByID(currentDevID)} connected=${connected}
|
|
||||||
setDeviceConfig=${setDeviceConfig} publishFn=${handlePublish} />
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<//>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
window.onload = () => render(h(App), document.body);
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
NAME ?= $(notdir $(CURDIR))
|
|
||||||
|
|
||||||
build:
|
|
||||||
git clone --depth 1 https://github.com/mongoose-examples/$(NAME)
|
|
||||||
cp ./../../../mongoose.[ch] $(NAME)/source/
|
|
||||||
make -C $(NAME) build
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf $(NAME)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mqtt-dashboard/device/net.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mqtt-dashboard/device/net.h
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pico-sdk
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../device-dashboard/net.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../device-dashboard/net.h
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../device-dashboard/packed_fs.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.h
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../modbus-dashboard/net.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../modbus-dashboard/net.h
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../modbus-dashboard/packed_fs.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../mongoose.h
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
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',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../device-dashboard/web_root/bundle.js
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/*! 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}.z-10{z-index:10}.z-\[48\]{z-index:48}.z-\[60\]{z-index:60}.m-4{margin:1rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.mx-4{margin-left:1rem;margin-right: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-3{margin-top:.75rem;margin-bottom:.75rem}.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}.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-64{height:16rem}.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-\[85rem\]{max-width:85rem}.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}.border-separate{border-collapse:initial}.border-spacing-0{--tw-border-spacing-x:0px;--tw-border-spacing-y:0px;border-spacing:var(--tw-border-spacing-x) var(--tw-borLine truncated
|
|
||||||
+5191
-1362
File diff suppressed because it is too large.
Load diff
+997
-426
File diff suppressed because it is too large.
Load diff
@@ -1 +0,0 @@
|
|||||||
See detailed tutorials at https://mongoose.ws/documentation/#reference-projects
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
CFLAGS = -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion
|
|
||||||
CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion
|
|
||||||
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
|
|
||||||
CFLAGS += -I. -Icmsis_core/CMSIS/Core/Include -Icmsis_f7/Include
|
|
||||||
CFLAGS += -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 $(CFLAGS_EXTRA)
|
|
||||||
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs nosys.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
|
|
||||||
|
|
||||||
SOURCES += cmsis_f7/Source/Templates/gcc/startup_stm32f746xx.s
|
|
||||||
|
|
||||||
SOURCES += main.c hal.c mongoose.c packed_fs.c net.c
|
|
||||||
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\"
|
|
||||||
|
|
||||||
all build example: firmware.bin
|
|
||||||
|
|
||||||
firmware.bin: firmware.elf
|
|
||||||
arm-none-eabi-objcopy -O binary $< $@
|
|
||||||
arm-none-eabi-size --format=berkeley $<
|
|
||||||
|
|
||||||
firmware.elf: cmsis_core cmsis_f7 $(SOURCES) hal.h link.ld Makefile
|
|
||||||
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
|
|
||||||
|
|
||||||
flash: firmware.bin
|
|
||||||
st-flash --reset write $< 0x8000000
|
|
||||||
|
|
||||||
cmsis_core:
|
|
||||||
git clone --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
|
|
||||||
cmsis_f7:
|
|
||||||
git clone --depth 1 -b v1.2.8 https://github.com/STMicroelectronics/cmsis_device_f7 $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf firmware.* cmsis_core cmsis_f7
|
|
||||||
Whitespace-only changes.
@@ -1 +0,0 @@
|
|||||||
../../../windows-macos-linux/web-ui-dashboard/main.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../windows-macos-linux/web-ui-dashboard/net.c
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../windows-macos-linux/web-ui-dashboard/net.h
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../../windows-macos-linux/web-ui-dashboard/packed_fs.c
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
# Environment setup: https://mongoose.ws/documentation/tutorials/tools/
|
|
||||||
|
|
||||||
PROG ?= ./example # Program we are building
|
|
||||||
DELETE = rm -rf # Command to remove files
|
|
||||||
NPX ?= npx # For generating optimised tailwind CSS
|
|
||||||
OUT ?= -o $(PROG) # Compiler argument for output file
|
|
||||||
|
|
||||||
SOURCES = main.c mongoose.c net.c packed_fs.c
|
|
||||||
CFLAGS += -W -Wall -Wextra -Wundef -Wshadow -Wdouble-promotion -Wconversion -Wno-sign-conversion
|
|
||||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections
|
|
||||||
CFLAGS += -g3 -Os -I.
|
|
||||||
|
|
||||||
# Mongoose build options. See https://mongoose.ws/documentation/#build-options
|
|
||||||
CFLAGS_MONGOOSE += -DMG_ENABLE_PACKED_FS=1
|
|
||||||
|
|
||||||
ifeq ($(OS),Windows_NT) # Windows settings. Assume MinGW compiler. To use VC: make CC=cl CFLAGS=/MD OUT=/Feprog.exe
|
|
||||||
PROG = example.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
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Default target. Build and run program
|
|
||||||
all: $(PROG)
|
|
||||||
$(RUN) $(PROG) $(ARGS)
|
|
||||||
|
|
||||||
# Build program from sources
|
|
||||||
$(PROG): $(SOURCES)
|
|
||||||
$(CC) $(SOURCES) $(CFLAGS) $(CFLAGS_MONGOOSE) $(CFLAGS_EXTRA) $(OUT)
|
|
||||||
|
|
||||||
# Build using Microsoft Visual C compiler
|
|
||||||
vc: $(SOURCES) Makefile
|
|
||||||
cl $(SOURCES) /DMG_ENABLE_PACKED_FS=1 /MD /W3 /nologo /Fedemo.exe
|
|
||||||
|
|
||||||
# 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 $@
|
|
||||||
|
|
||||||
# Create optimised CSS. Prerequisite: npm -g i tailwindcss tailwindcss-font-inter
|
|
||||||
css: web_root/index.html $(wildcard web_root/*.js)
|
|
||||||
$(NPX) tailwindcss -o web_root/main.css --minify
|
|
||||||
|
|
||||||
# Generate packed filesystem for serving Web UI
|
|
||||||
packed_fs.c: $(wildcard web_root/*) $(wildcard certs/*) Makefile
|
|
||||||
node pack.js $(addsuffix ::gzip, $(wildcard web_root/*)) certs/* > $@
|
|
||||||
|
|
||||||
# Cleanup. Delete built program and all build artifacts
|
|
||||||
clean:
|
|
||||||
$(DELETE) $(PROG) *.o *.obj *.exe *.dSYM mbedtls
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# A complete device dashboard
|
|
||||||
|
|
||||||
This example is a demonstration of how Mongoose Library could be integrated
|
|
||||||
into an embedded device and provide a complete device dashboard with the
|
|
||||||
following features:
|
|
||||||
|
|
||||||
- Authentication: login-protected dashboard
|
|
||||||
- Multiple logins (with possibly different permissions)
|
|
||||||
- The Web UI can be fully embedded into the firmware binary, then not
|
|
||||||
needing a filesystem to serve it; so being resilient to FS problems
|
|
||||||
- All changes are propagated to all connected clients
|
|
||||||
|
|
||||||
See a detailed tutorial at https://mongoose.ws/tutorials/device-dashboard/
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIBCTCBsAIJAK9wbIDkHnAoMAoGCCqGSM49BAMCMA0xCzAJBgNVBAYTAklFMB4X
|
|
||||||
DTIzMDEyOTIxMjEzOFoXDTMzMDEyNjIxMjEzOFowDTELMAkGA1UEBhMCSUUwWTAT
|
|
||||||
BgcqhkjOPQIBBggqhkjOPQMBBwNCAARzSQS5OHd17lUeNI+6kp9WYu0cxuEIi/JT
|
|
||||||
jphbCmdJD1cUvhmzM9/phvJT9ka10Z9toZhgnBq0o0xfTQ4jC1vwMAoGCCqGSM49
|
|
||||||
BAMCA0gAMEUCIQCe0T2E0GOiVe9KwvIEPeX1J1J0T7TNacgR0Ya33HV9VgIgNvdn
|
|
||||||
aEWiBp1xshs4iz6WbpxrS1IHucrqkZuJLfNZGZI=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
-----BEGIN EC PRIVATE KEY-----
|
|
||||||
MHcCAQEEICBz3HOkQLPBDtdknqC7k1PNsWj6HfhyNB5MenfjmqiooAoGCCqGSM49
|
|
||||||
AwEHoUQDQgAEc0kEuTh3de5VHjSPupKfVmLtHMbhCIvyU46YWwpnSQ9XFL4ZszPf
|
|
||||||
6YbyU/ZGtdGfbaGYYJwatKNMX00OIwtb8A==
|
|
||||||
-----END EC PRIVATE KEY-----
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
// Copyright (c) 2024 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#define LED1 0
|
|
||||||
#define LED2 1
|
|
||||||
#define UART_DEBUG NULL
|
|
||||||
|
|
||||||
// No-op HAL API implementation for a device with GPIO and UART
|
|
||||||
#define hal_init()
|
|
||||||
#define hal_ram_free() 0
|
|
||||||
#define hal_ram_used() 0
|
|
||||||
#define gpio_output(pin)
|
|
||||||
#define gpio_toggle(pin)
|
|
||||||
#define gpio_read(pin) 0
|
|
||||||
#define gpio_write(pin, val)
|
|
||||||
#define uart_init(uart, baud)
|
|
||||||
#define uart_read_ready(uart) 0
|
|
||||||
#define uart_write_byte(uart, ch)
|
|
||||||
#define uart_write_buf(uart, buf, len)
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
// Copyright (c) 2024 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
|
|
||||||
#include "hal.h"
|
|
||||||
#include "mongoose.h"
|
|
||||||
#include "net.h"
|
|
||||||
|
|
||||||
#define BLINK_PERIOD_MS 1000 // LED blinking period in millis
|
|
||||||
|
|
||||||
static void timer_fn(void *arg) {
|
|
||||||
gpio_toggle(LED1); // Blink LED
|
|
||||||
(void) arg; // Unused
|
|
||||||
}
|
|
||||||
|
|
||||||
// In RTOS environment, you can run this function in a separate task
|
|
||||||
static void run_mongoose(void) {
|
|
||||||
struct mg_mgr mgr; // Mongoose event manager
|
|
||||||
mg_mgr_init(&mgr); // Initialise event manager
|
|
||||||
mg_log_set(MG_LL_DEBUG); // Set log level to debug
|
|
||||||
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, NULL);
|
|
||||||
|
|
||||||
net_init(&mgr); // Initialise application defined in net.c
|
|
||||||
for (;;) { // Infinite event loop
|
|
||||||
mg_mgr_poll(&mgr, 0); // Process network events
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
hal_init(); // Cross-platform hardware init
|
|
||||||
run_mongoose(); // Initialise and run network application
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -1,256 +0,0 @@
|
|||||||
// Copyright (c) 2023 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
|
|
||||||
#include "hal.h"
|
|
||||||
#include "net.h"
|
|
||||||
|
|
||||||
// Authenticated user.
|
|
||||||
// A user can be authenticated by:
|
|
||||||
// - a name:pass pair, passed in a header Authorization: Basic .....
|
|
||||||
// - 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,
|
|
||||||
// a server responds with a http-only access_token cookie set.
|
|
||||||
struct user {
|
|
||||||
const char *name, *pass, *access_token;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
struct settings {
|
|
||||||
bool log_enabled;
|
|
||||||
int log_level;
|
|
||||||
long brightness;
|
|
||||||
char *device_name;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct settings s_settings = {true, 1, 57, NULL};
|
|
||||||
|
|
||||||
static const char *s_json_header =
|
|
||||||
"Content-Type: application/json\r\n"
|
|
||||||
"Cache-Control: no-cache\r\n";
|
|
||||||
|
|
||||||
int ui_event_next(int no, struct ui_event *e) {
|
|
||||||
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
|
|
||||||
static struct user *authenticate(struct mg_http_message *hm) {
|
|
||||||
// In production, make passwords strong and tokens randomly generated
|
|
||||||
// In this example, user list is kept in RAM. In production, it can
|
|
||||||
// be backed by file, database, or some other method.
|
|
||||||
static struct user users[] = {
|
|
||||||
{"admin", "admin", "admin_token"},
|
|
||||||
{"user1", "user1", "user1_token"},
|
|
||||||
{"user2", "user2", "user2_token"},
|
|
||||||
{NULL, NULL, NULL},
|
|
||||||
};
|
|
||||||
char user[64], pass[64];
|
|
||||||
struct user *u, *result = NULL;
|
|
||||||
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') {
|
|
||||||
// Both user and password is set, search by user/password
|
|
||||||
for (u = users; result == NULL && u->name != NULL; u++)
|
|
||||||
if (strcmp(user, u->name) == 0 && strcmp(pass, u->pass) == 0) result = u;
|
|
||||||
} else if (user[0] == '\0') {
|
|
||||||
// Only password is set, search by token
|
|
||||||
for (u = users; result == NULL && u->name != NULL; u++)
|
|
||||||
if (strcmp(pass, u->access_token) == 0) result = u;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_login(struct mg_connection *c, struct user *u) {
|
|
||||||
char cookie[256];
|
|
||||||
const char *cookie_name = c->is_tls ? "secure_access_token" : "access_token";
|
|
||||||
mg_snprintf(cookie, sizeof(cookie),
|
|
||||||
"Set-Cookie: %s=%s; Path=/; "
|
|
||||||
"%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n",
|
|
||||||
cookie_name, u->access_token,
|
|
||||||
c->is_tls ? "Secure; " : "", 3600 * 24);
|
|
||||||
mg_http_reply(c, 200, cookie, "{%m:%m}", MG_ESC("user"), MG_ESC(u->name));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_logout(struct mg_connection *c) {
|
|
||||||
char cookie[256];
|
|
||||||
const char *cookie_name = c->is_tls ? "secure_access_token" : "access_token";
|
|
||||||
mg_snprintf(cookie, sizeof(cookie),
|
|
||||||
"Set-Cookie: %s=; Path=/; "
|
|
||||||
"Expires=Thu, 01 Jan 1970 00:00:00 UTC; "
|
|
||||||
"%sHttpOnly; Max-Age=0; \r\n", cookie_name,
|
|
||||||
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 = (int) 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 = (int) 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 = (int) 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP request handler function
|
|
||||||
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
|
|
||||||
if (ev == MG_EV_ACCEPT) {
|
|
||||||
if (c->fn_data != NULL) { // TLS listener!
|
|
||||||
struct mg_tls_opts opts = {0};
|
|
||||||
opts.cert = mg_unpacked("/certs/server_cert.pem");
|
|
||||||
opts.key = mg_unpacked("/certs/server_key.pem");
|
|
||||||
mg_tls_init(c, &opts);
|
|
||||||
}
|
|
||||||
} else if (ev == MG_EV_HTTP_MSG) {
|
|
||||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
|
||||||
struct user *u = authenticate(hm);
|
|
||||||
|
|
||||||
if (mg_match(hm->uri, mg_str("/api/#"), NULL) && u == NULL) {
|
|
||||||
mg_http_reply(c, 403, "", "Not Authorised\n");
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/login"), NULL)) {
|
|
||||||
handle_login(c, u);
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/logout"), NULL)) {
|
|
||||||
handle_logout(c);
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/debug"), NULL)) {
|
|
||||||
handle_debug(c, hm);
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/stats/get"), NULL)) {
|
|
||||||
handle_stats_get(c);
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/events/get"), NULL)) {
|
|
||||||
handle_events_get(c, hm);
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/settings/get"), NULL)) {
|
|
||||||
handle_settings_get(c);
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/settings/set"), NULL)) {
|
|
||||||
handle_settings_set(c, hm->body);
|
|
||||||
} else if (mg_match(hm->uri, mg_str("/api/firmware/upload"), NULL)) {
|
|
||||||
handle_firmware_upload(c, hm);
|
|
||||||
} else {
|
|
||||||
struct mg_http_serve_opts opts;
|
|
||||||
memset(&opts, 0, sizeof(opts));
|
|
||||||
opts.fs = HAL_FS;
|
|
||||||
opts.root_dir = HAL_WEB_ROOT_DIR;
|
|
||||||
mg_http_serve_dir(c, ev_data, &opts);
|
|
||||||
}
|
|
||||||
MG_DEBUG(("%lu %.*s %.*s -> %.*s", c->id, (int) hm->method.len,
|
|
||||||
hm->method.buf, (int) hm->uri.len, hm->uri.buf, (int) 3,
|
|
||||||
&c->send.buf[9]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void net_init(struct mg_mgr *mgr) {
|
|
||||||
s_settings.device_name = strdup("My Device");
|
|
||||||
mg_http_listen(mgr, HTTP_URL, ev_handler, NULL);
|
|
||||||
mg_http_listen(mgr, HTTPS_URL, ev_handler, (void *) 1);
|
|
||||||
mg_timer_add(mgr, 3600 * 1000, MG_TIMER_RUN_NOW | MG_TIMER_REPEAT,
|
|
||||||
timer_sntp_fn, mgr);
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2023-2024 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "mongoose.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if MG_ENABLE_FATFS
|
|
||||||
#define HAL_FS (&mg_fs_fat)
|
|
||||||
#define HAL_ROOT_DIR "/"
|
|
||||||
#elif MG_ENABLE_PACKED_FS
|
|
||||||
#define HAL_FS (&mg_fs_packed)
|
|
||||||
#define HAL_ROOT_DIR "/"
|
|
||||||
#else
|
|
||||||
#define HAL_FS (&mg_fs_posix)
|
|
||||||
#define HAL_ROOT_DIR "./"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define HAL_WEB_ROOT_DIR HAL_ROOT_DIR "web_root"
|
|
||||||
|
|
||||||
#if defined(HTTP_URL) && defined(HTTPS_URL)
|
|
||||||
// Allow to override via the build flags
|
|
||||||
#elif MG_ENABLE_TCPIP
|
|
||||||
#define HTTP_URL "http://0.0.0.0:80" // Embedded build:
|
|
||||||
#define HTTPS_URL "https://0.0.0.0:443" // Use standard privileged ports
|
|
||||||
#else
|
|
||||||
#define HTTP_URL "http://0.0.0.0:8000" // Workstation build:
|
|
||||||
#define HTTPS_URL "https://0.0.0.0:8443" // Use non-privileged ports
|
|
||||||
#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 net_init(struct mg_mgr *mgr);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
// DO NOT EDIT. This file is generated using this command:
|
|
||||||
// /usr/local/bin/node /Users/cpq/src/mongoose/reference-projects/windows-macos-linux/web-ui-dashboard/pack.js web_root/bundle.js::gzip web_root/components.js::gzip web_root/history.min.js::gzip web_root/index.html::gzip web_root/main.css::gzip web_root/main.js::gzip certs/server_cert.pem certs/server_key.pem
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *mg_unlist(size_t no);
|
|
||||||
const char *mg_unpack(const char *, size_t *, time_t *);
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const unsigned char v0[] = {31,139,8,0,0,0,0,0,0,19,173,60,253,119,219,54,146,255,138,197,203,227,2,213,132,150,210,118,239,142,10,170,151,186,105,157,54,73,179,249,234,238,170,42,31,69,65,22,107,10,148,65,80,137,107,234,254,246,123,51,0,72,74,150,123,119,251,238,23,11,223,24,12,6,243,77,239,82,125,166,192,128,132,4,52,148,144,67,13,5,100,226,110,15,169,152,205,161,18,231,105,150,155,70,126,102,211,184,106,174,26,213,108,155,71,188,209,219,117,115,165,243,101,83,126,170,154,141,202,26,101,62,53,185,146,179,108,61,111,254,40,203,230,183,82,47,155,220,72,157,158,231,147,85,173,50,147,151,234,108,197,20,24,126,183,42,53,219,165,250,76,158,229,234,204,112,53,147,115,97,102,114,62,209,210,212,90,157,169,125,59,99,203,20,191,195,177,70,168,104,155,106,169,204,235,114,41,39,38,12,77,164,229,166,220,201,139,117,94,44,153,226,221,164,53,163,19,217,137,238,88,226,110,63,193,125,115,220,83,242,224,90,222,6,66,228,83,45,228,44,159,199,129,150,43,170,151,182,94,207,242,57,149,38,249,138,165,250,170,222,72,101,170,168,144,234,202,172,191,121,18,134,172,142,50,220,88,75,37,238,245,127,57,85,81,150,22,69,55,19,158,240,56,225,16,120,24,3,33,204,237,86,150,171,51,19,134,170,46,138,129,48,209,82,174,210,186,48,111,116,185,173,120,11,236,81,251,174,204,151,103,35,33,4,130,136,112,32,164,135,99,102,249,156,123,92,46,153,129,154,238,22,119,233,33,105,201,148,191,116,139,168,90,220,33,72,177,130,45,46,18,39,112,45,111,99,13,90,174,226,18,146,228,58,198,21,32,73,252,239,34,30,65,146,72,95,93,198,22,52,72,146,204,183,173,109,33,43,85,101,116,157,153,82,119,131,118,212,135,56,31,14,101,156,239,219,219,183,173,29,90,118,170,92,74,188,111,42,176,154,67,221,29,99,199,248,157,157,120,151,213,26,233,131,150,221,119,35,54,72,66,126,237,246,210,186,254,91,75,148,102,157,87,17,157,92,40,160,74,86,42,35,63,27,97,186,177,87,118,108,190,98,22,74,195,219,133,147,100,122,197,240,7,240,79,148,36,215,81,174,150,242,243,207,43,166,248,112,204,9,172,73,75,250,19,243,84,209,32,75,50,19,51,28,114,183,236,64,48,41,168,115,102,230,220,227,65,70,73,34,253,118,84,113,8,59,65,83,42,194,2,194,99,183,237,14,176,104,223,19,200,73,183,159,162,253,218,189,176,146,217,119,138,69,11,77,22,45,210,74,10,186,80,35,70,255,226,1,238,238,45,104,207,178,208,50,189,222,187,227,33,148,189,27,188,70,160,217,0,231,44,195,144,64,90,138,193,136,135,161,142,182,117,181,102,138,135,225,224,34,74,18,61,28,54,77,57,16,244,32,22,101,173,50,249,86,170,165,212,185,186,226,97,200,88,121,178,167,105,114,206,46,122,143,227,130,89,44,121,222,136,44,164,128,140,174,79,71,85,169,13,171,249,68,9,29,85,235,124,101,24,159,112,15,157,17,218,161,4,18,225,136,189,244,133,66,176,156,144,195,163,36,217,225,31,9,44,35,20,188,65,248,18,100,186,172,20,43,118,183,135,156,211,40,145,227,223,225,24,222,179,12,114,40,1,71,43,176,43,14,132,200,162,242,147,146,250,221,199,31,158,23,18,153,13,88,124,227,180,245,116,86,204,221,99,4,75,178,197,244,138,229,60,46,128,250,57,188,101,9,228,156,106,114,32,138,48,92,176,156,115,240,135,248,198,32,150,221,137,249,132,144,44,70,29,166,62,179,251,242,163,178,200,91,193,22,214,176,131,91,88,192,53,92,136,36,12,233,93,52,77,10,159,197,133,39,28,196,41,30,233,26,207,190,18,163,201,234,169,105,251,14,136,106,71,136,186,158,173,230,194,158,133,237,132,153,173,230,188,105,130,69,89,22,50,237,189,129,93,211,156,120,25,187,41,206,140,131,202,224,197,31,142,86,245,102,33,245,97,219,34,191,202,149,233,207,95,18,52,176,35,116,218,63,59,30,63,211,58,189,141,242,138,126,217,142,79,151,108,3,119,158,217,196,187,125,111,56,49,226,120,23,37,201,226,155,209,116,201,118,244,90,97,103,185,15,236,162,107,121,11,187,72,203,213,148,254,218,251,219,17,197,196,59,78,236,7,107,66,82,227,130,176,178,24,142,221,5,11,182,22,23,22,43,235,48,164,213,132,88,227,15,214,112,43,129,117,44,112,28,231,104,115,34,139,74,158,225,101,108,197,104,178,125,250,121,178,29,14,105,47,90,111,139,15,249,207,23,187,195,81,126,53,251,158,215,116,81,251,247,76,193,14,214,98,221,52,217,1,157,192,173,216,217,71,176,21,116,86,30,134,107,252,29,136,109,24,178,235,166,97,72,22,28,168,49,12,175,237,123,167,154,199,61,184,198,45,97,35,107,154,91,216,113,238,30,193,237,212,113,234,69,24,178,133,184,61,41,130,237,65,240,64,72,133,120,158,36,185,158,238,136,205,20,226,57,219,65,1,138,199,133,248,96,207,1,23,112,11,197,201,165,164,91,138,40,122,41,10,206,227,2,143,132,60,15,31,87,209,83,98,6,66,133,33,43,196,21,91,115,190,247,207,64,138,5,172,196,231,201,234,241,227,9,183,135,192,91,10,67,246,39,219,117,227,112,133,48,244,37,65,180,177,108,225,121,198,18,30,41,249,217,188,203,23,5,114,62,248,133,225,88,32,130,225,40,17,174,73,243,176,239,240,186,255,14,95,49,124,121,112,61,27,14,219,159,30,203,124,110,25,65,167,221,37,160,173,16,128,82,140,38,58,12,203,167,158,169,76,202,225,144,179,68,232,89,57,39,182,135,212,172,192,136,19,71,76,172,44,123,206,18,90,62,254,192,144,217,32,187,73,136,114,12,111,117,157,158,160,190,180,130,218,119,8,211,52,179,185,123,32,234,20,187,80,77,195,14,31,177,226,83,21,85,229,70,50,230,151,69,5Line truncated
|
|
||||||
|
|
||||||
static const unsigned char v1[] = {31,139,8,0,0,0,0,0,0,19,237,125,107,115,219,70,182,224,119,255,138,19,150,54,36,199,236,22,186,241,150,68,165,28,207,77,57,85,214,220,84,156,232,75,110,118,13,129,32,137,17,30,92,0,164,36,107,248,223,183,206,233,198,147,148,236,100,124,167,118,181,83,149,64,64,163,159,231,253,2,61,222,150,17,148,85,17,135,213,248,252,85,156,110,242,162,130,71,88,207,160,136,178,69,84,204,96,91,70,31,170,160,138,232,238,63,150,203,40,172,232,246,231,104,57,131,117,149,38,51,248,57,223,86,81,1,123,88,22,121,10,48,230,167,55,219,108,145,68,252,239,229,248,252,213,171,211,83,120,23,37,155,168,128,229,54,11,171,56,207,160,90,7,21,20,81,181,45,178,18,2,216,20,121,26,151,81,221,92,230,201,46,42,33,88,226,172,139,40,9,30,94,133,121,86,86,240,87,188,135,57,76,210,114,6,187,32,153,194,252,18,178,232,14,126,82,19,76,244,88,108,46,163,234,151,56,141,242,109,85,183,206,160,30,54,61,127,245,42,186,167,179,170,137,127,196,63,48,135,199,87,0,235,40,40,170,51,220,211,166,196,137,240,140,31,47,202,221,10,194,36,40,203,249,201,35,189,226,244,180,135,251,52,201,202,249,104,93,85,155,179,211,211,187,187,59,126,103,242,188,88,157,74,195,48,78,203,221,106,4,203,56,73,230,163,44,207,162,17,236,226,232,238,251,252,126,62,50,192,0,105,129,180,70,151,23,155,160,90,35,22,242,219,136,37,113,22,133,193,102,62,42,242,109,182,24,117,155,255,158,199,217,176,253,46,94,84,235,249,72,142,96,49,31,93,89,220,20,30,56,120,13,44,110,3,254,111,128,97,24,216,230,88,239,133,4,105,224,93,226,114,199,147,140,174,189,158,140,58,178,166,187,203,29,211,73,152,192,41,213,245,72,119,48,62,141,46,47,78,241,24,151,23,120,230,203,143,179,87,0,139,252,46,123,83,20,57,30,248,95,9,208,1,108,4,183,235,166,249,40,220,22,69,148,85,111,243,36,47,70,151,240,167,64,143,144,246,193,227,210,126,231,114,59,144,92,218,64,23,130,72,243,184,243,7,175,154,167,245,177,55,52,112,199,134,175,88,243,238,157,176,175,124,16,50,49,193,76,13,48,18,147,153,41,51,193,188,198,183,35,56,189,132,14,240,183,155,127,131,254,107,130,62,53,152,153,48,4,57,130,30,193,158,154,204,188,22,7,128,15,243,213,139,131,56,183,125,11,76,238,91,33,55,124,198,109,75,114,219,97,220,183,64,112,33,240,102,45,185,237,155,33,183,17,116,130,27,146,155,190,71,111,185,111,37,92,10,19,4,151,158,8,185,225,152,220,116,81,82,153,220,241,28,238,88,54,247,92,110,184,22,55,44,46,44,151,27,158,201,165,228,66,186,220,148,22,23,190,195,93,196,130,139,19,187,54,23,210,74,4,151,194,101,220,178,157,64,112,33,109,80,87,3,12,33,184,233,114,203,199,46,190,131,216,180,220,131,62,140,75,7,4,183,76,129,178,205,48,76,238,73,55,100,92,250,38,151,22,227,150,233,113,71,152,120,35,184,239,203,192,225,174,237,131,186,226,4,6,112,105,219,33,227,134,225,114,211,245,184,48,61,238,218,220,50,185,143,75,27,134,205,61,233,133,220,146,22,55,109,110,155,22,247,109,171,94,22,87,149,190,247,212,238,4,55,29,159,91,62,237,174,62,104,200,184,105,219,140,11,211,100,220,181,25,55,92,137,155,119,29,132,72,224,112,219,5,186,232,3,34,4,61,28,100,10,46,60,147,113,219,19,220,242,109,198,29,203,226,158,227,39,172,193,11,30,196,231,182,133,189,28,238,91,184,5,66,157,88,51,196,172,21,50,66,45,174,39,25,226,150,213,152,87,179,48,133,93,198,13,7,223,187,22,227,166,144,12,49,76,235,49,238,185,184,69,9,116,169,183,200,16,203,184,71,137,7,243,29,198,93,201,16,213,234,96,140,112,173,96,112,20,215,10,82,12,209,77,16,117,217,113,136,114,233,48,133,110,68,13,238,70,186,33,151,62,46,102,113,203,116,25,162,155,227,249,21,182,125,19,119,138,87,194,54,35,108,35,178,241,112,30,34,193,83,72,80,67,20,21,209,188,222,81,98,163,213,147,231,182,136,100,203,8,231,120,92,135,48,206,77,219,65,124,115,215,70,120,72,104,161,66,216,231,134,133,44,227,48,110,120,174,6,167,199,77,19,111,60,147,219,158,196,25,109,141,0,199,71,70,180,20,170,62,41,185,245,103,69,130,176,65,200,192,4,19,217,93,48,7,12,80,15,134,112,208,28,24,8,197,50,170,170,56,91,149,239,94,154,104,20,6,183,193,89,251,220,181,245,125,32,56,162,213,86,128,49,193,72,77,48,186,141,6,54,94,33,78,193,65,45,150,154,32,36,205,144,50,188,246,122,27,199,166,48,104,138,148,209,28,6,205,225,51,103,109,210,20,230,31,154,66,45,72,171,63,133,179,235,151,134,51,7,132,201,237,107,2,151,1,120,244,30,180,12,52,175,152,217,3,22,181,1,142,184,22,14,183,83,33,153,249,79,77,192,28,230,215,19,152,95,62,129,79,19,24,252,16,89,97,144,189,52,60,185,220,38,216,188,115,222,244,13,51,197,59,59,193,237,43,4,166,234,36,188,126,47,33,13,188,163,110,8,185,235,131,14,194,3,234,179,102,216,133,249,96,12,87,18,180,146,240,118,140,214,250,98,153,7,202,255,137,202,219,42,223,188,52,180,248,32,92,180,151,81,227,185,65,13,1,84,240,62,160,205,33,223,35,226,164,88,163,129,225,72,65,151,55,117,63,4,34,218,239,238,53,205,146,58,76,200,107,49,48,229,69,107,202,191,179,185,180,135,88,1,97,95,99,123,42,60,48,6,196,33,208,14,3,243,200,56,195,132,102,208,181,144,127,116,73,73,75,14,25,47,72,162,127,109,184,224,95,162,213,44,238,161,185,141,182,184,12,164,201,61,203,3,253,7,1,105,115,203,182,40,28,240,198,227,190,227,130,186,106,166,66,33,181,99,220,189Line truncated
|
|
||||||
|
|
||||||
static const unsigned char v2[] = {31,139,8,0,0,0,0,0,0,19,237,91,109,111,219,184,150,254,43,182,6,43,144,48,163,218,157,185,179,187,114,57,70,218,166,47,64,130,4,77,218,249,96,24,3,69,166,108,78,100,210,165,40,39,134,173,255,190,56,164,168,23,91,73,211,189,157,189,131,221,253,18,75,124,61,60,58,60,231,121,14,153,126,146,139,88,115,41,144,38,2,239,60,121,251,39,139,181,71,169,222,174,153,76,122,236,97,45,149,206,124,255,168,102,37,231,121,202,38,246,39,40,219,81,129,112,232,185,49,235,198,115,150,112,193,124,223,254,6,209,106,62,177,143,104,58,35,2,135,143,205,59,41,127,131,15,60,211,82,109,205,248,186,249,86,32,189,228,25,169,150,129,119,138,233,92,137,94,189,48,188,115,207,61,129,36,222,241,4,177,169,156,225,178,33,60,59,249,199,155,72,245,20,133,34,186,43,203,194,93,65,248,60,148,36,149,209,156,205,195,254,168,24,151,93,53,116,141,163,52,69,202,141,64,20,169,159,5,38,42,176,221,104,127,88,87,20,48,13,163,187,106,32,17,172,168,38,34,136,41,35,34,88,83,207,35,2,13,113,129,166,205,239,67,24,222,121,121,198,122,153,86,60,214,222,184,90,151,132,85,58,161,124,95,7,127,252,193,178,11,251,133,116,184,155,179,36,202,83,29,234,162,16,141,42,144,73,4,177,98,145,102,87,145,94,82,17,172,35,149,185,231,84,198,17,140,158,157,42,118,246,53,143,82,234,26,159,151,53,85,193,5,91,73,181,173,62,75,89,250,33,202,150,135,101,175,149,188,207,152,114,197,27,201,231,189,161,83,59,122,137,199,151,198,18,2,107,30,87,74,174,153,210,91,36,136,215,158,218,35,59,38,242,21,83,209,109,202,194,254,144,44,152,14,143,173,64,29,72,92,20,152,60,58,195,209,130,159,61,201,81,207,162,192,102,81,156,50,52,122,98,81,149,190,159,57,21,175,191,208,147,75,169,63,234,179,7,174,187,56,225,35,202,208,191,99,18,83,137,34,76,114,202,208,127,96,146,81,137,114,76,18,202,208,127,98,146,82,137,18,60,126,228,235,198,65,105,121,164,203,36,178,163,218,182,25,165,174,190,32,7,94,170,185,7,14,12,122,44,130,104,62,63,103,209,156,139,197,117,26,101,75,218,244,4,118,181,222,11,143,82,170,131,120,25,169,83,141,134,120,162,67,239,133,55,208,5,17,1,12,188,254,254,1,130,44,191,205,180,66,35,28,214,195,92,41,150,240,7,218,22,191,212,248,208,140,192,197,156,61,92,38,72,52,134,16,65,202,196,66,47,155,35,221,168,136,167,207,151,72,151,67,156,140,204,184,41,143,25,26,146,19,39,92,189,205,155,35,193,55,23,84,239,247,222,11,143,48,112,66,18,254,40,42,42,49,189,159,60,60,86,125,74,79,70,190,143,36,21,78,102,133,137,168,223,134,68,97,183,1,26,157,39,208,185,180,55,55,6,171,123,241,131,49,56,134,130,57,139,229,156,125,254,244,17,9,76,118,235,72,47,69,180,98,161,32,25,139,84,188,12,189,9,172,156,77,60,47,100,100,25,101,203,208,251,9,74,36,148,200,162,104,187,184,142,245,6,110,76,194,168,14,236,168,68,82,29,192,96,68,81,38,42,1,140,106,170,53,48,223,247,38,94,159,82,230,251,72,13,104,41,73,195,42,24,72,55,96,152,72,223,247,126,130,166,178,108,106,69,108,52,149,32,246,64,98,162,138,182,189,255,53,94,255,25,206,189,229,155,75,79,19,101,25,95,136,253,190,21,93,165,66,86,149,163,177,120,21,169,69,190,98,66,103,165,5,142,197,96,96,85,205,104,85,55,21,179,177,235,38,123,92,244,24,46,39,88,43,169,37,128,0,208,254,229,189,112,78,205,134,89,70,36,246,125,4,113,215,4,105,92,184,229,23,196,184,218,33,38,17,149,96,73,49,188,142,192,109,73,20,131,219,50,142,248,104,145,109,77,19,105,69,229,110,241,229,230,2,213,139,69,13,79,244,4,113,138,134,36,171,119,18,70,26,19,30,100,58,210,140,10,28,34,78,21,218,21,68,99,98,199,162,148,242,202,212,124,31,213,47,212,243,76,87,99,121,19,107,82,238,181,182,16,211,197,22,130,165,13,220,11,14,235,98,143,112,99,181,19,107,108,246,229,96,8,40,2,251,27,216,71,232,110,139,188,82,208,62,165,194,247,27,66,155,53,217,233,203,213,129,184,119,108,75,25,24,118,99,37,19,239,133,157,215,21,28,204,93,173,24,13,73,228,220,59,110,84,16,89,61,98,144,172,234,208,40,39,188,232,52,224,78,47,91,239,110,74,13,190,113,250,119,59,221,20,219,71,40,52,170,128,34,120,128,2,88,38,188,223,177,173,239,163,33,201,107,177,181,213,135,113,209,145,102,248,91,27,215,88,59,109,196,222,98,172,43,228,44,255,242,93,95,161,172,159,49,225,20,73,240,217,13,97,160,86,83,145,167,41,105,108,139,134,38,169,104,54,215,212,152,9,178,93,96,237,172,209,11,182,18,81,6,107,67,117,159,106,183,177,58,216,129,158,104,232,129,67,61,62,218,105,124,210,209,65,78,36,226,68,225,80,161,254,16,254,66,52,233,143,112,193,210,140,245,76,97,65,36,157,206,136,234,112,248,253,97,83,84,188,19,160,196,104,189,78,183,200,26,61,169,252,20,174,16,186,12,214,121,182,68,172,165,50,65,251,35,34,169,12,18,158,106,166,208,113,88,238,105,8,15,5,168,135,55,231,116,206,79,211,67,127,73,4,61,85,42,218,130,59,97,116,56,102,175,244,152,13,6,88,76,217,172,225,64,217,108,44,131,68,170,179,40,94,118,206,219,94,145,192,69,181,150,93,198,244,149,146,171,181,14,5,137,165,72,184,90,221,168,72,100,28,198,184,145,33,35,209,122,205,196,252,156,103,154,9,166,66,69,132,212,60,217,186,130,44,228,128,17,133,219,10,148,127,39,68,139,35,241,57,99,111,47,47,104,31,121,185,176,248,117,94,127,224,123,46,230,242,126,191,239,219,135,96,46,99,179,238,227,146,210,1Line truncated
|
|
||||||
|
|
||||||
static const unsigned char v3[] = {31,139,8,0,0,0,0,0,0,19,93,147,77,115,219,32,16,134,239,249,21,91,46,58,52,66,232,91,206,8,205,164,105,14,61,116,218,67,219,105,143,68,90,75,36,8,84,192,114,252,239,59,178,108,215,201,133,133,125,159,133,133,93,234,15,159,191,61,252,248,243,253,17,6,63,170,230,166,94,12,40,161,123,78,80,19,104,149,112,142,147,33,220,238,148,130,167,62,220,15,210,35,105,110,0,234,1,69,183,76,0,106,47,189,194,166,142,86,187,250,70,244,2,218,65,88,135,158,147,157,223,134,21,129,232,90,28,188,159,66,252,187,147,51,39,191,195,159,247,225,131,25,39,225,229,147,66,2,173,209,30,181,231,228,203,35,199,174,199,119,177,90,140,200,201,44,113,63,25,235,175,240,189,236,252,192,59,156,101,139,225,113,113,11,82,75,47,133,10,93,43,20,242,152,178,255,155,41,169,95,192,162,226,68,182,70,19,240,135,9,57,145,163,232,49,114,115,255,241,117,84,4,6,139,91,78,58,225,197,221,27,229,182,118,115,15,175,163,210,142,7,203,109,238,162,104,191,223,211,125,74,141,237,163,132,49,182,160,1,108,165,82,60,208,70,99,0,75,206,159,204,43,15,24,48,72,50,72,178,0,156,183,230,229,148,46,15,98,154,159,93,60,104,119,214,162,246,15,70,25,27,52,80,79,194,15,103,94,73,141,173,152,120,96,205,78,119,193,181,251,217,72,125,241,119,60,248,26,103,180,202,75,136,75,202,170,68,36,41,173,178,10,78,134,1,99,57,205,242,44,140,105,26,223,87,116,83,148,176,142,12,88,28,87,176,161,101,62,135,180,252,181,185,47,160,56,6,20,176,153,105,153,139,247,116,152,208,52,78,160,160,44,73,218,152,150,105,74,139,12,82,154,23,16,83,86,229,176,156,148,195,114,210,152,211,50,206,128,137,36,163,73,158,195,201,28,119,57,73,23,36,133,20,24,196,23,33,128,168,129,122,121,222,230,93,53,215,106,141,66,106,218,58,71,214,234,58,127,80,232,6,68,127,162,235,232,220,191,245,147,233,14,231,78,31,165,14,135,208,181,22,81,147,166,142,22,237,8,185,214,202,201,131,179,45,39,131,116,222,216,3,29,165,166,207,110,193,86,245,26,92,27,105,52,221,110,233,230,99,216,49,165,183,124,29,173,255,238,31,169,238,250,235,136,3,0,0,0};
|
|
||||||
|
|
||||||
static const unsigned char v4[] = {31,139,8,0,0,0,0,0,0,19,237,60,217,142,228,56,114,191,34,247,96,128,202,177,168,214,153,89,169,130,141,53,22,48,188,192,142,31,108,63,120,209,213,15,76,137,153,201,45,93,38,169,170,204,214,202,223,110,4,41,74,212,145,215,28,246,236,194,24,84,87,49,46,6,131,100,40,24,12,206,231,31,254,206,18,152,102,31,180,72,19,206,173,247,192,9,28,223,250,139,245,227,31,254,195,250,35,77,72,193,137,245,23,235,40,68,197,227,207,159,13,82,39,41,243,31,62,255,96,199,120,47,8,179,227,29,217,151,140,52,187,242,132,56,253,70,139,67,188,43,89,74,24,218,149,167,23,245,103,236,90,188,204,104,106,125,71,34,178,33,187,118,194,139,144,248,64,73,89,8,82,136,248,211,167,246,40,242,172,201,104,65,208,145,208,195,81,196,158,19,189,160,15,178,123,163,2,9,114,18,208,19,65,56,253,115,205,69,236,185,238,247,47,40,47,191,33,129,119,18,19,135,47,168,52,91,198,159,251,178,16,104,143,115,154,157,227,63,20,130,48,235,29,51,251,159,24,197,153,253,47,36,123,39,130,38,216,230,184,224,136,19,70,247,29,3,193,162,102,4,113,34,4,45,14,60,254,148,188,123,222,39,251,19,231,174,247,73,209,188,99,70,177,160,101,97,80,149,21,255,246,201,10,252,118,87,166,231,38,199,236,64,139,216,125,49,199,70,139,35,97,84,180,71,214,116,16,247,37,41,179,146,105,76,103,68,36,202,10,125,208,84,28,99,175,58,181,120,183,99,241,199,145,48,242,244,69,80,145,145,175,171,102,100,162,148,36,37,147,250,196,117,145,18,6,125,90,105,41,4,73,95,110,17,180,71,207,62,250,246,49,176,143,161,125,140,236,227,186,145,67,148,54,212,106,73,200,199,120,16,184,25,171,62,237,72,211,237,108,46,88,89,28,26,83,200,174,204,82,194,218,164,76,137,253,182,75,237,138,17,155,227,188,106,204,57,171,41,202,203,162,228,21,78,136,253,239,255,252,99,89,148,232,223,200,161,206,48,179,127,36,69,86,218,63,150,5,78,74,251,247,101,193,203,12,115,251,143,116,71,84,247,22,80,219,191,47,107,70,9,179,254,149,124,216,189,168,151,97,124,30,201,91,158,227,44,51,198,252,236,126,223,242,122,103,243,186,50,160,155,232,251,209,84,186,47,85,201,169,28,40,35,25,22,244,157,188,188,19,6,43,42,67,56,163,7,48,0,21,20,103,32,172,217,149,66,148,121,140,28,63,130,46,235,170,17,101,21,35,7,90,2,239,50,210,72,243,209,34,133,125,225,234,117,176,184,56,146,50,203,112,197,73,172,255,104,119,181,16,101,97,211,162,170,133,93,86,226,192,202,186,178,57,201,72,34,108,16,140,25,193,35,211,142,38,86,153,2,182,214,194,60,47,45,224,201,162,237,215,122,133,211,20,188,130,171,53,82,42,168,177,9,134,11,190,47,89,30,23,101,65,218,47,226,92,145,127,80,116,95,109,213,98,132,19,161,27,188,222,229,84,124,181,21,73,191,224,113,85,17,204,112,145,144,88,97,94,118,56,121,131,17,23,105,111,47,105,120,19,65,115,124,32,170,227,88,250,143,125,153,212,156,209,226,208,148,181,128,33,198,184,22,101,135,172,41,162,197,59,206,104,170,124,221,17,167,229,135,226,174,88,121,96,132,243,230,194,100,199,177,86,148,22,5,97,136,87,180,64,157,53,6,92,89,139,49,78,251,3,169,68,55,126,130,89,114,252,186,52,112,176,231,158,146,44,125,233,148,71,229,126,207,137,136,145,95,157,12,21,148,8,99,83,46,9,83,70,233,121,246,52,35,168,174,178,18,167,232,166,233,97,189,244,27,157,215,121,142,217,185,73,41,175,50,124,142,51,202,5,162,130,228,237,46,43,147,183,255,170,75,65,236,52,181,211,204,222,211,67,205,136,61,115,61,246,145,217,21,56,131,222,127,182,114,156,156,136,57,196,206,200,129,20,105,51,172,186,156,20,181,93,102,118,13,159,20,46,16,23,231,76,13,112,105,141,246,27,131,17,185,3,244,140,182,114,31,197,106,41,84,25,78,200,81,122,171,126,39,205,81,77,89,225,132,138,115,236,117,91,227,187,109,130,3,188,215,162,150,165,220,35,224,11,43,179,97,155,116,19,146,212,140,151,44,174,74,10,95,181,54,78,41,7,31,146,106,68,74,246,184,206,68,139,235,148,150,118,130,139,119,204,109,146,239,72,106,211,61,195,57,177,105,126,176,203,221,159,193,63,240,247,131,253,78,83,82,246,19,39,167,107,234,205,114,154,166,25,105,129,81,81,231,248,164,191,81,224,58,70,11,248,72,211,148,20,95,123,137,114,141,253,96,199,49,108,201,148,149,213,52,164,144,97,65,231,223,192,73,211,226,128,78,177,251,178,4,63,107,184,244,40,25,22,100,32,29,64,61,21,43,5,22,68,183,248,27,249,24,200,101,171,167,228,9,206,64,150,103,54,207,186,89,225,2,157,98,107,104,156,251,6,45,146,35,250,86,150,185,134,240,132,149,89,134,120,129,43,196,5,163,137,40,8,231,113,197,202,19,205,169,56,43,170,3,195,41,37,224,148,89,153,163,254,123,98,77,176,239,20,95,70,138,114,134,43,89,74,11,156,245,186,100,152,31,73,138,190,17,86,106,88,81,231,132,209,4,169,125,56,133,118,134,158,17,51,156,152,253,128,247,68,180,0,191,99,66,148,43,234,150,134,91,157,230,168,110,133,239,247,123,3,215,1,131,221,179,191,95,63,187,115,174,206,11,187,150,107,125,231,186,174,73,177,140,186,6,85,221,145,116,138,221,101,53,211,163,217,49,88,209,114,226,58,8,196,173,12,115,97,204,194,89,174,18,13,56,214,68,175,183,14,66,11,216,71,253,92,64,104,105,96,57,169,40,214,13,216,23,90,105,173,66,183,93,198,122,245,192,153,130,61,106,170,105,143,152,169,220,99,230,186,247,168,241,32,122,176,246,89,83,248,116,148,3,66,13,183,117,56,67,101,145,157,155,126,233,226Line truncated
|
|
||||||
|
|
||||||
static const unsigned char v5[] = {31,139,8,0,0,0,0,0,0,19,189,59,107,115,219,56,146,223,253,43,122,180,222,145,228,33,41,82,150,223,150,167,146,76,102,146,173,76,146,138,157,212,237,186,92,9,68,66,36,198,36,193,2,160,215,104,248,159,238,55,220,47,187,106,128,79,73,86,50,179,123,151,170,200,36,1,116,55,26,141,126,161,49,24,0,188,125,119,247,242,18,158,189,127,13,62,137,99,9,201,76,42,144,138,8,5,11,166,34,232,146,140,13,186,192,82,224,34,160,2,20,7,73,197,156,130,138,40,144,44,3,162,128,164,43,248,248,225,245,193,65,119,38,41,72,37,152,175,186,87,7,44,201,184,80,176,134,200,2,65,211,128,10,11,102,146,222,42,162,168,126,122,57,157,82,95,233,199,15,116,106,65,164,146,216,130,15,124,166,168,128,28,166,130,39,0,93,103,48,153,165,65,76,157,223,100,19,232,107,159,167,210,130,55,60,100,169,5,183,84,41,150,134,22,60,159,41,197,241,131,34,202,2,197,178,23,60,230,66,90,160,255,210,192,130,183,92,177,41,243,137,98,216,239,61,9,89,90,60,127,204,98,78,130,159,89,76,13,148,146,134,174,51,240,121,146,241,148,166,74,26,50,14,16,187,66,236,28,198,144,9,158,73,24,223,232,25,124,185,150,243,16,252,152,72,57,62,92,235,38,71,191,229,176,76,226,84,142,59,145,82,217,229,96,176,88,44,156,197,177,195,69,56,24,186,174,59,144,243,176,3,115,70,23,207,249,114,220,113,193,5,111,232,156,159,233,223,147,206,205,117,64,167,242,230,90,170,85,76,111,156,56,182,253,88,218,222,122,202,226,248,50,229,41,189,146,74,240,71,122,249,55,215,117,139,103,59,97,138,138,152,37,76,93,122,213,199,5,11,84,116,233,58,39,217,242,42,191,30,24,128,215,3,3,62,4,22,140,59,111,200,138,138,207,195,14,4,68,17,59,37,9,45,190,193,176,211,238,227,217,187,122,121,157,155,235,140,168,168,96,67,167,164,182,3,193,184,243,171,55,116,78,135,150,231,156,15,63,157,59,23,222,51,207,57,57,183,244,143,107,185,150,103,121,158,229,185,206,232,252,213,136,120,206,104,100,233,31,221,100,123,182,115,124,246,204,57,189,112,78,47,138,222,67,231,124,100,121,110,108,59,158,237,120,67,226,156,123,206,185,87,244,119,188,19,219,25,157,127,58,113,78,206,136,115,126,230,156,159,21,195,156,243,83,219,57,63,125,53,114,206,142,63,157,57,195,115,226,156,159,58,231,167,186,217,181,244,203,201,171,11,103,132,16,79,156,243,147,170,225,196,118,206,79,62,29,59,163,147,103,173,33,158,235,120,199,214,177,229,156,157,58,103,245,71,77,32,113,134,23,206,208,144,236,34,153,182,227,225,188,46,204,143,249,172,39,247,106,232,28,95,124,66,230,32,95,206,44,253,99,72,30,89,206,240,228,149,231,109,53,212,12,253,87,103,176,151,243,200,86,195,220,79,222,54,227,207,157,11,13,235,213,78,244,206,240,196,242,188,79,199,206,197,104,155,2,231,124,104,13,145,252,115,231,130,180,39,230,225,216,227,179,216,241,134,142,71,26,220,241,44,199,243,28,111,212,224,34,126,26,57,163,179,114,69,42,198,123,182,121,121,117,238,120,199,229,114,214,204,183,205,178,156,190,194,101,105,46,52,182,96,183,79,23,206,168,41,26,174,229,120,39,206,232,60,118,60,45,52,181,68,97,203,177,227,121,86,91,246,92,51,11,205,224,65,88,252,151,243,240,230,203,213,193,193,116,150,250,168,67,224,21,37,1,21,189,117,204,67,62,51,170,77,88,32,169,186,141,248,226,150,5,116,66,240,189,126,201,251,176,62,0,16,84,205,68,106,244,199,193,117,192,230,229,250,77,66,123,17,49,133,106,149,249,143,43,80,60,179,93,248,221,190,31,157,63,192,114,97,79,103,113,12,19,173,155,237,9,100,43,123,8,135,235,6,124,248,254,123,232,102,177,125,54,236,230,160,4,73,37,67,66,109,18,199,16,204,132,214,124,246,177,235,154,182,41,23,73,231,230,0,160,73,66,182,180,135,80,96,202,86,182,11,9,254,76,99,186,4,166,104,34,109,159,166,138,10,61,14,224,122,98,116,167,90,101,116,220,49,47,29,224,169,31,51,255,113,124,184,166,115,84,148,109,142,244,244,183,239,230,253,188,196,169,232,82,217,50,38,138,218,35,215,45,64,3,92,31,174,181,222,119,38,68,200,227,170,119,100,159,118,96,80,224,31,148,15,141,41,104,98,241,199,246,32,36,153,189,180,71,32,105,60,181,165,18,84,249,17,196,225,165,249,126,90,227,106,140,23,52,38,138,205,41,52,0,117,110,42,84,59,144,53,57,83,161,220,129,5,224,90,102,36,109,207,59,129,205,249,199,60,12,105,128,102,152,200,75,56,92,163,92,229,13,252,109,10,34,22,4,52,69,116,147,152,251,143,248,16,25,244,11,59,91,234,239,161,29,10,178,178,135,174,219,1,34,24,177,205,152,113,71,137,25,109,77,77,115,221,24,196,28,20,83,49,106,121,45,222,29,96,62,79,199,229,154,24,153,207,27,107,93,126,169,217,52,104,175,146,254,131,63,95,174,14,242,230,62,42,5,99,61,19,177,217,47,197,70,49,118,247,45,153,191,97,233,35,140,161,183,214,36,89,154,20,11,34,129,142,196,76,196,121,191,178,199,133,56,23,136,137,238,51,238,252,237,112,141,15,121,167,100,154,121,135,241,24,135,195,143,208,157,132,197,10,156,184,102,61,38,241,140,218,167,174,11,161,224,179,172,11,151,208,213,223,53,39,207,92,23,34,62,167,226,178,221,215,124,43,249,125,82,14,206,141,40,25,113,56,6,193,103,105,64,3,59,9,32,179,135,80,138,65,76,73,192,210,208,62,133,41,79,149,45,105,194,38,60,14,154,251,1,231,93,109,132,133,125,10,184,25,42,134,31,26,246,228,37,211,43,174,127,185,250,138,214,153,51,30,83,101,123,56,5,105,227,36,98,178,106,60,218,60,163,2Line truncated
|
|
||||||
|
|
||||||
static const unsigned char v6[] = {45,45,45,45,45,66,69,71,73,78,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,77,73,73,66,67,84,67,66,115,65,73,74,65,75,57,119,98,73,68,107,72,110,65,111,77,65,111,71,67,67,113,71,83,77,52,57,66,65,77,67,77,65,48,120,67,122,65,74,66,103,78,86,66,65,89,84,65,107,108,70,77,66,52,88,10,68,84,73,122,77,68,69,121,79,84,73,120,77,106,69,122,79,70,111,88,68,84,77,122,77,68,69,121,78,106,73,120,77,106,69,122,79,70,111,119,68,84,69,76,77,65,107,71,65,49,85,69,66,104,77,67,83,85,85,119,87,84,65,84,10,66,103,99,113,104,107,106,79,80,81,73,66,66,103,103,113,104,107,106,79,80,81,77,66,66,119,78,67,65,65,82,122,83,81,83,53,79,72,100,49,55,108,85,101,78,73,43,54,107,112,57,87,89,117,48,99,120,117,69,73,105,47,74,84,10,106,112,104,98,67,109,100,74,68,49,99,85,118,104,109,122,77,57,47,112,104,118,74,84,57,107,97,49,48,90,57,116,111,90,104,103,110,66,113,48,111,48,120,102,84,81,52,106,67,49,118,119,77,65,111,71,67,67,113,71,83,77,52,57,10,66,65,77,67,65,48,103,65,77,69,85,67,73,81,67,101,48,84,50,69,48,71,79,105,86,101,57,75,119,118,73,69,80,101,88,49,74,49,74,48,84,55,84,78,97,99,103,82,48,89,97,51,51,72,86,57,86,103,73,103,78,118,100,110,10,97,69,87,105,66,112,49,120,115,104,115,52,105,122,54,87,98,112,120,114,83,49,73,72,117,99,114,113,107,90,117,74,76,102,78,90,71,90,73,61,10,45,45,45,45,45,69,78,68,32,67,69,82,84,73,70,73,67,65,84,69,45,45,45,45,45,10,0};
|
|
||||||
|
|
||||||
static const unsigned char v7[] = {45,45,45,45,45,66,69,71,73,78,32,69,67,32,80,82,73,86,65,84,69,32,75,69,89,45,45,45,45,45,10,77,72,99,67,65,81,69,69,73,67,66,122,51,72,79,107,81,76,80,66,68,116,100,107,110,113,67,55,107,49,80,78,115,87,106,54,72,102,104,121,78,66,53,77,101,110,102,106,109,113,105,111,111,65,111,71,67,67,113,71,83,77,52,57,10,65,119,69,72,111,85,81,68,81,103,65,69,99,48,107,69,117,84,104,51,100,101,53,86,72,106,83,80,117,112,75,102,86,109,76,116,72,77,98,104,67,73,118,121,85,52,54,89,87,119,112,110,83,81,57,88,70,76,52,90,115,122,80,102,10,54,89,98,121,85,47,90,71,116,100,71,102,98,97,71,89,89,74,119,97,116,75,78,77,88,48,48,79,73,119,116,98,56,65,61,61,10,45,45,45,45,45,69,78,68,32,69,67,32,80,82,73,86,65,84,69,32,75,69,89,45,45,45,45,45,10,0};
|
|
||||||
|
|
||||||
static const struct packed_file {
|
|
||||||
const char *name;
|
|
||||||
const unsigned char *data;
|
|
||||||
size_t size;
|
|
||||||
time_t mtime;
|
|
||||||
} packed_files[] = {
|
|
||||||
{"/web_root/bundle.js.gz", v0, sizeof(v0) - 1, 1710000285},
|
|
||||||
{"/web_root/components.js.gz", v1, sizeof(v1) - 1, 1713984696},
|
|
||||||
{"/web_root/history.min.js.gz", v2, sizeof(v2) - 1, 1710000285},
|
|
||||||
{"/web_root/index.html.gz", v3, sizeof(v3) - 1, 1710000285},
|
|
||||||
{"/web_root/main.css.gz", v4, sizeof(v4) - 1, 1713984502},
|
|
||||||
{"/web_root/main.js.gz", v5, sizeof(v5) - 1, 1713984681},
|
|
||||||
{"/certs/server_cert.pem", v6, sizeof(v6) - 1, 1710000285},
|
|
||||||
{"/certs/server_key.pem", v7, sizeof(v7) - 1, 1710000285},
|
|
||||||
{NULL, NULL, 0, 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int scmp(const char *a, const char *b) {
|
|
||||||
while (*a && (*a == *b)) a++, b++;
|
|
||||||
return *(const unsigned char *) a - *(const unsigned char *) b;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *mg_unlist(size_t no) {
|
|
||||||
return packed_files[no].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *mg_unpack(const char *name, size_t *size, time_t *mtime) {
|
|
||||||
const struct packed_file *p;
|
|
||||||
for (p = packed_files; p->name != NULL; p++) {
|
|
||||||
if (scmp(p->name, name) != 0) continue;
|
|
||||||
if (size != NULL) *size = p->size;
|
|
||||||
if (mtime != NULL) *mtime = p->mtime;
|
|
||||||
return (const char *) p->data;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,356 +0,0 @@
|
|||||||
'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-screen 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}<//>
|
|
||||||
<//>`;
|
|
||||||
};
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
!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,14 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" class="h-full bg-white">
|
|
||||||
<head>
|
|
||||||
<title></title>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<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" />
|
|
||||||
</head>
|
|
||||||
<body class="min-h-screen"></body>
|
|
||||||
<script src="history.min.js"></script>
|
|
||||||
<script type="module" src="main.js"></script>
|
|
||||||
</html>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/*! 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,Arial,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%}.h-screen{height:100vh}.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-collaLine truncated
|
|
||||||
@@ -1,376 +0,0 @@
|
|||||||
// NOTE: API calls must start with 'api/' in order to serve the app at any URI
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
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 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>`;
|
|
||||||
|
|
||||||
function Header({logout, user, setShowSidebar, showSidebar}) {
|
|
||||||
return html`
|
|
||||||
<div class="bg-white sticky top-0 z-[48] xw-full border-b py-2 ${showSidebar && 'pl-72'} transition-all duration-300 transform">
|
|
||||||
<div class="px-2 w-full py-0 my-0 flex items-center">
|
|
||||||
<button type="button" onclick=${ev => setShowSidebar(v => !v)} class="text-slate-400">
|
|
||||||
<${Icons.bars3} class="h-6" />
|
|
||||||
<//>
|
|
||||||
<div class="flex flex-1 gap-x-4 self-stretch lg:gap-x-6">
|
|
||||||
<div class="relative flex flex-1"><//>
|
|
||||||
<div class="flex items-center gap-x-4 lg:gap-x-6">
|
|
||||||
<span class="text-sm text-slate-400">logged in as: ${user}<//>
|
|
||||||
<div class="hidden lg:block lg:h-4 lg:w-px lg:bg-gray-200" aria-hidden="true"><//>
|
|
||||||
<${Button} title="Logout" icon=${Icons.logout} onclick=${logout} />
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<//>
|
|
||||||
<//>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
function Sidebar({url, show}) {
|
|
||||||
const NavLink = ({title, icon, href, url}) => html`
|
|
||||||
<div>
|
|
||||||
<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">
|
|
||||||
<${icon} class="w-6 h-6"/>
|
|
||||||
${title}
|
|
||||||
<///>
|
|
||||||
<//>`;
|
|
||||||
return html`
|
|
||||||
<div class="bg-violet-100 hs-overlay hs-overlay-open:translate-x-0
|
|
||||||
-translate-x-full transition-all duration-300 transform
|
|
||||||
fixed top-0 left-0 bottom-0 z-[60] w-72 bg-white border-r
|
|
||||||
border-gray-200 overflow-y-auto scrollbar-y
|
|
||||||
${show && 'translate-x-0'} right-auto bottom-0">
|
|
||||||
<div class="flex flex-col m-4 gap-y-6">
|
|
||||||
<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 refresh = () =>
|
|
||||||
fetch('api/events/get', {
|
|
||||||
method: 'POST', body: JSON.stringify({page: page}),
|
|
||||||
}).then(r => r.json())
|
|
||||||
.then(r => setEvents(r));
|
|
||||||
|
|
||||||
useEffect(refresh, [page]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setPage(JSON.parse(localStorage.getItem('page')));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
localStorage.setItem('page', page.toString());
|
|
||||||
}, [page]);
|
|
||||||
|
|
||||||
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} />`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Event = ({e}) => html`
|
|
||||||
<tr>
|
|
||||||
<${Td} text=${['power', 'hardware', 'tier3', 'tier4'][e.type]} />
|
|
||||||
<${Td} text=${html`<${Prio} prio=${e.prio}/>`} />
|
|
||||||
<${Td} text=${e.time ? (new Date(e.time * 1000)).toLocaleString() : '1970-01-01'} />
|
|
||||||
<${Td} text=${e.text} />
|
|
||||||
<//>`;
|
|
||||||
|
|
||||||
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>
|
|
||||||
<${Pagination} currentPage=${page} setPageFn=${setPage} totalItems=400 itemsPerPage=20 />
|
|
||||||
<//>
|
|
||||||
<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="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);
|
|
||||||
+9
-4
@@ -6,9 +6,9 @@
|
|||||||
#define MG_ARCH_ESP32 3 // ESP32
|
#define MG_ARCH_ESP32 3 // ESP32
|
||||||
#define MG_ARCH_ESP8266 4 // ESP8266
|
#define MG_ARCH_ESP8266 4 // ESP8266
|
||||||
#define MG_ARCH_FREERTOS 5 // FreeRTOS
|
#define MG_ARCH_FREERTOS 5 // FreeRTOS
|
||||||
#define MG_ARCH_AZURERTOS 6 // MS Azure RTOS
|
#define MG_ARCH_THREADX 6 // Eclipse ThreadX (former MS Azure RTOS)
|
||||||
#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
|
#define MG_ARCH_ZEPHYR 7 // Zephyr RTOS
|
||||||
#define MG_ARCH_NEWLIB 8 // Bare metal ARM
|
#define MG_ARCH_ARMGCC 8 // Plain ARM GCC
|
||||||
#define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX)
|
#define MG_ARCH_CMSIS_RTOS1 9 // CMSIS-RTOS API v1 (Keil RTX)
|
||||||
#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
|
#define MG_ARCH_TIRTOS 10 // Texas Semi TI-RTOS
|
||||||
#define MG_ARCH_PICOSDK 11 // Raspberry Pi Pico-SDK (RP2040, RP2350)
|
#define MG_ARCH_PICOSDK 11 // Raspberry Pi Pico-SDK (RP2040, RP2350)
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
#define MG_ARCH_CMSIS_RTOS2 13 // CMSIS-RTOS API v2 (Keil RTX5, FreeRTOS)
|
#define MG_ARCH_CMSIS_RTOS2 13 // CMSIS-RTOS API v2 (Keil RTX5, FreeRTOS)
|
||||||
#define MG_ARCH_RTTHREAD 14 // RT-Thread RTOS
|
#define MG_ARCH_RTTHREAD 14 // RT-Thread RTOS
|
||||||
#define MG_ARCH_ARMCGT 15 // Texas Semi ARM-CGT
|
#define MG_ARCH_ARMCGT 15 // Texas Semi ARM-CGT
|
||||||
|
#define MG_ARCH_CUBE 16 // STM32Cube environment
|
||||||
|
|
||||||
|
#define MG_ARCH_NEWLIB MG_ARCH_ARMGCC // Alias, deprecate in 2025
|
||||||
|
|
||||||
#if !defined(MG_ARCH)
|
#if !defined(MG_ARCH)
|
||||||
#if defined(__unix__) || defined(__APPLE__)
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
@@ -30,17 +33,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(MG_ARCH)
|
#if !defined(MG_ARCH)
|
||||||
#error "MG_ARCH is not specified and we couldn't guess it. Define MG_ARCH=... in your compiler"
|
#error "MG_ARCH is not specified and we couldn't guess it. Define MG_ARCH=... in mongoose_config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// http://esr.ibiblio.org/?p=5095
|
// http://esr.ibiblio.org/?p=5095
|
||||||
#define MG_BIG_ENDIAN (*(uint16_t *) "\0\xff" < 0x100)
|
#define MG_BIG_ENDIAN (*(uint16_t *) "\0\xff" < 0x100)
|
||||||
|
|
||||||
|
#include "arch_armgcc.h"
|
||||||
|
#include "arch_cube.h"
|
||||||
#include "arch_esp32.h"
|
#include "arch_esp32.h"
|
||||||
#include "arch_esp8266.h"
|
#include "arch_esp8266.h"
|
||||||
#include "arch_freertos.h"
|
#include "arch_freertos.h"
|
||||||
#include "arch_newlib.h"
|
|
||||||
#include "arch_rtx.h"
|
#include "arch_rtx.h"
|
||||||
|
#include "arch_threadx.h"
|
||||||
#include "arch_unix.h"
|
#include "arch_unix.h"
|
||||||
#include "arch_win32.h"
|
#include "arch_win32.h"
|
||||||
#include "arch_zephyr.h"
|
#include "arch_zephyr.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_NEWLIB
|
#if MG_ARCH == MG_ARCH_ARMGCC
|
||||||
#define _POSIX_TIMERS
|
#define _POSIX_TIMERS
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_AZURERTOS
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <fx_api.h>
|
|
||||||
#include <tx_api.h>
|
|
||||||
|
|
||||||
#include <nx_api.h>
|
|
||||||
#include <nx_bsd.h>
|
|
||||||
#include <nx_port.h>
|
|
||||||
#include <tx_port.h>
|
|
||||||
|
|
||||||
#define PATH_MAX FX_MAXIMUM_PATH
|
|
||||||
#define MG_DIRSEP '\\'
|
|
||||||
|
|
||||||
#define socklen_t int
|
|
||||||
#define closesocket(x) soc_close(x)
|
|
||||||
|
|
||||||
#undef FOPEN_MAX
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if MG_ARCH == MG_ARCH_CUBE
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Cube-generated header, includes ST Cube HAL
|
||||||
|
// NOTE: use angle brackets to prevent amalgamator ditching it
|
||||||
|
#include <main.h>
|
||||||
|
|
||||||
|
#ifndef MG_PATH_MAX
|
||||||
|
#define MG_PATH_MAX 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_DIRLIST
|
||||||
|
#define MG_ENABLE_DIRLIST 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_SOCKET
|
||||||
|
#define MG_ENABLE_SOCKET 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_TCPIP
|
||||||
|
#define MG_ENABLE_TCPIP 1 // Enable built-in TCP/IP stack
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MG_ENABLE_TCPIP && !defined(MG_ENABLE_DRIVER_STM32F) && !defined(MG_ENABLE_DRIVER_STM32H)
|
||||||
|
#if defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
|
||||||
|
#define MG_ENABLE_DRIVER_STM32F 1
|
||||||
|
#elif defined(STM32H5) || defined(STM32H7)
|
||||||
|
#define MG_ENABLE_DRIVER_STM32H 1
|
||||||
|
#else
|
||||||
|
#error Select a driver in mongoose_config.h
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_TLS
|
||||||
|
#define MG_TLS MG_TLS_BUILTIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MG_OTA) && defined(STM32F1) || defined(STM32F2) || defined(STM32F4) || defined(STM32F7)
|
||||||
|
#define MG_OTA MG_OTA_STM32F
|
||||||
|
#elif !defined(MG_OTA) && defined(STM32H5)
|
||||||
|
#define MG_OTA MG_OTA_STM32H5
|
||||||
|
#elif !defined(MG_OTA) && defined(STM32H7)
|
||||||
|
#define MG_OTA MG_OTA_STM32H7
|
||||||
|
#endif
|
||||||
|
// use HAL-defined execute-in-ram section
|
||||||
|
#define MG_IRAM __attribute__((section(".RamFunc")))
|
||||||
|
|
||||||
|
#ifndef HAL_ICACHE_MODULE_ENABLED
|
||||||
|
#define HAL_ICACHE_IsEnabled() 0
|
||||||
|
#define HAL_ICACHE_Enable() (void) 0
|
||||||
|
#define HAL_ICACHE_Disable() (void) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_SET_MAC_ADDRESS
|
||||||
|
// Construct MAC address from UUID
|
||||||
|
#define MGUID ((uint32_t *) UID_BASE) // Unique 96-bit chip ID
|
||||||
|
#define MG_SET_MAC_ADDRESS(mac) \
|
||||||
|
do { \
|
||||||
|
int icache_enabled_ = HAL_ICACHE_IsEnabled(); \
|
||||||
|
if (icache_enabled_) HAL_ICACHE_Disable(); \
|
||||||
|
mac[0] = 42; \
|
||||||
|
mac[1] = ((MGUID[0] >> 0) & 255) ^ ((MGUID[2] >> 19) & 255); \
|
||||||
|
mac[2] = ((MGUID[0] >> 10) & 255) ^ ((MGUID[1] >> 10) & 255); \
|
||||||
|
mac[3] = (MGUID[0] >> 19) & 255; \
|
||||||
|
mac[4] = ((MGUID[1] >> 0) & 255) ^ ((MGUID[2] >> 10) & 255); \
|
||||||
|
mac[5] = ((MGUID[2] >> 0) & 255) ^ ((MGUID[1] >> 19) & 255); \
|
||||||
|
if (icache_enabled_) HAL_ICACHE_Enable(); \
|
||||||
|
} while (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -22,4 +22,12 @@
|
|||||||
|
|
||||||
#define MG_PATH_MAX 128
|
#define MG_PATH_MAX 128
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_POSIX_FS
|
||||||
|
#define MG_ENABLE_POSIX_FS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_DIRLIST
|
||||||
|
#define MG_ENABLE_DIRLIST 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+9
-4
@@ -17,6 +17,7 @@
|
|||||||
#define mode_t size_t
|
#define mode_t size_t
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
|
||||||
#elif defined(__CCRH__)
|
#elif defined(__CCRH__)
|
||||||
#else
|
#else
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -25,10 +26,11 @@
|
|||||||
#include <FreeRTOS.h>
|
#include <FreeRTOS.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
|
|
||||||
#define calloc(a, b) mg_calloc(a, b)
|
#define MG_ENABLE_CUSTOM_CALLOC 1
|
||||||
#define free(a) vPortFree(a)
|
|
||||||
#define malloc(a) pvPortMalloc(a)
|
static inline void mg_free(void *ptr) {
|
||||||
#define strdup(s) ((char *) mg_strdup(mg_str(s)).buf)
|
vPortFree(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
// Re-route calloc/free to the FreeRTOS's functions, don't use stdlib
|
||||||
static inline void *mg_calloc(size_t cnt, size_t size) {
|
static inline void *mg_calloc(size_t cnt, size_t size) {
|
||||||
@@ -37,10 +39,13 @@ static inline void *mg_calloc(size_t cnt, size_t size) {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(MG_ENABLE_POSIX_FS) || !MG_ENABLE_POSIX_FS
|
||||||
|
#else
|
||||||
#define mkdir(a, b) mg_mkdir(a, b)
|
#define mkdir(a, b) mg_mkdir(a, b)
|
||||||
static inline int mg_mkdir(const char *path, mode_t mode) {
|
static inline int mg_mkdir(const char *path, mode_t mode) {
|
||||||
(void) path, (void) mode;
|
(void) path, (void) mode;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // MG_ARCH == MG_ARCH_FREERTOS
|
#endif // MG_ARCH == MG_ARCH_FREERTOS
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if MG_ARCH == MG_ARCH_THREADX
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Do not include time.h and stdlib.h, since they conflict with nxd_bsd.h
|
||||||
|
// extern time_t time(time_t *);
|
||||||
|
#include <nxd_bsd.h>
|
||||||
|
|
||||||
|
#define MG_DIRSEP '\\'
|
||||||
|
#undef FOPEN_MAX
|
||||||
|
|
||||||
|
#ifndef MG_PATH_MAX
|
||||||
|
#define MG_PATH_MAX 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_SOCK_LISTEN_BACKLOG_SIZE
|
||||||
|
#define MG_SOCK_LISTEN_BACKLOG_SIZE 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_IPV6
|
||||||
|
#define MG_ENABLE_IPV6 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define socklen_t int
|
||||||
|
#define closesocket(x) soc_close(x)
|
||||||
|
|
||||||
|
// In order to enable BSD support in NetxDuo, do the following (assuming Cube):
|
||||||
|
// 1. Add nxd_bsd.h and nxd_bsd.c to the repo:
|
||||||
|
// https://github.com/eclipse-threadx/netxduo/blob/v6.1.12_rel/addons/BSD/nxd_bsd.c
|
||||||
|
// https://github.com/eclipse-threadx/netxduo/blob/v6.1.12_rel/addons/BSD/nxd_bsd.h
|
||||||
|
// 2. Add to tx_user.h
|
||||||
|
// #define TX_THREAD_USER_EXTENSION int bsd_errno;
|
||||||
|
// 3. Add to nx_user.h
|
||||||
|
// #define NX_ENABLE_EXTENDED_NOTIFY_SUPPORT
|
||||||
|
// 4. Add __CCRX__ build preprocessor constant
|
||||||
|
// Project -> Properties -> C/C++ -> Settings -> MCU Compiler -> Preprocessor
|
||||||
|
|
||||||
|
#endif
|
||||||
+55
-11
@@ -2,10 +2,33 @@
|
|||||||
|
|
||||||
#if MG_ARCH == MG_ARCH_WIN32
|
#if MG_ARCH == MG_ARCH_WIN32
|
||||||
|
|
||||||
|
// Avoid name clashing; (macro expansion producing 'defined' has undefined
|
||||||
|
// behaviour). See config.h for user options
|
||||||
|
#ifndef MG_ENABLE_WINSOCK
|
||||||
|
#if (!defined(MG_ENABLE_TCPIP) || !MG_ENABLE_TCPIP) && \
|
||||||
|
(!defined(MG_ENABLE_LWIP) || !MG_ENABLE_LWIP) && \
|
||||||
|
(!defined(MG_ENABLE_FREERTOS_TCP) || !MG_ENABLE_FREERTOS_TCP)
|
||||||
|
#define MG_ENABLE_WINSOCK 1
|
||||||
|
#else
|
||||||
|
#define MG_ENABLE_WINSOCK 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _CRT_RAND_S
|
#ifndef _CRT_RAND_S
|
||||||
#define _CRT_RAND_S
|
#define _CRT_RAND_S
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef _WIN32_WINNT
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||||
|
#define _WIN32_WINNT 0x0400 // Let vc98 pick up wincrypt.h
|
||||||
|
#else
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef WINVER
|
||||||
|
#define WINVER _WIN32_WINNT
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
#endif
|
||||||
@@ -33,6 +56,8 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <winsock2.h> // fix missing macros and types
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||||
#define __func__ ""
|
#define __func__ ""
|
||||||
typedef __int64 int64_t;
|
typedef __int64 int64_t;
|
||||||
@@ -47,22 +72,34 @@ typedef enum { false = 0, true = 1 } bool;
|
|||||||
#else
|
#else
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#if MG_ENABLE_WINSOCK
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
#include <winerror.h>
|
#include <winerror.h>
|
||||||
#include <winsock2.h>
|
|
||||||
|
|
||||||
// For mg_random()
|
// For mg_random()
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1700
|
#if defined(_MSC_VER) && _MSC_VER < 1700
|
||||||
#ifndef _WIN32_WINNT
|
|
||||||
#define _WIN32_WINNT 0x400 // Let vc98 pick up wincrypt.h
|
|
||||||
#endif
|
|
||||||
#include <wincrypt.h>
|
#include <wincrypt.h>
|
||||||
#pragma comment(lib, "advapi32.lib")
|
#pragma comment(lib, "advapi32.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER <= 1200
|
||||||
|
#ifndef IPPROTO_IP
|
||||||
|
#define IPPROTO_IP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IP_ADD_MEMBERSHIP
|
||||||
|
struct ip_mreq {
|
||||||
|
struct in_addr imr_multiaddr;
|
||||||
|
struct in_addr imr_interface;
|
||||||
|
};
|
||||||
|
#define IP_ADD_MEMBERSHIP 12
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Protect from calls like std::snprintf in app code
|
// Protect from calls like std::snprintf in app code
|
||||||
// See https://github.com/cesanta/mongoose/issues/1047
|
// See https://github.com/cesanta/mongoose/issues/1047
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
@@ -73,25 +110,30 @@ typedef enum { false = 0, true = 1 } bool;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MG_INVALID_SOCKET INVALID_SOCKET
|
|
||||||
#define MG_SOCKET_TYPE SOCKET
|
|
||||||
typedef unsigned long nfds_t;
|
typedef unsigned long nfds_t;
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
#if MG_ENABLE_WINSOCK
|
||||||
#pragma comment(lib, "ws2_32.lib")
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
|
#endif
|
||||||
#ifndef alloca
|
#ifndef alloca
|
||||||
#define alloca(a) _alloca(a)
|
#define alloca(a) _alloca(a)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#define poll(a, b, c) WSAPoll((a), (b), (c))
|
|
||||||
#define closesocket(x) closesocket(x)
|
|
||||||
|
|
||||||
typedef int socklen_t;
|
|
||||||
#define MG_DIRSEP '\\'
|
#define MG_DIRSEP '\\'
|
||||||
|
|
||||||
#ifndef MG_PATH_MAX
|
#ifndef MG_PATH_MAX
|
||||||
#define MG_PATH_MAX FILENAME_MAX
|
#define MG_PATH_MAX FILENAME_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MG_ENABLE_WINSOCK
|
||||||
|
|
||||||
|
#define MG_INVALID_SOCKET INVALID_SOCKET
|
||||||
|
#define MG_SOCKET_TYPE SOCKET
|
||||||
|
#define poll(a, b, c) WSAPoll((a), (b), (c))
|
||||||
|
#define closesocket(x) closesocket(x)
|
||||||
|
typedef int socklen_t;
|
||||||
|
|
||||||
#ifndef SO_EXCLUSIVEADDRUSE
|
#ifndef SO_EXCLUSIVEADDRUSE
|
||||||
#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
|
#define SO_EXCLUSIVEADDRUSE ((int) (~SO_REUSEADDR))
|
||||||
#endif
|
#endif
|
||||||
@@ -106,13 +148,15 @@ typedef int socklen_t;
|
|||||||
#define MG_SOCK_RESET(errcode) \
|
#define MG_SOCK_RESET(errcode) \
|
||||||
(((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET))
|
(((errcode) < 0) && (WSAGetLastError() == WSAECONNRESET))
|
||||||
|
|
||||||
|
#endif // MG_ENABLE_WINSOCK
|
||||||
|
|
||||||
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
#define realpath(a, b) _fullpath((b), (a), MG_PATH_MAX)
|
||||||
#define sleep(x) Sleep((x) * 1000)
|
#define sleep(x) Sleep((x) *1000)
|
||||||
#define mkdir(a, b) _mkdir(a)
|
#define mkdir(a, b) _mkdir(a)
|
||||||
#define timegm(x) _mkgmtime(x)
|
#define timegm(x) _mkgmtime(x)
|
||||||
|
|
||||||
#ifndef S_ISDIR
|
#ifndef S_ISDIR
|
||||||
#define S_ISDIR(x) (((x) & _S_IFMT) == _S_IFDIR)
|
#define S_ISDIR(x) (((x) &_S_IFMT) == _S_IFDIR)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_ENABLE_DIRLIST
|
#ifndef MG_ENABLE_DIRLIST
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#if MG_ARCH == MG_ARCH_ZEPHYR
|
#if MG_ARCH == MG_ARCH_ZEPHYR
|
||||||
|
|
||||||
#include <zephyr/kernel.h>
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/version.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
+36
-3
@@ -4,6 +4,10 @@
|
|||||||
#define MG_ENABLE_LOG 1
|
#define MG_ENABLE_LOG 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_CUSTOM_CALLOC
|
||||||
|
#define MG_ENABLE_CUSTOM_CALLOC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MG_ENABLE_CUSTOM_LOG
|
#ifndef MG_ENABLE_CUSTOM_LOG
|
||||||
#define MG_ENABLE_CUSTOM_LOG 0 // Let user define their own MG_LOG
|
#define MG_ENABLE_CUSTOM_LOG 0 // Let user define their own MG_LOG
|
||||||
#endif
|
#endif
|
||||||
@@ -56,7 +60,8 @@
|
|||||||
#define MG_ENABLE_MD5 1
|
#define MG_ENABLE_MD5 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with external IP stack (like LWIP)
|
// Set MG_ENABLE_WINSOCK=0 for Win32 builds with other external IP stack not
|
||||||
|
// mentioned in arch_win32.h
|
||||||
#ifndef MG_ENABLE_WINSOCK
|
#ifndef MG_ENABLE_WINSOCK
|
||||||
#define MG_ENABLE_WINSOCK 1
|
#define MG_ENABLE_WINSOCK 1
|
||||||
#endif
|
#endif
|
||||||
@@ -170,14 +175,42 @@
|
|||||||
#define MG_TCPIP_GW MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP)
|
#define MG_TCPIP_GW MG_IPV4(0, 0, 0, 0) // Default is 0.0.0.0 (DHCP)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if MG_ENABLE_IPV6
|
||||||
|
|
||||||
|
#ifndef MG_TCPIP_GLOBAL
|
||||||
|
#define MG_TCPIP_GLOBAL MG_IPV6(0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_TCPIP_IPV6_LINKLOCAL
|
||||||
|
#define MG_TCPIP_IPV6_LINKLOCAL MG_IPV6(0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_TCPIP_PREFIX_LEN
|
||||||
|
#define MG_TCPIP_PREFIX_LEN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_TCPIP_GW6
|
||||||
|
#define MG_TCPIP_GW6 MG_IPV6(0, 0, 0, 0, 0, 0, 0, 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef MG_SET_MAC_ADDRESS
|
#ifndef MG_SET_MAC_ADDRESS
|
||||||
#define MG_SET_MAC_ADDRESS(mac)
|
#define MG_SET_MAC_ADDRESS(mac)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_SET_WIFI_CREDS
|
#ifndef MG_TCPIP_DHCPNAME_SIZE
|
||||||
#define MG_SET_WIFI_CREDS(ssid, pass)
|
#define MG_TCPIP_DHCPNAME_SIZE 18 // struct mg_tcpip_if :: dhcp_name size
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_SET_WIFI_CONFIG
|
||||||
|
#define MG_SET_WIFI_CONFIG(data)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
|
#ifndef MG_ENABLE_TCPIP_PRINT_DEBUG_STATS
|
||||||
#define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
|
#define MG_ENABLE_TCPIP_PRINT_DEBUG_STATS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_ENABLE_CHACHA20
|
||||||
|
#define MG_ENABLE_CHACHA20 1 // When set to 0, GCM is used. For MG_TLS_BUILTIN
|
||||||
|
#endif
|
||||||
@@ -18,7 +18,7 @@ static void mg_sendnsreq(struct mg_connection *, struct mg_str *, int,
|
|||||||
|
|
||||||
static void mg_dns_free(struct dns_data **head, struct dns_data *d) {
|
static void mg_dns_free(struct dns_data **head, struct dns_data *d) {
|
||||||
LIST_DELETE(struct dns_data, head, d);
|
LIST_DELETE(struct dns_data, head, d);
|
||||||
free(d);
|
mg_free(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_resolve_cancel(struct mg_connection *c) {
|
void mg_resolve_cancel(struct mg_connection *c) {
|
||||||
@@ -100,6 +100,7 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
|||||||
const struct mg_dns_header *h = (struct mg_dns_header *) buf;
|
const struct mg_dns_header *h = (struct mg_dns_header *) buf;
|
||||||
struct mg_dns_rr rr;
|
struct mg_dns_rr rr;
|
||||||
size_t i, n, num_answers, ofs = sizeof(*h);
|
size_t i, n, num_answers, ofs = sizeof(*h);
|
||||||
|
bool is_response;
|
||||||
memset(dm, 0, sizeof(*dm));
|
memset(dm, 0, sizeof(*dm));
|
||||||
|
|
||||||
if (len < sizeof(*h)) return 0; // Too small, headers dont fit
|
if (len < sizeof(*h)) return 0; // Too small, headers dont fit
|
||||||
@@ -110,12 +111,22 @@ bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *dm) {
|
|||||||
num_answers = 10; // Sanity cap
|
num_answers = 10; // Sanity cap
|
||||||
}
|
}
|
||||||
dm->txnid = mg_ntohs(h->txnid);
|
dm->txnid = mg_ntohs(h->txnid);
|
||||||
|
is_response = mg_ntohs(h->flags) & 0x8000;
|
||||||
|
|
||||||
for (i = 0; i < mg_ntohs(h->num_questions); i++) {
|
for (i = 0; i < mg_ntohs(h->num_questions); i++) {
|
||||||
if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
|
if ((n = mg_dns_parse_rr(buf, len, ofs, true, &rr)) == 0) return false;
|
||||||
// MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
|
// MG_INFO(("Q %lu %lu %hu/%hu", ofs, n, rr.atype, rr.aclass));
|
||||||
|
mg_dns_parse_name(buf, len, ofs, dm->name, sizeof(dm->name));
|
||||||
ofs += n;
|
ofs += n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!is_response) {
|
||||||
|
// For queries, there is no need to parse the answers. In this way,
|
||||||
|
// we also ensure the domain name (dm->name) is parsed from
|
||||||
|
// the question field.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_answers; i++) {
|
for (i = 0; i < num_answers; i++) {
|
||||||
if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
|
if ((n = mg_dns_parse_rr(buf, len, ofs, false, &rr)) == 0) return false;
|
||||||
// MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
|
// MG_INFO(("A -- %lu %lu %hu/%hu %s", ofs, n, rr.atype, rr.aclass,
|
||||||
@@ -221,21 +232,26 @@ static bool mg_dns_send(struct mg_connection *c, const struct mg_str *name,
|
|||||||
return mg_send(c, &pkt, sizeof(pkt.header) + n);
|
return mg_send(c, &pkt, sizeof(pkt.header) + n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc);
|
||||||
|
bool mg_dnsc_init(struct mg_mgr *mgr, struct mg_dns *dnsc) {
|
||||||
|
if (dnsc->url == NULL) {
|
||||||
|
mg_error(0, "DNS server URL is NULL. Call mg_mgr_init()");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (dnsc->c == NULL) {
|
||||||
|
dnsc->c = mg_connect(mgr, dnsc->url, NULL, NULL);
|
||||||
|
if (dnsc->c == NULL) return false;
|
||||||
|
dnsc->c->pfn = dns_cb;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
|
static void mg_sendnsreq(struct mg_connection *c, struct mg_str *name, int ms,
|
||||||
struct mg_dns *dnsc, bool ipv6) {
|
struct mg_dns *dnsc, bool ipv6) {
|
||||||
struct dns_data *d = NULL;
|
struct dns_data *d = NULL;
|
||||||
if (dnsc->url == NULL) {
|
if (!mg_dnsc_init(c->mgr, dnsc)) {
|
||||||
mg_error(c, "DNS server URL is NULL. Call mg_mgr_init()");
|
|
||||||
} else if (dnsc->c == NULL) {
|
|
||||||
dnsc->c = mg_connect(c->mgr, dnsc->url, NULL, NULL);
|
|
||||||
if (dnsc->c != NULL) {
|
|
||||||
dnsc->c->pfn = dns_cb;
|
|
||||||
// dnsc->c->is_hexdumping = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dnsc->c == NULL) {
|
|
||||||
mg_error(c, "resolver");
|
mg_error(c, "resolver");
|
||||||
} else if ((d = (struct dns_data *) calloc(1, sizeof(*d))) == NULL) {
|
} else if ((d = (struct dns_data *) mg_calloc(1, sizeof(*d))) == NULL) {
|
||||||
mg_error(c, "resolve OOM");
|
mg_error(c, "resolve OOM");
|
||||||
} else {
|
} else {
|
||||||
struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
|
struct dns_data *reqs = (struct dns_data *) c->mgr->active_dns_requests;
|
||||||
@@ -265,3 +281,73 @@ void mg_resolve(struct mg_connection *c, const char *url) {
|
|||||||
mg_sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
|
mg_sendnsreq(c, &host, c->mgr->dnstimeout, dns, c->mgr->use_dns6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const uint8_t mdns_answer[] = {
|
||||||
|
0, 1, // 2 bytes - record type, A
|
||||||
|
0, 1, // 2 bytes - address class, INET
|
||||||
|
0, 0, 0, 120, // 4 bytes - TTL
|
||||||
|
0, 4 // 2 bytes - address length
|
||||||
|
};
|
||||||
|
|
||||||
|
static void mdns_cb(struct mg_connection *c, int ev, void *ev_data) {
|
||||||
|
if (ev == MG_EV_READ) {
|
||||||
|
struct mg_dns_header *qh = (struct mg_dns_header *) c->recv.buf;
|
||||||
|
if (c->recv.len > 12 && (qh->flags & mg_htons(0xF800)) == 0) {
|
||||||
|
// flags -> !resp, opcode=0 => query; ignore other opcodes and responses
|
||||||
|
struct mg_dns_rr rr; // Parse first question, offset 12 is header size
|
||||||
|
size_t n = mg_dns_parse_rr(c->recv.buf, c->recv.len, 12, true, &rr);
|
||||||
|
MG_VERBOSE(("mDNS request parsed, result=%d", (int) n));
|
||||||
|
if (n > 0) {
|
||||||
|
// RFC-6762 Appendix C, RFC2181 11: m(n + 1-63), max 255 + 0x0
|
||||||
|
// buf and h declared here to ease future expansion to DNS-SD
|
||||||
|
uint8_t buf[sizeof(struct mg_dns_header) + 256 + sizeof(mdns_answer) + 4];
|
||||||
|
struct mg_dns_header *h = (struct mg_dns_header *) buf;
|
||||||
|
char local_name[63 + 7]; // name label + '.' + local label + '\0'
|
||||||
|
uint8_t name_len = (uint8_t) strlen((char *)c->fn_data);
|
||||||
|
struct mg_dns_message dm;
|
||||||
|
bool unicast = (rr.aclass & MG_BIT(15)) != 0; // QU
|
||||||
|
// uint16_t q = mg_ntohs(qh->num_questions);
|
||||||
|
rr.aclass &= (uint16_t) ~MG_BIT(15); // remove "QU" (unicast response)
|
||||||
|
qh->num_questions = mg_htons(1); // parser sanity
|
||||||
|
mg_dns_parse(c->recv.buf, c->recv.len, &dm);
|
||||||
|
if (name_len > (sizeof(local_name) - 7)) // leave room for .local\0
|
||||||
|
name_len = sizeof(local_name) - 7;
|
||||||
|
memcpy(local_name, c->fn_data, name_len);
|
||||||
|
strcpy(local_name + name_len, ".local"); // ensure proper name.local\0
|
||||||
|
if (strcmp(local_name, dm.name) == 0) {
|
||||||
|
uint8_t *p = &buf[sizeof(*h)];
|
||||||
|
memset(h, 0, sizeof(*h)); // clear header
|
||||||
|
h->txnid = unicast ? qh->txnid : 0; // RFC-6762 18.1
|
||||||
|
// RFC-6762 6: 0 questions, 1 Answer, 0 Auth, 0 Additional RRs
|
||||||
|
h->num_answers = mg_htons(1); // only one answer
|
||||||
|
h->flags = mg_htons(0x8400); // Authoritative response
|
||||||
|
*p++ = name_len; // label 1
|
||||||
|
memcpy(p, c->fn_data, name_len), p += name_len;
|
||||||
|
*p++ = 5; // label 2
|
||||||
|
memcpy(p, "local", 5), p += 5;
|
||||||
|
*p++ = 0; // no more labels
|
||||||
|
memcpy(p, mdns_answer, sizeof(mdns_answer)), p += sizeof(mdns_answer);
|
||||||
|
#if MG_ENABLE_TCPIP
|
||||||
|
memcpy(p, &c->mgr->ifp->ip, 4), p += 4;
|
||||||
|
#else
|
||||||
|
memcpy(p, c->data, 4), p += 4;
|
||||||
|
#endif
|
||||||
|
if (!unicast) memcpy(&c->rem, &c->loc, sizeof(c->rem));
|
||||||
|
mg_send(c, buf, (size_t)(p - buf)); // And send it!
|
||||||
|
MG_DEBUG(("mDNS %c response sent", unicast ? 'U' : 'M'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mg_iobuf_del(&c->recv, 0, c->recv.len);
|
||||||
|
}
|
||||||
|
(void) ev_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mg_multicast_add(struct mg_connection *c, char *ip);
|
||||||
|
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name) {
|
||||||
|
struct mg_connection *c =
|
||||||
|
mg_listen(mgr, "udp://224.0.0.251:5353", mdns_cb, name);
|
||||||
|
if (c != NULL) mg_multicast_add(c, (char *)"224.0.0.251");
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -36,3 +36,5 @@ void mg_resolve_cancel(struct mg_connection *);
|
|||||||
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
bool mg_dns_parse(const uint8_t *buf, size_t len, struct mg_dns_message *);
|
||||||
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
size_t mg_dns_parse_rr(const uint8_t *buf, size_t len, size_t ofs,
|
||||||
bool is_question, struct mg_dns_rr *);
|
bool is_question, struct mg_dns_rr *);
|
||||||
|
|
||||||
|
struct mg_connection *mg_mdns_listen(struct mg_mgr *mgr, char *name);
|
||||||
+17
-3
@@ -13,12 +13,12 @@ static struct mg_tcpip_if *s_ifp;
|
|||||||
|
|
||||||
static void mac_cb(uint32_t);
|
static void mac_cb(uint32_t);
|
||||||
static bool cmsis_init(struct mg_tcpip_if *);
|
static bool cmsis_init(struct mg_tcpip_if *);
|
||||||
static bool cmsis_up(struct mg_tcpip_if *);
|
static bool cmsis_poll(struct mg_tcpip_if *, bool);
|
||||||
static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *);
|
static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *);
|
||||||
static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *);
|
static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *);
|
||||||
|
|
||||||
struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL,
|
struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL,
|
||||||
cmsis_up};
|
cmsis_poll};
|
||||||
|
|
||||||
static bool cmsis_init(struct mg_tcpip_if *ifp) {
|
static bool cmsis_init(struct mg_tcpip_if *ifp) {
|
||||||
ARM_ETH_MAC_ADDR addr;
|
ARM_ETH_MAC_ADDR addr;
|
||||||
@@ -56,7 +56,21 @@ static size_t cmsis_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cmsis_up(struct mg_tcpip_if *ifp) {
|
static void cmsis_update_hash_table(struct mg_tcpip_if *ifp) {
|
||||||
|
// TODO(): read database, rebuild hash table
|
||||||
|
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||||
|
ARM_ETH_MAC_ADDR addr;
|
||||||
|
memcpy(&addr, mcast_addr, sizeof(addr));
|
||||||
|
mac->SetAddressFilter(&addr, 1);
|
||||||
|
(void) ifp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool cmsis_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
|
if (ifp->update_mac_hash_table) {
|
||||||
|
cmsis_update_hash_table(ifp);
|
||||||
|
ifp->update_mac_hash_table = false;
|
||||||
|
}
|
||||||
|
if (!s1) return false;
|
||||||
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
||||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||||
bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state
|
bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state
|
||||||
|
|||||||
+1415
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
((defined(MG_ENABLE_DRIVER_CYW) && MG_ENABLE_DRIVER_CYW) || \
|
||||||
|
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO))
|
||||||
|
|
||||||
|
struct mg_tcpip_spi_ {
|
||||||
|
void *spi; // Opaque SPI bus descriptor
|
||||||
|
void (*begin)(void *); // SPI begin: slave select low
|
||||||
|
void (*end)(void *); // SPI end: slave select high
|
||||||
|
void (*txn)(void *, uint8_t *, uint8_t *,
|
||||||
|
size_t len); // SPI transaction: write-read len bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mg_tcpip_driver_cyw_firmware {
|
||||||
|
const uint8_t *code_addr;
|
||||||
|
size_t code_len;
|
||||||
|
const uint8_t *nvram_addr;
|
||||||
|
size_t nvram_len;
|
||||||
|
const uint8_t *clm_addr;
|
||||||
|
size_t clm_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mg_tcpip_driver_cyw_data {
|
||||||
|
struct mg_wifi_data wifi;
|
||||||
|
void *bus;
|
||||||
|
struct mg_tcpip_driver_cyw_firmware *fw;
|
||||||
|
bool hs; // use chip "high-speed" mode; otherwise SPI CPOL0 CPHA0 (DS 4.2.3 Table 6)
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||||
|
do { \
|
||||||
|
static struct mg_tcpip_driver_cyw_data driver_data_; \
|
||||||
|
static struct mg_tcpip_if mif_; \
|
||||||
|
MG_SET_WIFI_CONFIG(&driver_data_); \
|
||||||
|
mif_.ip = MG_TCPIP_IP; \
|
||||||
|
mif_.mask = MG_TCPIP_MASK; \
|
||||||
|
mif_.gw = MG_TCPIP_GW; \
|
||||||
|
mif_.driver = &mg_tcpip_driver_cyw; \
|
||||||
|
mif_.driver_data = &driver_data_; \
|
||||||
|
mif_.recv_queue.size = 8192; \
|
||||||
|
mif_.mac[0] = 2; /* MAC read from OTP at driver init */ \
|
||||||
|
mg_tcpip_init(mgr, &mif_); \
|
||||||
|
MG_INFO(("Driver: cyw, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
+43
-13
@@ -1,6 +1,9 @@
|
|||||||
#include "net_builtin.h"
|
#include "net_builtin.h"
|
||||||
|
|
||||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
(defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10) || \
|
||||||
|
(defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11) || \
|
||||||
|
(defined(MG_ENABLE_DRIVER_MCXE) && MG_ENABLE_DRIVER_MCXE)
|
||||||
struct imxrt_enet {
|
struct imxrt_enet {
|
||||||
volatile uint32_t RESERVED0, EIR, EIMR, RESERVED1, RDAR, TDAR, RESERVED2[3],
|
volatile uint32_t RESERVED0, EIR, EIMR, RESERVED1, RDAR, TDAR, RESERVED2[3],
|
||||||
ECR, RESERVED3[6], MMFR, MSCR, RESERVED4[7], MIBC, RESERVED5[7], RCR,
|
ECR, RESERVED3[6], MMFR, MSCR, RESERVED4[7], MIBC, RESERVED5[7], RCR,
|
||||||
@@ -26,12 +29,15 @@ struct imxrt_enet {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#undef ENET
|
#undef ENET
|
||||||
#if defined(MG_DRIVER_IMXRT_RT11) && MG_DRIVER_IMXRT_RT11
|
#if defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11
|
||||||
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x40424000U)
|
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x40424000U)
|
||||||
#define ETH_DESC_CNT 5 // Descriptors count
|
#define ETH_DESC_CNT 5 // Descriptors count
|
||||||
#else
|
#elif defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10
|
||||||
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x402D8000U)
|
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x402D8000U)
|
||||||
#define ETH_DESC_CNT 4 // Descriptors count
|
#define ETH_DESC_CNT 4 // Descriptors count
|
||||||
|
#else // MG_ENABLE_DRIVER_MCXE
|
||||||
|
#define ENET ((struct imxrt_enet *) (uintptr_t) 0x40079000U)
|
||||||
|
#define ETH_DESC_CNT 4 // Descriptor count
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ETH_PKT_SIZE 1536 // Max frame size, 64-bit aligned
|
#define ETH_PKT_SIZE 1536 // Max frame size, 64-bit aligned
|
||||||
@@ -42,15 +48,12 @@ struct enet_desc {
|
|||||||
uint32_t *buffer; // Data ptr
|
uint32_t *buffer; // Data ptr
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
|
|
||||||
#define MG_64BYTE_ALIGNED __attribute__((aligned((64U))))
|
|
||||||
|
|
||||||
// Descriptors: in non-cached area (TODO(scaprile)), (37.5.1.22.2 37.5.1.23.2)
|
// Descriptors: in non-cached area (TODO(scaprile)), (37.5.1.22.2 37.5.1.23.2)
|
||||||
// Buffers: 64-byte aligned (37.3.14)
|
// Buffers: 64-byte aligned (37.3.14)
|
||||||
static volatile struct enet_desc s_rxdesc[ETH_DESC_CNT] MG_64BYTE_ALIGNED;
|
static volatile struct enet_desc s_rxdesc[ETH_DESC_CNT] MG_ETH_RAM MG_64BYTE_ALIGNED;
|
||||||
static volatile struct enet_desc s_txdesc[ETH_DESC_CNT] MG_64BYTE_ALIGNED;
|
static volatile struct enet_desc s_txdesc[ETH_DESC_CNT] MG_ETH_RAM MG_64BYTE_ALIGNED;
|
||||||
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_64BYTE_ALIGNED;
|
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_64BYTE_ALIGNED;
|
||||||
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_64BYTE_ALIGNED;
|
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_64BYTE_ALIGNED;
|
||||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||||
|
|
||||||
static uint16_t enet_read_phy(uint8_t addr, uint8_t reg) {
|
static uint16_t enet_read_phy(uint8_t addr, uint8_t reg) {
|
||||||
@@ -115,9 +118,14 @@ static bool mg_tcpip_driver_imxrt_init(struct mg_tcpip_if *ifp) {
|
|||||||
ENET->RDAR = MG_BIT(24); // Receive Descriptors have changed
|
ENET->RDAR = MG_BIT(24); // Receive Descriptors have changed
|
||||||
ENET->TDAR = MG_BIT(24); // Transmit Descriptors have changed
|
ENET->TDAR = MG_BIT(24); // Transmit Descriptors have changed
|
||||||
// ENET->OPD = 0x10014;
|
// ENET->OPD = 0x10014;
|
||||||
|
ENET->IAUR = 0;
|
||||||
|
ENET->IALR = 0;
|
||||||
|
ENET->GAUR = 0;
|
||||||
|
ENET->GALR = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Transmit frame
|
// Transmit frame
|
||||||
static size_t mg_tcpip_driver_imxrt_tx(const void *buf, size_t len,
|
static size_t mg_tcpip_driver_imxrt_tx(const void *buf, size_t len,
|
||||||
struct mg_tcpip_if *ifp) {
|
struct mg_tcpip_if *ifp) {
|
||||||
@@ -142,7 +150,24 @@ static size_t mg_tcpip_driver_imxrt_tx(const void *buf, size_t len,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_tcpip_driver_imxrt_up(struct mg_tcpip_if *ifp) {
|
static void mg_tcpip_driver_imxrt_update_hash_table(struct mg_tcpip_if *ifp) {
|
||||||
|
// TODO(): read database, rebuild hash table
|
||||||
|
// RM 37.3.4.3.2
|
||||||
|
uint32_t hash_table[2] = {0, 0};
|
||||||
|
// uint8_t hash64 = ((~mg_crc32(0, mcast_addr, 6)) >> 26) & 0x3f;
|
||||||
|
// hash_table[((uint8_t)hash64) >> 5] |= (1 << (hash64 & 0x1f));
|
||||||
|
hash_table[1] = MG_BIT(1); // above reduces to this for mDNS addr
|
||||||
|
ENET->GAUR = hash_table[1];
|
||||||
|
ENET->GALR = hash_table[0];
|
||||||
|
(void) ifp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mg_tcpip_driver_imxrt_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
|
if (ifp->update_mac_hash_table) {
|
||||||
|
mg_tcpip_driver_imxrt_update_hash_table(ifp);
|
||||||
|
ifp->update_mac_hash_table = false;
|
||||||
|
}
|
||||||
|
if (!s1) return false;
|
||||||
struct mg_tcpip_driver_imxrt_data *d =
|
struct mg_tcpip_driver_imxrt_data *d =
|
||||||
(struct mg_tcpip_driver_imxrt_data *) ifp->driver_data;
|
(struct mg_tcpip_driver_imxrt_data *) ifp->driver_data;
|
||||||
uint8_t speed = MG_PHY_SPEED_10M;
|
uint8_t speed = MG_PHY_SPEED_10M;
|
||||||
@@ -165,9 +190,14 @@ static bool mg_tcpip_driver_imxrt_up(struct mg_tcpip_if *ifp) {
|
|||||||
return up;
|
return up;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ENET_IRQHandler(void);
|
|
||||||
static uint32_t s_rxno;
|
static uint32_t s_rxno;
|
||||||
|
#if !defined(MG_ENABLE_DRIVER_MCXE)
|
||||||
|
void ENET_IRQHandler(void);
|
||||||
void ENET_IRQHandler(void) {
|
void ENET_IRQHandler(void) {
|
||||||
|
#else
|
||||||
|
void ENET_Receive_IRQHandler(void);
|
||||||
|
void ENET_Receive_IRQHandler(void) {
|
||||||
|
#endif
|
||||||
ENET->EIR = MG_BIT(25); // Ack IRQ
|
ENET->EIR = MG_BIT(25); // Ack IRQ
|
||||||
// Frame received, loop
|
// Frame received, loop
|
||||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||||
@@ -188,6 +218,6 @@ void ENET_IRQHandler(void) {
|
|||||||
|
|
||||||
struct mg_tcpip_driver mg_tcpip_driver_imxrt = {mg_tcpip_driver_imxrt_init,
|
struct mg_tcpip_driver mg_tcpip_driver_imxrt = {mg_tcpip_driver_imxrt_init,
|
||||||
mg_tcpip_driver_imxrt_tx, NULL,
|
mg_tcpip_driver_imxrt_tx, NULL,
|
||||||
mg_tcpip_driver_imxrt_up};
|
mg_tcpip_driver_imxrt_poll};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+4
-1
@@ -1,6 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_IMXRT) && MG_ENABLE_DRIVER_IMXRT
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
(defined(MG_ENABLE_DRIVER_IMXRT10) && MG_ENABLE_DRIVER_IMXRT10) || \
|
||||||
|
(defined(MG_ENABLE_DRIVER_IMXRT11) && MG_ENABLE_DRIVER_IMXRT11) || \
|
||||||
|
(defined(MG_ENABLE_DRIVER_MCXE) && MG_ENABLE_DRIVER_MCXE)
|
||||||
|
|
||||||
struct mg_tcpip_driver_imxrt_data {
|
struct mg_tcpip_driver_imxrt_data {
|
||||||
// MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
|
// MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_NXP_WIFI) && \
|
||||||
|
MG_ENABLE_DRIVER_NXP_WIFI
|
||||||
|
|
||||||
|
#include "drivers/nxp_wifi.h"
|
||||||
|
|
||||||
|
bool __attribute__((weak)) netif_init(struct mg_tcpip_if *ifp) {
|
||||||
|
(void) ifp;
|
||||||
|
MG_ERROR(("Please link wifi/port/net contents"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size_t __attribute__((weak))
|
||||||
|
netif_tx(const void *bfr, size_t len, struct mg_tcpip_if *ifp) {
|
||||||
|
(void) bfr;
|
||||||
|
(void) len;
|
||||||
|
netif_init(ifp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool __attribute__((weak)) netif_connect(struct mg_wifi_data *wifi) {
|
||||||
|
(void) wifi;
|
||||||
|
return netif_init(NULL);
|
||||||
|
}
|
||||||
|
bool __attribute__((weak))
|
||||||
|
netif_poll(struct mg_tcpip_if *ifp, bool s1, mg_tcpip_event_handler_t evcb) {
|
||||||
|
(void) ifp;
|
||||||
|
(void) s1;
|
||||||
|
(void) evcb;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mg_tcpip_if *s_ifp;
|
||||||
|
static uint32_t s_ip, s_mask;
|
||||||
|
|
||||||
|
static void wifi_cb(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
|
||||||
|
struct mg_wifi_data *wifi =
|
||||||
|
&((struct mg_tcpip_driver_nxp_wifi_data *) ifp->driver_data)->wifi;
|
||||||
|
if (wifi->apmode && ev == MG_TCPIP_EV_ST_CHG &&
|
||||||
|
*(uint8_t *) ev_data == MG_TCPIP_STATE_UP) {
|
||||||
|
MG_DEBUG(("Access Point started"));
|
||||||
|
s_ip = ifp->ip, ifp->ip = wifi->apip;
|
||||||
|
s_mask = ifp->mask, ifp->mask = wifi->apmask;
|
||||||
|
ifp->enable_dhcp_client = false;
|
||||||
|
ifp->enable_dhcp_server = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool nxp_wifi_init(struct mg_tcpip_if *ifp) {
|
||||||
|
struct mg_wifi_data *wifi =
|
||||||
|
&((struct mg_tcpip_driver_nxp_wifi_data *) ifp->driver_data)->wifi;
|
||||||
|
s_ifp = ifp;
|
||||||
|
s_ip = ifp->ip;
|
||||||
|
s_mask = ifp->mask;
|
||||||
|
ifp->pfn = wifi_cb;
|
||||||
|
if (!netif_init(ifp)) return false;
|
||||||
|
if (wifi->apmode) {
|
||||||
|
return mg_wifi_ap_start(wifi);
|
||||||
|
} else if (wifi->ssid != NULL && wifi->pass != NULL) {
|
||||||
|
return mg_wifi_connect(wifi);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nxp_wifi_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
|
return netif_poll(ifp, s1, mg_tcpip_call);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct mg_tcpip_driver mg_tcpip_driver_nxp_wifi = {nxp_wifi_init, netif_tx,
|
||||||
|
NULL, nxp_wifi_poll};
|
||||||
|
|
||||||
|
bool mg_wifi_connect(struct mg_wifi_data *wifi) {
|
||||||
|
s_ifp->ip = s_ip;
|
||||||
|
s_ifp->mask = s_mask;
|
||||||
|
if (s_ifp->ip == 0) s_ifp->enable_dhcp_client = true;
|
||||||
|
s_ifp->enable_dhcp_server = false;
|
||||||
|
return netif_connect(wifi);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __attribute__((weak)) mg_wifi_scan(void) {
|
||||||
|
return netif_init(NULL);
|
||||||
|
}
|
||||||
|
bool __attribute__((weak)) mg_wifi_disconnect(void) {
|
||||||
|
return netif_init(NULL);
|
||||||
|
}
|
||||||
|
bool __attribute__((weak)) mg_wifi_ap_start(struct mg_wifi_data *wifi) {
|
||||||
|
(void) wifi;
|
||||||
|
return netif_init(NULL);
|
||||||
|
}
|
||||||
|
bool __attribute__((weak)) mg_wifi_ap_stop(void) {
|
||||||
|
return netif_init(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
defined(MG_ENABLE_DRIVER_NXP_WIFI) && MG_ENABLE_DRIVER_NXP_WIFI
|
||||||
|
|
||||||
|
|
||||||
|
struct mg_tcpip_driver_nxp_wifi_data {
|
||||||
|
struct mg_wifi_data wifi;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||||
|
do { \
|
||||||
|
static struct mg_tcpip_driver_nxp_wifi_data driver_data_; \
|
||||||
|
static struct mg_tcpip_if mif_; \
|
||||||
|
MG_SET_WIFI_CONFIG(&driver_data_); \
|
||||||
|
mif_.ip = MG_TCPIP_IP; \
|
||||||
|
mif_.mask = MG_TCPIP_MASK; \
|
||||||
|
mif_.gw = MG_TCPIP_GW; \
|
||||||
|
mif_.driver = &mg_tcpip_driver_nxp_wifi; \
|
||||||
|
mif_.driver_data = &driver_data_; \
|
||||||
|
mif_.recv_queue.size = 8192; \
|
||||||
|
mif_.mac[0] = 2; /* MAC read from OTP at driver init */ \
|
||||||
|
mg_tcpip_init(mgr, &mif_); \
|
||||||
|
MG_INFO(("Driver: nxp wifi, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#endif
|
||||||
+20
-10
@@ -1,13 +1,15 @@
|
|||||||
#include "phy.h"
|
#include "phy.h"
|
||||||
|
|
||||||
enum { // ID1 ID2
|
enum { // ID1 ID2
|
||||||
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
|
MG_PHY_KSZ8x = 0x22, // 0022 1561 - KSZ8081RNB
|
||||||
MG_PHY_DP83x = 0x2000,
|
MG_PHY_DP83x = 0x2000,
|
||||||
MG_PHY_DP83867 = 0xa231, // 2000 a231 - TI DP83867I
|
MG_PHY_DP83867 = 0xa231, // 2000 a231 - TI DP83867I
|
||||||
MG_PHY_DP83825 = 0xa140, // 2000 a140 - TI DP83825I
|
MG_PHY_DP83825 = 0xa140, // 2000 a140 - TI DP83825I
|
||||||
MG_PHY_DP83848 = 0x5ca2, // 2000 5ca2 - TI DP83848I
|
MG_PHY_DP83848 = 0x5ca2, // 2000 5ca2 - TI DP83848I
|
||||||
MG_PHY_LAN87x = 0x7, // 0007 c0fx - LAN8720
|
MG_PHY_LAN87x = 0x7, // 0007 c0fx - LAN8720
|
||||||
MG_PHY_RTL8201 = 0x1C // 001c c816 - RTL8201
|
MG_PHY_RTL8201 = 0x1C, // 001c c816 - RTL8201,
|
||||||
|
MG_PHY_ICS1894x = 0x15,
|
||||||
|
MG_PHY_ICS189432 = 0xf450 // 0015 f450 - ICS1894
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -23,7 +25,8 @@ enum {
|
|||||||
MG_PHY_KSZ8x_REG_PC2R = 31,
|
MG_PHY_KSZ8x_REG_PC2R = 31,
|
||||||
MG_PHY_LAN87x_REG_SCSR = 31,
|
MG_PHY_LAN87x_REG_SCSR = 31,
|
||||||
MG_PHY_RTL8201_REG_RMSR = 16, // in page 7
|
MG_PHY_RTL8201_REG_RMSR = 16, // in page 7
|
||||||
MG_PHY_RTL8201_REG_PAGESEL = 31
|
MG_PHY_RTL8201_REG_PAGESEL = 31,
|
||||||
|
MG_PHY_ICS189432_REG_POLL = 17
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
|
static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
|
||||||
@@ -45,10 +48,11 @@ static const char *mg_phy_id_to_str(uint16_t id1, uint16_t id2) {
|
|||||||
return "LAN87x";
|
return "LAN87x";
|
||||||
case MG_PHY_RTL8201:
|
case MG_PHY_RTL8201:
|
||||||
return "RTL8201";
|
return "RTL8201";
|
||||||
|
case MG_PHY_ICS1894x:
|
||||||
|
return "ICS1894x";
|
||||||
default:
|
default:
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
(void) id2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
|
void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
|
||||||
@@ -77,11 +81,13 @@ void mg_phy_init(struct mg_phy *phy, uint8_t phy_addr, uint8_t config) {
|
|||||||
phy->write_reg(phy_addr, MG_PHY_DP83x_REG_RCSR, MG_BIT(7) | MG_BIT(0));
|
phy->write_reg(phy_addr, MG_PHY_DP83x_REG_RCSR, MG_BIT(7) | MG_BIT(0));
|
||||||
} else if (id1 == MG_PHY_KSZ8x) {
|
} else if (id1 == MG_PHY_KSZ8x) {
|
||||||
// Disable isolation (override hw, it doesn't make sense at this point)
|
// Disable isolation (override hw, it doesn't make sense at this point)
|
||||||
phy->write_reg( // #2848, some NXP boards set ISO, even though
|
// - #2848, some NXP boards set ISO, even though docs say they don't
|
||||||
phy_addr, MG_PHY_REG_BCR, // docs say they don't
|
phy->write_reg(phy_addr, MG_PHY_REG_BCR,
|
||||||
phy->read_reg(phy_addr, MG_PHY_REG_BCR) & (uint16_t) ~MG_BIT(10));
|
(uint16_t) (phy->read_reg(phy_addr, MG_PHY_REG_BCR) &
|
||||||
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R, // now do clock stuff
|
(uint16_t) ~MG_BIT(10)));
|
||||||
MG_BIT(15) | MG_BIT(8) | MG_BIT(7));
|
// now do clock stuff
|
||||||
|
phy->write_reg(phy_addr, MG_PHY_KSZ8x_REG_PC2R,
|
||||||
|
(uint16_t) (MG_BIT(15) | MG_BIT(8) | MG_BIT(7)));
|
||||||
} else if (id1 == MG_PHY_LAN87x) {
|
} else if (id1 == MG_PHY_LAN87x) {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
} else if (id1 == MG_PHY_RTL8201) {
|
} else if (id1 == MG_PHY_RTL8201) {
|
||||||
@@ -134,6 +140,10 @@ bool mg_phy_up(struct mg_phy *phy, uint8_t phy_addr, bool *full_duplex,
|
|||||||
uint16_t bcr = phy->read_reg(phy_addr, MG_PHY_REG_BCR);
|
uint16_t bcr = phy->read_reg(phy_addr, MG_PHY_REG_BCR);
|
||||||
*full_duplex = bcr & MG_BIT(8);
|
*full_duplex = bcr & MG_BIT(8);
|
||||||
*speed = (bcr & MG_BIT(13)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
|
*speed = (bcr & MG_BIT(13)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
|
||||||
|
} else if (id1 == MG_PHY_ICS1894x) {
|
||||||
|
uint16_t poll_reg = phy->read_reg(phy_addr, MG_PHY_ICS189432_REG_POLL);
|
||||||
|
*full_duplex = poll_reg & MG_BIT(14);
|
||||||
|
*speed = (poll_reg & MG_BIT(15)) ? MG_PHY_SPEED_100M : MG_PHY_SPEED_10M;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return up;
|
return up;
|
||||||
|
|||||||
+145
-20
@@ -1,61 +1,186 @@
|
|||||||
#if MG_ENABLE_TCPIP && MG_ARCH == MG_ARCH_PICOSDK && \
|
#if MG_ENABLE_TCPIP && MG_ARCH == MG_ARCH_PICOSDK && \
|
||||||
defined(MG_ENABLE_DRIVER_PICO_W) && MG_ENABLE_DRIVER_PICO_W
|
defined(MG_ENABLE_DRIVER_PICO_W) && MG_ENABLE_DRIVER_PICO_W
|
||||||
|
|
||||||
#include "net_builtin.h"
|
|
||||||
#include "drivers/pico-w.h"
|
#include "drivers/pico-w.h"
|
||||||
|
#include "net_builtin.h"
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
|
|
||||||
static struct mg_tcpip_if *s_ifp;
|
static struct mg_tcpip_if *s_ifp;
|
||||||
|
static uint32_t s_ip, s_mask;
|
||||||
|
static bool s_aplink = false, s_scanning = false;
|
||||||
|
static bool s_stalink = false, s_connecting = false;
|
||||||
|
|
||||||
|
static void wifi_cb(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
|
||||||
|
struct mg_wifi_data *wifi =
|
||||||
|
&((struct mg_tcpip_driver_pico_w_data *) ifp->driver_data)->wifi;
|
||||||
|
if (wifi->apmode && ev == MG_TCPIP_EV_ST_CHG &&
|
||||||
|
*(uint8_t *) ev_data == MG_TCPIP_STATE_UP) {
|
||||||
|
MG_DEBUG(("Access Point started"));
|
||||||
|
s_ip = ifp->ip, ifp->ip = wifi->apip;
|
||||||
|
s_mask = ifp->mask, ifp->mask = wifi->apmask;
|
||||||
|
ifp->enable_dhcp_client = false;
|
||||||
|
ifp->enable_dhcp_server = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool mg_tcpip_driver_pico_w_init(struct mg_tcpip_if *ifp) {
|
static bool mg_tcpip_driver_pico_w_init(struct mg_tcpip_if *ifp) {
|
||||||
struct mg_tcpip_driver_pico_w_data *d =
|
struct mg_tcpip_driver_pico_w_data *d =
|
||||||
(struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
|
(struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
|
||||||
|
struct mg_wifi_data *wifi = &d->wifi;
|
||||||
s_ifp = ifp;
|
s_ifp = ifp;
|
||||||
|
s_ip = ifp->ip;
|
||||||
|
s_mask = ifp->mask;
|
||||||
|
ifp->pfn = wifi_cb;
|
||||||
if (cyw43_arch_init() != 0)
|
if (cyw43_arch_init() != 0)
|
||||||
return false; // initialize async_context and WiFi chip
|
return false; // initialize async_context and WiFi chip
|
||||||
cyw43_arch_enable_sta_mode();
|
if (wifi->apmode && wifi->apssid != NULL) {
|
||||||
// start connecting to network
|
if (!mg_wifi_ap_start(wifi)) return false;
|
||||||
if (cyw43_arch_wifi_connect_bssid_async(d->ssid, NULL, d->pass,
|
cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac); // same MAC
|
||||||
CYW43_AUTH_WPA2_AES_PSK) != 0)
|
} else {
|
||||||
return false;
|
cyw43_arch_enable_sta_mode();
|
||||||
cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac);
|
cyw43_wifi_get_mac(&cyw43_state, CYW43_ITF_STA, ifp->mac);
|
||||||
|
if (wifi->ssid != NULL) {
|
||||||
|
return mg_wifi_connect(wifi);
|
||||||
|
} else {
|
||||||
|
cyw43_arch_disable_sta_mode();
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t mg_tcpip_driver_pico_w_tx(const void *buf, size_t len,
|
static size_t mg_tcpip_driver_pico_w_tx(const void *buf, size_t len,
|
||||||
struct mg_tcpip_if *ifp) {
|
struct mg_tcpip_if *ifp) {
|
||||||
(void) ifp;
|
struct mg_tcpip_driver_pico_w_data *d =
|
||||||
return cyw43_send_ethernet(&cyw43_state, CYW43_ITF_STA, len, buf, false)
|
(struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
|
||||||
? 0
|
return cyw43_send_ethernet(&cyw43_state,
|
||||||
: len;
|
d->wifi.apmode ? CYW43_ITF_AP : CYW43_ITF_STA, len,
|
||||||
|
buf, false) == 0
|
||||||
|
? len
|
||||||
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_tcpip_driver_pico_w_up(struct mg_tcpip_if *ifp) {
|
static bool mg_tcpip_driver_pico_w_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
(void) ifp;
|
cyw43_arch_poll(); // not necessary, except when IRQs are disabled (OTA)
|
||||||
return (cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA) ==
|
if (s_scanning && !cyw43_wifi_scan_active(&cyw43_state)) {
|
||||||
CYW43_LINK_JOIN);
|
MG_VERBOSE(("scan complete"));
|
||||||
|
s_scanning = 0;
|
||||||
|
mg_tcpip_call(ifp, MG_TCPIP_EV_WIFI_SCAN_END, NULL);
|
||||||
|
}
|
||||||
|
if (ifp->update_mac_hash_table) {
|
||||||
|
// first call to _poll() is after _init(), so this is safe
|
||||||
|
cyw43_wifi_update_multicast_filter(&cyw43_state, (uint8_t *) mcast_addr,
|
||||||
|
true);
|
||||||
|
ifp->update_mac_hash_table = false;
|
||||||
|
}
|
||||||
|
if (!s1) return false;
|
||||||
|
struct mg_tcpip_driver_pico_w_data *d =
|
||||||
|
(struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
|
||||||
|
if (d->wifi.apmode) return s_aplink;
|
||||||
|
int sdkstate = cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA);
|
||||||
|
MG_VERBOSE(("conn: %c state: %d", s_connecting ? '1' : '0', sdkstate));
|
||||||
|
if (sdkstate < 0 && s_connecting) {
|
||||||
|
mg_tcpip_call(ifp, MG_TCPIP_EV_WIFI_CONNECT_ERR, &sdkstate);
|
||||||
|
s_connecting = false;
|
||||||
|
}
|
||||||
|
return s_stalink;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mg_tcpip_driver mg_tcpip_driver_pico_w = {
|
struct mg_tcpip_driver mg_tcpip_driver_pico_w = {
|
||||||
mg_tcpip_driver_pico_w_init,
|
mg_tcpip_driver_pico_w_init,
|
||||||
mg_tcpip_driver_pico_w_tx,
|
mg_tcpip_driver_pico_w_tx,
|
||||||
NULL,
|
NULL,
|
||||||
mg_tcpip_driver_pico_w_up,
|
mg_tcpip_driver_pico_w_poll,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Called once per outstanding frame by async_context
|
// Called once per outstanding frame by async_context
|
||||||
void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len,
|
void cyw43_cb_process_ethernet(void *cb_data, int itf, size_t len,
|
||||||
const uint8_t *buf) {
|
const uint8_t *buf) {
|
||||||
if (itf != CYW43_ITF_STA) return;
|
|
||||||
mg_tcpip_qwrite((void *) buf, len, s_ifp);
|
mg_tcpip_qwrite((void *) buf, len, s_ifp);
|
||||||
(void) cb_data;
|
(void) cb_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by async_context
|
// Called by async_context
|
||||||
void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {}
|
void cyw43_cb_tcpip_set_link_up(cyw43_t *self, int itf) {
|
||||||
void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {}
|
if (itf == CYW43_ITF_AP) {
|
||||||
|
s_aplink = true;
|
||||||
|
} else {
|
||||||
|
s_stalink = true;
|
||||||
|
s_connecting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void cyw43_cb_tcpip_set_link_down(cyw43_t *self, int itf) {
|
||||||
|
if (itf == CYW43_ITF_AP) {
|
||||||
|
s_aplink = false;
|
||||||
|
} else {
|
||||||
|
s_stalink = false;
|
||||||
|
// SDK calls this before we check status, don't clear s_connecting here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// there's life beyond lwIP
|
// there's life beyond lwIP
|
||||||
void pbuf_copy_partial(void) {(void) 0;}
|
void pbuf_copy_partial(void) {
|
||||||
|
(void) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int result_cb(void *arg, const cyw43_ev_scan_result_t *data) {
|
||||||
|
struct mg_wifi_scan_bss_data bss;
|
||||||
|
bss.SSID = mg_str_n(data->ssid, data->ssid_len);
|
||||||
|
bss.BSSID = (char *) data->bssid;
|
||||||
|
bss.RSSI = (int8_t) data->rssi;
|
||||||
|
bss.has_n = 0; // SDK ignores this
|
||||||
|
bss.channel = (uint8_t) data->channel;
|
||||||
|
bss.band = MG_WIFI_BAND_2G;
|
||||||
|
// SDK-internal dependency, 2.1.0
|
||||||
|
bss.security = data->auth_mode & MG_BIT(0) ? MG_WIFI_SECURITY_WEP
|
||||||
|
: MG_WIFI_SECURITY_OPEN;
|
||||||
|
if (data->auth_mode & MG_BIT(1)) bss.security |= MG_WIFI_SECURITY_WPA;
|
||||||
|
if (data->auth_mode & MG_BIT(2)) bss.security |= MG_WIFI_SECURITY_WPA2;
|
||||||
|
MG_VERBOSE(("BSS: %.*s (%u) (%M) %d dBm %u", bss.SSID.len, bss.SSID.buf,
|
||||||
|
bss.channel, mg_print_mac, bss.BSSID, (int) bss.RSSI,
|
||||||
|
bss.security));
|
||||||
|
mg_tcpip_call(s_ifp, MG_TCPIP_EV_WIFI_SCAN_RESULT, &bss);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_wifi_scan(void) {
|
||||||
|
cyw43_wifi_scan_options_t opts;
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
bool res = (cyw43_wifi_scan(&cyw43_state, &opts, NULL, result_cb) == 0);
|
||||||
|
if (res) s_scanning = true;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_wifi_connect(struct mg_wifi_data *wifi) {
|
||||||
|
s_ifp->ip = s_ip;
|
||||||
|
s_ifp->mask = s_mask;
|
||||||
|
if (s_ifp->ip == 0) s_ifp->enable_dhcp_client = true;
|
||||||
|
s_ifp->enable_dhcp_server = false;
|
||||||
|
cyw43_arch_enable_sta_mode();
|
||||||
|
MG_DEBUG(("Connecting to '%s'", wifi->ssid));
|
||||||
|
int res = cyw43_arch_wifi_connect_async(wifi->ssid, wifi->pass,
|
||||||
|
CYW43_AUTH_WPA2_AES_PSK);
|
||||||
|
MG_VERBOSE(("res: %d", res));
|
||||||
|
if (res == 0) s_connecting = true;
|
||||||
|
return (res == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_wifi_disconnect(void) {
|
||||||
|
cyw43_arch_disable_sta_mode();
|
||||||
|
s_connecting = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_wifi_ap_start(struct mg_wifi_data *wifi) {
|
||||||
|
MG_DEBUG(("Starting AP '%s' (%u)", wifi->apssid, wifi->apchannel));
|
||||||
|
cyw43_wifi_ap_set_channel(&cyw43_state, wifi->apchannel);
|
||||||
|
cyw43_arch_enable_ap_mode(wifi->apssid, wifi->appass,
|
||||||
|
CYW43_AUTH_WPA2_AES_PSK);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_wifi_ap_stop(void) {
|
||||||
|
cyw43_arch_disable_ap_mode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -8,15 +8,14 @@
|
|||||||
#include "pico/unique_id.h" // keep this include
|
#include "pico/unique_id.h" // keep this include
|
||||||
|
|
||||||
struct mg_tcpip_driver_pico_w_data {
|
struct mg_tcpip_driver_pico_w_data {
|
||||||
char *ssid;
|
struct mg_wifi_data wifi;
|
||||||
char *pass;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||||
do { \
|
do { \
|
||||||
static struct mg_tcpip_driver_pico_w_data driver_data_; \
|
static struct mg_tcpip_driver_pico_w_data driver_data_; \
|
||||||
static struct mg_tcpip_if mif_; \
|
static struct mg_tcpip_if mif_; \
|
||||||
MG_SET_WIFI_CREDS(&driver_data_.ssid, &driver_data_.pass); \
|
MG_SET_WIFI_CONFIG(&driver_data_); \
|
||||||
mif_.ip = MG_TCPIP_IP; \
|
mif_.ip = MG_TCPIP_IP; \
|
||||||
mif_.mask = MG_TCPIP_MASK; \
|
mif_.mask = MG_TCPIP_MASK; \
|
||||||
mif_.gw = MG_TCPIP_GW; \
|
mif_.gw = MG_TCPIP_GW; \
|
||||||
|
|||||||
+3
-2
@@ -96,7 +96,8 @@ static uint32_t fcs_do(uint32_t fcs, uint8_t x) {
|
|||||||
return fcs;
|
return fcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_ppp_up(struct mg_tcpip_if *ifp) {
|
static bool mg_ppp_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
|
(void) s1;
|
||||||
return ifp->driver_data != NULL;
|
return ifp->driver_data != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,6 +323,6 @@ static size_t mg_ppp_rx(void *ethbuf, size_t ethlen, struct mg_tcpip_if *ifp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct mg_tcpip_driver mg_tcpip_driver_ppp = {mg_ppp_init, mg_ppp_tx, mg_ppp_rx,
|
struct mg_tcpip_driver mg_tcpip_driver_ppp = {mg_ppp_init, mg_ppp_tx, mg_ppp_rx,
|
||||||
mg_ppp_up};
|
mg_ppp_poll};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+37
-24
@@ -1,6 +1,8 @@
|
|||||||
#include "net_builtin.h"
|
#include "net_builtin.h"
|
||||||
|
|
||||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
(defined(MG_ENABLE_DRIVER_RA6) && MG_ENABLE_DRIVER_RA6) || \
|
||||||
|
(defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8)
|
||||||
struct ra_etherc {
|
struct ra_etherc {
|
||||||
volatile uint32_t ECMR, RESERVED, RFLR, RESERVED1, ECSR, RESERVED2, ECSIPR,
|
volatile uint32_t ECMR, RESERVED, RFLR, RESERVED1, ECSR, RESERVED2, ECSIPR,
|
||||||
RESERVED3, PIR, RESERVED4, PSR, RESERVED5[5], RDMLR, RESERVED6[3], IPGR,
|
RESERVED3, PIR, RESERVED4, PSR, RESERVED5[5], RDMLR, RESERVED6[3], IPGR,
|
||||||
@@ -18,27 +20,30 @@ struct ra_edmac {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#undef ETHERC
|
#undef ETHERC
|
||||||
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40114100U)
|
|
||||||
#undef EDMAC
|
#undef EDMAC
|
||||||
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40114000U)
|
|
||||||
#undef RASYSC
|
#undef RASYSC
|
||||||
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
|
|
||||||
#undef ICU_IELSR
|
#undef ICU_IELSR
|
||||||
|
#if defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8
|
||||||
|
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40354100U)
|
||||||
|
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40354000U)
|
||||||
|
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
|
||||||
|
#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x4000C300U)
|
||||||
|
#else
|
||||||
|
#define ETHERC ((struct ra_etherc *) (uintptr_t) 0x40114100U)
|
||||||
|
#define EDMAC ((struct ra_edmac *) (uintptr_t) 0x40114000U)
|
||||||
|
#define RASYSC ((uint32_t *) (uintptr_t) 0x4001E000U)
|
||||||
#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x40006300U)
|
#define ICU_IELSR ((uint32_t *) (uintptr_t) 0x40006300U)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ETH_PKT_SIZE 1536 // Max frame size, multiple of 32
|
#define ETH_PKT_SIZE 1536 // Max frame size, multiple of 32
|
||||||
#define ETH_DESC_CNT 4 // Descriptors count
|
#define ETH_DESC_CNT 4 // Descriptors count
|
||||||
|
|
||||||
// TODO(): handle these in a portable compiler-independent CMSIS-friendly way
|
|
||||||
#define MG_16BYTE_ALIGNED __attribute__((aligned((16U))))
|
|
||||||
#define MG_32BYTE_ALIGNED __attribute__((aligned((32U))))
|
|
||||||
|
|
||||||
// Descriptors: 16-byte aligned
|
// Descriptors: 16-byte aligned
|
||||||
// Buffers: 32-byte aligned (27.3.1)
|
// Buffers: 32-byte aligned (27.3.1)
|
||||||
static volatile uint32_t s_rxdesc[ETH_DESC_CNT][4] MG_16BYTE_ALIGNED;
|
static volatile uint32_t s_rxdesc[ETH_DESC_CNT][4] MG_ETH_RAM MG_16BYTE_ALIGNED;
|
||||||
static volatile uint32_t s_txdesc[ETH_DESC_CNT][4] MG_16BYTE_ALIGNED;
|
static volatile uint32_t s_txdesc[ETH_DESC_CNT][4] MG_ETH_RAM MG_16BYTE_ALIGNED;
|
||||||
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_32BYTE_ALIGNED;
|
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_32BYTE_ALIGNED;
|
||||||
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_32BYTE_ALIGNED;
|
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_32BYTE_ALIGNED;
|
||||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||||
|
|
||||||
// fastest is 3 cycles (SUB + BNE) on a 3-stage pipeline or equivalent
|
// fastest is 3 cycles (SUB + BNE) on a 3-stage pipeline or equivalent
|
||||||
@@ -101,9 +106,9 @@ static uint16_t smi_rd(uint16_t header) {
|
|||||||
pir = 0; // read, mdc = 0
|
pir = 0; // read, mdc = 0
|
||||||
ETHERC->PIR = pir;
|
ETHERC->PIR = pir;
|
||||||
raspin(s_smispin / 2); // 1/4 clock period, 300ns max access time
|
raspin(s_smispin / 2); // 1/4 clock period, 300ns max access time
|
||||||
data |= (uint16_t)(ETHERC->PIR & MG_BIT(3) ? 1 : 0); // read mdio
|
data |= (uint16_t) (ETHERC->PIR & MG_BIT(3) ? 1 : 0); // read mdio
|
||||||
raspin(s_smispin / 2); // 1/4 clock period
|
raspin(s_smispin / 2); // 1/4 clock period
|
||||||
pir |= MG_BIT(0); // mdc = 1
|
pir |= MG_BIT(0); // mdc = 1
|
||||||
ETHERC->PIR = pir;
|
ETHERC->PIR = pir;
|
||||||
raspin(s_smispin);
|
raspin(s_smispin);
|
||||||
}
|
}
|
||||||
@@ -111,11 +116,14 @@ static uint16_t smi_rd(uint16_t header) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t raeth_read_phy(uint8_t addr, uint8_t reg) {
|
static uint16_t raeth_read_phy(uint8_t addr, uint8_t reg) {
|
||||||
return smi_rd((uint16_t)((1 << 14) | (2 << 12) | (addr << 7) | (reg << 2) | (2 << 0)));
|
return smi_rd(
|
||||||
|
(uint16_t) ((1 << 14) | (2 << 12) | (addr << 7) | (reg << 2) | (2 << 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void raeth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
static void raeth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
||||||
smi_wr((uint16_t)((1 << 14) | (1 << 12) | (addr << 7) | (reg << 2) | (2 << 0)), val);
|
smi_wr(
|
||||||
|
(uint16_t) ((1 << 14) | (1 << 12) | (addr << 7) | (reg << 2) | (2 << 0)),
|
||||||
|
val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MDC clock is generated manually; as per 802.3, it must not exceed 2.5MHz
|
// MDC clock is generated manually; as per 802.3, it must not exceed 2.5MHz
|
||||||
@@ -152,7 +160,7 @@ static bool mg_tcpip_driver_ra_init(struct mg_tcpip_if *ifp) {
|
|||||||
|
|
||||||
MG_DEBUG(("PHY addr: %d, smispin: %d", d->phy_addr, s_smispin));
|
MG_DEBUG(("PHY addr: %d, smispin: %d", d->phy_addr, s_smispin));
|
||||||
struct mg_phy phy = {raeth_read_phy, raeth_write_phy};
|
struct mg_phy phy = {raeth_read_phy, raeth_write_phy};
|
||||||
mg_phy_init(&phy, d->phy_addr, 0); // MAC clocks PHY
|
mg_phy_init(&phy, d->phy_addr, 0); // MAC clocks PHY
|
||||||
|
|
||||||
// Select RMII mode,
|
// Select RMII mode,
|
||||||
ETHERC->ECMR = MG_BIT(2) | MG_BIT(1); // 100M, Full-duplex, CRC
|
ETHERC->ECMR = MG_BIT(2) | MG_BIT(1); // 100M, Full-duplex, CRC
|
||||||
@@ -171,9 +179,9 @@ static bool mg_tcpip_driver_ra_init(struct mg_tcpip_if *ifp) {
|
|||||||
EDMAC->FDR = 0x070f; // (27.2.11)
|
EDMAC->FDR = 0x070f; // (27.2.11)
|
||||||
EDMAC->RMCR = MG_BIT(0); // (27.2.12)
|
EDMAC->RMCR = MG_BIT(0); // (27.2.12)
|
||||||
ETHERC->ECMR |= MG_BIT(6) | MG_BIT(5); // TE RE
|
ETHERC->ECMR |= MG_BIT(6) | MG_BIT(5); // TE RE
|
||||||
EDMAC->EESIPR = MG_BIT(18); // Enable Rx IRQ
|
EDMAC->EESIPR = MG_BIT(18); // FR: Enable Rx (frame) IRQ
|
||||||
EDMAC->EDRRR = MG_BIT(0); // Receive Descriptors have changed
|
EDMAC->EDRRR = MG_BIT(0); // Receive Descriptors have changed
|
||||||
EDMAC->EDTRR = MG_BIT(0); // Transmit Descriptors have changed
|
EDMAC->EDTRR = MG_BIT(0); // Transmit Descriptors have changed
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +206,12 @@ static size_t mg_tcpip_driver_ra_tx(const void *buf, size_t len,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_tcpip_driver_ra_up(struct mg_tcpip_if *ifp) {
|
static bool mg_tcpip_driver_ra_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
|
if (ifp->update_mac_hash_table) {
|
||||||
|
EDMAC->EESIPR = MG_BIT(18) | MG_BIT(7); // FR, RMAF: Frame and mcast IRQ
|
||||||
|
ifp->update_mac_hash_table = false;
|
||||||
|
}
|
||||||
|
if (!s1) return false;
|
||||||
struct mg_tcpip_driver_ra_data *d =
|
struct mg_tcpip_driver_ra_data *d =
|
||||||
(struct mg_tcpip_driver_ra_data *) ifp->driver_data;
|
(struct mg_tcpip_driver_ra_data *) ifp->driver_data;
|
||||||
uint8_t speed = MG_PHY_SPEED_10M;
|
uint8_t speed = MG_PHY_SPEED_10M;
|
||||||
@@ -224,7 +237,7 @@ static uint32_t s_rxno;
|
|||||||
void EDMAC_IRQHandler(void) {
|
void EDMAC_IRQHandler(void) {
|
||||||
struct mg_tcpip_driver_ra_data *d =
|
struct mg_tcpip_driver_ra_data *d =
|
||||||
(struct mg_tcpip_driver_ra_data *) s_ifp->driver_data;
|
(struct mg_tcpip_driver_ra_data *) s_ifp->driver_data;
|
||||||
EDMAC->EESR = MG_BIT(18); // Ack IRQ in EDMAC 1st
|
EDMAC->EESR = MG_BIT(18) | MG_BIT(7); // Ack IRQ in EDMAC 1st
|
||||||
ICU_IELSR[d->irqno] &= ~MG_BIT(16); // Ack IRQ in ICU last
|
ICU_IELSR[d->irqno] &= ~MG_BIT(16); // Ack IRQ in ICU last
|
||||||
// Frame received, loop
|
// Frame received, loop
|
||||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||||
@@ -245,6 +258,6 @@ void EDMAC_IRQHandler(void) {
|
|||||||
|
|
||||||
struct mg_tcpip_driver mg_tcpip_driver_ra = {mg_tcpip_driver_ra_init,
|
struct mg_tcpip_driver mg_tcpip_driver_ra = {mg_tcpip_driver_ra_init,
|
||||||
mg_tcpip_driver_ra_tx, NULL,
|
mg_tcpip_driver_ra_tx, NULL,
|
||||||
mg_tcpip_driver_ra_up};
|
mg_tcpip_driver_ra_poll};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+32
-1
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_RA) && MG_ENABLE_DRIVER_RA
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
(defined(MG_ENABLE_DRIVER_RA6) && MG_ENABLE_DRIVER_RA6) || \
|
||||||
|
(defined(MG_ENABLE_DRIVER_RA8) && MG_ENABLE_DRIVER_RA8)
|
||||||
|
|
||||||
struct mg_tcpip_driver_ra_data {
|
struct mg_tcpip_driver_ra_data {
|
||||||
// MDC clock "divider". MDC clock is software generated,
|
// MDC clock "divider". MDC clock is software generated,
|
||||||
@@ -9,4 +11,33 @@ struct mg_tcpip_driver_ra_data {
|
|||||||
uint8_t phy_addr; // PHY address
|
uint8_t phy_addr; // PHY address
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifndef MG_DRIVER_CLK_FREQ
|
||||||
|
#define MG_DRIVER_CLK_FREQ 100000000UL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_DRIVER_IRQ_NO
|
||||||
|
#define MG_DRIVER_IRQ_NO 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_TCPIP_PHY_ADDR
|
||||||
|
#define MG_TCPIP_PHY_ADDR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||||
|
do { \
|
||||||
|
static struct mg_tcpip_driver_ra_data driver_data_; \
|
||||||
|
static struct mg_tcpip_if mif_; \
|
||||||
|
driver_data_.clock = MG_DRIVER_CLK_FREQ; \
|
||||||
|
driver_data_.irqno = MG_DRIVER_IRQ_NO; \
|
||||||
|
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
|
||||||
|
mif_.ip = MG_TCPIP_IP; \
|
||||||
|
mif_.mask = MG_TCPIP_MASK; \
|
||||||
|
mif_.gw = MG_TCPIP_GW; \
|
||||||
|
mif_.driver = &mg_tcpip_driver_ra; \
|
||||||
|
mif_.driver_data = &driver_data_; \
|
||||||
|
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||||
|
mg_tcpip_init(mgr, &mif_); \
|
||||||
|
MG_INFO(("Driver: ra, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+24
-8
@@ -26,17 +26,17 @@ struct ENET_Type {
|
|||||||
CHANNEL_TCSR[4], CHANNEL_TCCR[4];
|
CHANNEL_TCSR[4], CHANNEL_TCCR[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef ENET
|
||||||
#define ENET ((struct ENET_Type *) 0x40138000)
|
#define ENET ((struct ENET_Type *) 0x40138000)
|
||||||
|
|
||||||
#define ETH_PKT_SIZE 1536 // Max frame size
|
#define ETH_PKT_SIZE 1536 // Max frame size
|
||||||
#define ETH_DESC_CNT 4 // Descriptors count
|
#define ETH_DESC_CNT 4 // Descriptors count
|
||||||
#define ETH_DS 2 // Descriptor size (words)
|
#define ETH_DS 2 // Descriptor size (words)
|
||||||
|
|
||||||
#define MG_8BYTE_ALIGNED __attribute__((aligned((8U))))
|
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_8BYTE_ALIGNED;
|
||||||
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_8BYTE_ALIGNED;
|
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_ETH_RAM MG_8BYTE_ALIGNED;
|
||||||
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE] MG_8BYTE_ALIGNED;
|
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
|
||||||
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
|
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_ETH_RAM MG_8BYTE_ALIGNED;
|
||||||
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS] MG_8BYTE_ALIGNED;
|
|
||||||
static uint8_t s_txno; // Current TX descriptor
|
static uint8_t s_txno; // Current TX descriptor
|
||||||
static uint8_t s_rxno; // Current RX descriptor
|
static uint8_t s_rxno; // Current RX descriptor
|
||||||
|
|
||||||
@@ -89,6 +89,10 @@ static bool mg_tcpip_driver_rw612_init(struct mg_tcpip_if *ifp) {
|
|||||||
ENET->PALR =
|
ENET->PALR =
|
||||||
ifp->mac[0] << 24 | ifp->mac[1] << 16 | ifp->mac[2] << 8 | ifp->mac[3];
|
ifp->mac[0] << 24 | ifp->mac[1] << 16 | ifp->mac[2] << 8 | ifp->mac[3];
|
||||||
ENET->PAUR |= (ifp->mac[4] << 24 | ifp->mac[5] << 16);
|
ENET->PAUR |= (ifp->mac[4] << 24 | ifp->mac[5] << 16);
|
||||||
|
ENET->IALR = 0;
|
||||||
|
ENET->IAUR = 0;
|
||||||
|
ENET->GALR = 0;
|
||||||
|
ENET->GAUR = 0;
|
||||||
ENET->MSCR = ((d->mdc_cr & 0x3f) << 1) | ((d->mdc_holdtime & 7) << 8);
|
ENET->MSCR = ((d->mdc_cr & 0x3f) << 1) | ((d->mdc_holdtime & 7) << 8);
|
||||||
ENET->EIMR = MG_BIT(25); // Enable RX interrupt
|
ENET->EIMR = MG_BIT(25); // Enable RX interrupt
|
||||||
ENET->ECR |= MG_BIT(8) | MG_BIT(1); // DBSWP, Enable
|
ENET->ECR |= MG_BIT(8) | MG_BIT(1); // DBSWP, Enable
|
||||||
@@ -121,7 +125,19 @@ static size_t mg_tcpip_driver_rw612_tx(const void *buf, size_t len,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_tcpip_driver_rw612_up(struct mg_tcpip_if *ifp) {
|
|
||||||
|
static void mg_tcpip_driver_rw612_update_hash_table(struct mg_tcpip_if *ifp) {
|
||||||
|
// TODO(): read database, rebuild hash table
|
||||||
|
ENET->GAUR = MG_BIT(1); // see imxrt, it reduces to this for mDNS
|
||||||
|
(void) ifp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mg_tcpip_driver_rw612_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
|
if (ifp->update_mac_hash_table) {
|
||||||
|
mg_tcpip_driver_rw612_update_hash_table(ifp);
|
||||||
|
ifp->update_mac_hash_table = false;
|
||||||
|
}
|
||||||
|
if (!s1) return false;
|
||||||
struct mg_tcpip_driver_rw612_data *d =
|
struct mg_tcpip_driver_rw612_data *d =
|
||||||
(struct mg_tcpip_driver_rw612_data *) ifp->driver_data;
|
(struct mg_tcpip_driver_rw612_data *) ifp->driver_data;
|
||||||
uint8_t speed = MG_PHY_SPEED_10M;
|
uint8_t speed = MG_PHY_SPEED_10M;
|
||||||
@@ -157,7 +173,7 @@ static bool mg_tcpip_driver_rw612_up(struct mg_tcpip_if *ifp) {
|
|||||||
|
|
||||||
void ENET_IRQHandler(void) {
|
void ENET_IRQHandler(void) {
|
||||||
if (ENET->EIR & MG_BIT(25)) {
|
if (ENET->EIR & MG_BIT(25)) {
|
||||||
ENET->EIR = MG_BIT(25); // Ack RX
|
ENET->EIR = MG_BIT(25); // Ack RX
|
||||||
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
for (uint32_t i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||||
if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) != 0) break; // exit when done
|
if ((s_rxdesc[s_rxno][0] & MG_BIT(31)) != 0) break; // exit when done
|
||||||
// skip partial/errored frames
|
// skip partial/errored frames
|
||||||
@@ -177,5 +193,5 @@ void ENET_IRQHandler(void) {
|
|||||||
|
|
||||||
struct mg_tcpip_driver mg_tcpip_driver_rw612 = {mg_tcpip_driver_rw612_init,
|
struct mg_tcpip_driver mg_tcpip_driver_rw612 = {mg_tcpip_driver_rw612_init,
|
||||||
mg_tcpip_driver_rw612_tx, NULL,
|
mg_tcpip_driver_rw612_tx, NULL,
|
||||||
mg_tcpip_driver_rw612_up};
|
mg_tcpip_driver_rw612_poll};
|
||||||
#endif
|
#endif
|
||||||
+120
-85
@@ -1,8 +1,37 @@
|
|||||||
#include "net_builtin.h"
|
#include "net_builtin.h"
|
||||||
|
|
||||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
|
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
|
||||||
|
MG_ENABLE_DRIVER_SAME54
|
||||||
|
|
||||||
#include <sam.h>
|
struct GMAC_REGS_ {
|
||||||
|
uint32_t GMAC_NCR, GMAC_NCFGR, GMAC_NSR, GMAC_UR, GMAC_DCFGR, GMAC_TSR,
|
||||||
|
GMAC_RBQB, GMAC_TBQB, GMAC_RSR, GMAC_ISR, GMAC_IER, GMAC_IDR, GMAC_IMR,
|
||||||
|
GMAC_MAN, GMAC_RPQ, GMAC_TPQ, GMAC_TPSF, GMAC_RPSF, GMAC_RJFML,
|
||||||
|
Reserved1[13], GMAC_HRB, GMAC_HRT, GMAC_SAB0, GMAC_SAT0, GMAC_SAB1,
|
||||||
|
GMAC_SAT1, GMAC_SAB2, GMAC_SAT2, GMAC_SAB3, GMAC_SAT3, GMAC_TIDM[4],
|
||||||
|
GMAC_WOL, GMAC_IPGS, GMAC_SVLAN, GMAC_TPFCP, GMAC_SAMB1, GMAC_SAMT1,
|
||||||
|
Reserved2[3], GMAC_NSC, GMAC_SCL, GMAC_SCH, GMAC_EFTSH, GMAC_EFRSH,
|
||||||
|
GMAC_PEFTSH, GMAC_PEFRSH, Reserved3[2], GMAC_OTLO, GMAC_OTHI, GMAC_FT,
|
||||||
|
GMAC_BCFT, GMAC_MFT, GMAC_PFT, GMAC_BFT64, GMAC_TBFT127, GMAC_TBFT255,
|
||||||
|
GMAC_TBFT511, GMAC_TBFT1023, GMAC_TBFT1518, GMAC_GTBFT1518, GMAC_TUR,
|
||||||
|
GMAC_SCF, GMAC_MCF, GMAC_EC, GMAC_LC, GMAC_DTF, GMAC_CSE, GMAC_ORLO,
|
||||||
|
GMAC_ORHI, GMAC_FR, GMAC_BCFR, GMAC_MFR, GMAC_PFR, GMAC_BFR64,
|
||||||
|
GMAC_TBFR127, GMAC_TBFR255, GMAC_TBFR511, GMAC_TBFR1023, GMAC_TBFR1518,
|
||||||
|
GMAC_TMXBFR, GMAC_UFR, GMAC_OFR, GMAC_JR, GMAC_FCSE, GMAC_LFFE, GMAC_RSE,
|
||||||
|
GMAC_AE, GMAC_RRE, GMAC_ROE, GMAC_IHCE, GMAC_TCE, GMAC_UCE, Reserved4[2],
|
||||||
|
GMAC_TISUBN, GMAC_TSH, Reserved5, GMAC_TSSSL, GMAC_TSSN, GMAC_TSL,
|
||||||
|
GMAC_TN, GMAC_TA, GMAC_TI, GMAC_EFTSL, GMAC_EFTN, GMAC_EFRSL, GMAC_EFRN,
|
||||||
|
GMAC_PEFTSL, GMAC_PEFTN, GMAC_PEFRSL, GMAC_PEFRN, Reserved6[28],
|
||||||
|
GMAC_RLPITR, GMAC_RLPITI, GMAC_TLPITR, GMAC_TLPITI;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GCLK_REGS_ {
|
||||||
|
uint32_t GCLK_CTRLA_RESERVED, GCLK_SYNCBUSY, Reserved2[6], GCLK_GENCTRL[12],
|
||||||
|
Reserved3[12], GCLK_PCHCTRL[48];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GMAC_REGS ((struct GMAC_REGS_ *) 0x42000800)
|
||||||
|
#define GCLK_REGS ((struct GCLK_REGS_ *) 0x40001c00)
|
||||||
|
|
||||||
#define ETH_PKT_SIZE 1536 // Max frame size
|
#define ETH_PKT_SIZE 1536 // Max frame size
|
||||||
#define ETH_DESC_CNT 4 // Descriptors count
|
#define ETH_DESC_CNT 4 // Descriptors count
|
||||||
@@ -16,72 +45,67 @@ static uint8_t s_txno; // Current TX descriptor
|
|||||||
static uint8_t s_rxno; // Current RX descriptor
|
static uint8_t s_rxno; // Current RX descriptor
|
||||||
|
|
||||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||||
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
|
|
||||||
|
|
||||||
#define MG_PHYREGBIT_BCR_DUPLEX_MODE MG_BIT(8)
|
|
||||||
#define MG_PHYREGBIT_BCR_SPEED MG_BIT(13)
|
|
||||||
#define MG_PHYREGBIT_BSR_LINK_STATUS MG_BIT(2)
|
|
||||||
|
|
||||||
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
|
GMAC_REGS->GMAC_MAN = MG_BIT(30) | // Clause 22
|
||||||
GMAC_MAN_OP(2) | // Setting the read operation
|
MG_BIT(29) | // Setting the read operation
|
||||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||||
GMAC_MAN_REGA(reg); // Setting the register
|
((reg & 0x1f) << 18); // Setting the register
|
||||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0;
|
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2))) (void) 0;
|
||||||
return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value
|
return GMAC_REGS->GMAC_MAN & 0xffff; // Getting the read value
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
||||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation
|
GMAC_REGS->GMAC_MAN = MG_BIT(30) |
|
||||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
MG_BIT(28) | // Setting the write operation
|
||||||
GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register
|
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete
|
((reg & 0x1f) << 18) | val; // Setting the register
|
||||||
|
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2)))
|
||||||
|
; // Waiting until the write op is complete
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
uint32_t get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
||||||
if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) {
|
if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) {
|
||||||
return d->mdc_cr;
|
return d->mdc_cr;
|
||||||
} else {
|
} else {
|
||||||
// get MCLK from GCLK_GENERATOR 0
|
// get MCLK from GCLK_GENERATOR 0
|
||||||
uint32_t div = 512;
|
uint32_t div = 512;
|
||||||
uint32_t mclk;
|
uint32_t mclk;
|
||||||
if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) {
|
if (!(GCLK_REGS->GCLK_GENCTRL[0] & MG_BIT(12))) {
|
||||||
div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16);
|
div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16);
|
||||||
if (div == 0) div = 1;
|
if (div == 0) div = 1;
|
||||||
}
|
}
|
||||||
switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) {
|
switch (GCLK_REGS->GCLK_GENCTRL[0] & 0xF) {
|
||||||
case GCLK_GENCTRL_SRC_XOSC0_Val:
|
case 0: // GCLK_GENCTRL_SRC_XOSC0_Val
|
||||||
mclk = 32000000UL; /* 32MHz */
|
mclk = 32000000UL; // 32MHz
|
||||||
break;
|
break;
|
||||||
case GCLK_GENCTRL_SRC_XOSC1_Val:
|
case 1: // GCLK_GENCTRL_SRC_XOSC1_Val
|
||||||
mclk = 32000000UL; /* 32MHz */
|
mclk = 32000000UL; // 32MHz
|
||||||
break;
|
break;
|
||||||
case GCLK_GENCTRL_SRC_OSCULP32K_Val:
|
case 4: // GCLK_GENCTRL_SRC_OSCULP32K_Val
|
||||||
mclk = 32000UL;
|
mclk = 32000UL; // 32Khz
|
||||||
break;
|
break;
|
||||||
case GCLK_GENCTRL_SRC_XOSC32K_Val:
|
case 5: // GCLK_GENCTRL_SRC_XOSC32K_Val
|
||||||
mclk = 32000UL;
|
mclk = 32000UL; // 32Khz
|
||||||
break;
|
break;
|
||||||
case GCLK_GENCTRL_SRC_DFLL_Val:
|
case 6: // GCLK_GENCTRL_SRC_DFLL_Val
|
||||||
mclk = 48000000UL; /* 48MHz */
|
mclk = 48000000UL; // 48MHz
|
||||||
break;
|
break;
|
||||||
case GCLK_GENCTRL_SRC_DPLL0_Val:
|
case 7: // GCLK_GENCTRL_SRC_DPLL0_Val:
|
||||||
mclk = 200000000UL; /* 200MHz */
|
mclk = 200000000UL; // 200MHz
|
||||||
break;
|
break;
|
||||||
case GCLK_GENCTRL_SRC_DPLL1_Val:
|
case 8: // GCLK_GENCTRL_SRC_DPLL1_Val
|
||||||
mclk = 200000000UL; /* 200MHz */
|
mclk = 200000000UL; // 200MHz
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mclk = 200000000UL; /* 200MHz */
|
mclk = 200000000UL; // 200MHz
|
||||||
}
|
}
|
||||||
|
|
||||||
mclk /= div;
|
mclk /= div;
|
||||||
uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values
|
uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values
|
||||||
uint8_t dividers[] = {8, 16, 32, 48, 64, 96}; // Respective CLK dividers
|
uint8_t dividers[] = {8, 16, 32, 48, 64, 96}; // Respective CLK dividers
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) {
|
if (mclk / dividers[i] <= 2375000UL) { // 2.5MHz - 5%
|
||||||
return crs[i];
|
return crs[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,11 +119,12 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
|||||||
(struct mg_tcpip_driver_same54_data *) ifp->driver_data;
|
(struct mg_tcpip_driver_same54_data *) ifp->driver_data;
|
||||||
s_ifp = ifp;
|
s_ifp = ifp;
|
||||||
|
|
||||||
MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk;
|
GMAC_REGS->GMAC_NCFGR = get_clock_rate(d) << 18; // Set MDC divider
|
||||||
MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk;
|
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
||||||
GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider
|
GMAC_REGS->GMAC_NCR |= MG_BIT(4); // Enable MDC & MDIO
|
||||||
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
|
||||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO
|
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||||
|
mg_phy_init(&phy, d->phy_addr, 0);
|
||||||
|
|
||||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
|
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
|
||||||
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
|
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
|
||||||
@@ -107,38 +132,33 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
|||||||
}
|
}
|
||||||
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
|
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
|
||||||
|
|
||||||
GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18) // DMA recv buf 1536
|
GMAC_REGS->GMAC_DCFGR = (0x18 << 16) | // DMA recv buf 1536
|
||||||
| GMAC_DCFGR_RXBMS(GMAC_DCFGR_RXBMS_FULL_Val) |
|
(3 << 8) | // RXBMS
|
||||||
GMAC_DCFGR_TXPBMS(1); // See #2487
|
MG_BIT(10); // See #2487
|
||||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
||||||
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
||||||
s_rxdesc[i][1] = 0; // Clear status
|
s_rxdesc[i][1] = 0; // Clear status
|
||||||
}
|
}
|
||||||
s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(1); // Last rx descriptor - wrap
|
s_rxdesc[ETH_DESC_CNT - 1][0] |= MG_BIT(1); // Last rx descriptor - wrap
|
||||||
|
|
||||||
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
|
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
|
||||||
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
|
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
|
||||||
|
|
||||||
GMAC_REGS->SA[0].GMAC_SAB =
|
GMAC_REGS->GMAC_SAB0 =
|
||||||
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
|
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
|
||||||
GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
GMAC_REGS->GMAC_SAT0 = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
||||||
|
|
||||||
GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII
|
GMAC_REGS->GMAC_UR &= ~MG_BIT(0); // Disable MII, use RMII
|
||||||
GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk |
|
GMAC_REGS->GMAC_NCFGR |= MG_BIT(8) | MG_BIT(6) | // MAXFX, MTIHEN
|
||||||
GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk;
|
MG_BIT(25) | MG_BIT(4); // EFRHD, CAF
|
||||||
GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk |
|
GMAC_REGS->GMAC_TSR = 0x17f; // all transmit statuses
|
||||||
GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk |
|
GMAC_REGS->GMAC_RSR = 0xf; // all recv statuses
|
||||||
GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
|
||||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk;
|
|
||||||
GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk |
|
|
||||||
GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk;
|
|
||||||
GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required
|
GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required
|
||||||
GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk |
|
GMAC_REGS->GMAC_IER = MG_BIT(11) | MG_BIT(10) | // HRESP, ROVR
|
||||||
GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk |
|
MG_BIT(7) | MG_BIT(6) | // TCOMP, TFC
|
||||||
GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk |
|
MG_BIT(5) | MG_BIT(4) | // RLEX, TUR
|
||||||
GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk;
|
MG_BIT(2) | MG_BIT(1); // RXUBR, RCOMP
|
||||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk;
|
GMAC_REGS->GMAC_NCR |= MG_BIT(3) | MG_BIT(2); // TXEN, RXEN
|
||||||
NVIC_EnableIRQ(GMAC_IRQn);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -159,25 +179,42 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
|
|||||||
s_txdesc[s_txno][1] = status;
|
s_txdesc[s_txno][1] = status;
|
||||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||||
}
|
}
|
||||||
__DSB(); // Ensure descriptors have been written
|
MG_DSB(); // Ensure descriptors have been written
|
||||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission
|
GMAC_REGS->GMAC_NCR |= MG_BIT(9); // Enable transmission
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mg_tcpip_driver_same54_up(struct mg_tcpip_if *ifp) {
|
static void mg_tcpip_driver_same54_update_hash_table(struct mg_tcpip_if *ifp) {
|
||||||
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
|
// TODO(): read database, rebuild hash table
|
||||||
bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0;
|
// Setting Hash Index for 01:00:5e:00:00:fb (multicast)
|
||||||
|
// 24.6.9 Hash addressing
|
||||||
|
// computed hash is 55, which means bit 23 (55 - 32) in
|
||||||
|
// HRT register must be set
|
||||||
|
GMAC_REGS->GMAC_HRT = MG_BIT(23);
|
||||||
|
GMAC_REGS->GMAC_NCFGR |= MG_BIT(6); // enable multicast hash filtering
|
||||||
|
(void) ifp;
|
||||||
|
}
|
||||||
|
|
||||||
// If PHY is ready, update NCFGR accordingly
|
static bool mg_tcpip_driver_same54_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||||
if (ifp->state == MG_TCPIP_STATE_DOWN && up) {
|
if (ifp->update_mac_hash_table) {
|
||||||
uint16_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
|
mg_tcpip_driver_same54_update_hash_table(ifp);
|
||||||
bool fd = bcr & MG_PHYREGBIT_BCR_DUPLEX_MODE ? 1 : 0;
|
ifp->update_mac_hash_table = false;
|
||||||
bool spd = bcr & MG_PHYREGBIT_BCR_SPEED ? 1 : 0;
|
|
||||||
GMAC_REGS->GMAC_NCFGR = (GMAC_REGS->GMAC_NCFGR &
|
|
||||||
~(GMAC_NCFGR_SPD_Msk | MG_PHYREGBIT_BCR_SPEED)) |
|
|
||||||
GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool up = false;
|
||||||
|
if (s1) {
|
||||||
|
uint8_t speed = MG_PHY_SPEED_10M;
|
||||||
|
bool full_duplex = false;
|
||||||
|
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||||
|
up = mg_phy_up(&phy, 0, &full_duplex, &speed);
|
||||||
|
|
||||||
|
// If PHY is ready, update NCFGR accordingly
|
||||||
|
if (ifp->state == MG_TCPIP_STATE_DOWN && up) {
|
||||||
|
GMAC_REGS->GMAC_NCFGR =
|
||||||
|
(GMAC_REGS->GMAC_NCFGR & ~(MG_BIT(0) | MG_BIT(1))) | (speed & 1) |
|
||||||
|
(full_duplex << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
return up;
|
return up;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,8 +223,8 @@ void GMAC_Handler(void) {
|
|||||||
uint32_t isr = GMAC_REGS->GMAC_ISR;
|
uint32_t isr = GMAC_REGS->GMAC_ISR;
|
||||||
uint32_t rsr = GMAC_REGS->GMAC_RSR;
|
uint32_t rsr = GMAC_REGS->GMAC_RSR;
|
||||||
uint32_t tsr = GMAC_REGS->GMAC_TSR;
|
uint32_t tsr = GMAC_REGS->GMAC_TSR;
|
||||||
if (isr & GMAC_ISR_RCOMP_Msk) {
|
if (isr & MG_BIT(1)) {
|
||||||
if (rsr & GMAC_ISR_RCOMP_Msk) {
|
if (rsr & MG_BIT(1)) {
|
||||||
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
|
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||||
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
|
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
|
||||||
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
|
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
|
||||||
@@ -198,9 +235,7 @@ void GMAC_Handler(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk |
|
if (tsr != 0) {
|
||||||
GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
|
||||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
|
|
||||||
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
|
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
|
||||||
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
|
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
|
||||||
}
|
}
|
||||||
@@ -211,5 +246,5 @@ void GMAC_Handler(void) {
|
|||||||
|
|
||||||
struct mg_tcpip_driver mg_tcpip_driver_same54 = {
|
struct mg_tcpip_driver mg_tcpip_driver_same54 = {
|
||||||
mg_tcpip_driver_same54_init, mg_tcpip_driver_same54_tx, NULL,
|
mg_tcpip_driver_same54_init, mg_tcpip_driver_same54_tx, NULL,
|
||||||
mg_tcpip_driver_same54_up};
|
mg_tcpip_driver_same54_poll};
|
||||||
#endif
|
#endif
|
||||||
+27
-5
@@ -1,13 +1,35 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
|
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
|
||||||
|
MG_ENABLE_DRIVER_SAME54
|
||||||
struct mg_tcpip_driver_same54_data {
|
|
||||||
int mdc_cr;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef MG_DRIVER_MDC_CR
|
#ifndef MG_DRIVER_MDC_CR
|
||||||
#define MG_DRIVER_MDC_CR 5
|
#define MG_DRIVER_MDC_CR 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef MG_DRIVER_PHY_ADDR
|
||||||
|
#define MG_DRIVER_PHY_ADDR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct mg_tcpip_driver_same54_data {
|
||||||
|
int mdc_cr;
|
||||||
|
uint8_t phy_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||||
|
do { \
|
||||||
|
static struct mg_tcpip_driver_same54_data driver_data_; \
|
||||||
|
static struct mg_tcpip_if mif_; \
|
||||||
|
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
|
||||||
|
driver_data_.phy_addr = MG_DRIVER_PHY_ADDR; \
|
||||||
|
mif_.ip = MG_TCPIP_IP; \
|
||||||
|
mif_.mask = MG_TCPIP_MASK; \
|
||||||
|
mif_.gw = MG_TCPIP_GW; \
|
||||||
|
mif_.driver = &mg_tcpip_driver_same54; \
|
||||||
|
mif_.driver_data = &driver_data_; \
|
||||||
|
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||||
|
mg_tcpip_init(mgr, &mif_); \
|
||||||
|
MG_INFO(("Driver: same54, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
#include "sdio.h"
|
||||||
|
|
||||||
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO)
|
||||||
|
|
||||||
|
// SDIO 6.9 Table 6-1 CCCR (Common Card Control Registers)
|
||||||
|
#define MG_SDIO_CCCR_SDIOREV 0x000
|
||||||
|
#define MG_SDIO_CCCR_SDREV 0x001
|
||||||
|
#define MG_SDIO_CCCR_IOEN 0x002
|
||||||
|
#define MG_SDIO_CCCR_IORDY 0x003
|
||||||
|
#define MG_SDIO_CCCR_INTEN 0x004
|
||||||
|
#define MG_SDIO_CCCR_BIC 0x007
|
||||||
|
#define MG_SDIO_CCCR_CCAP 0x008
|
||||||
|
#define MG_SDIO_CCCR_CCIS 0x009 // 3 registers
|
||||||
|
#define MG_SDIO_CCCR_F0BLKSZ 0x010 // 2 registers
|
||||||
|
#define MG_SDIO_CCCR_HISPD 0x013
|
||||||
|
// SDIO 6.10 Table 6-3 FBR (Function Basic Registers)
|
||||||
|
#define MG_SDIO_FBR_FnBLKSZ(n) (((n) &7) * 0x100 + 0x10) // 2 registers
|
||||||
|
|
||||||
|
// SDIO 5.1 IO_RW_DIRECT Command (CMD52)
|
||||||
|
#define MG_SDIO_DATA(x) ((x) &0xFF) // bits 0-7
|
||||||
|
#define MG_SDIO_ADDR(x) (((x) &0x1FFFF) << 9) // bits 9-25
|
||||||
|
#define MG_SDIO_FUNC(x) (((x) &3) << 28) // bits 28-30 (30 unused here)
|
||||||
|
#define MG_SDIO_WR MG_BIT(31)
|
||||||
|
|
||||||
|
// SDIO 5.3 IO_RW_EXTENDED Command (CMD53)
|
||||||
|
#define MG_SDIO_LEN(x) ((x) &0x1FF) // bits 0-8
|
||||||
|
#define MG_SDIO_OPINC MG_BIT(26)
|
||||||
|
#define MG_SDIO_BLKMODE MG_BIT(27)
|
||||||
|
|
||||||
|
// - Drivers set blocksize, drivers request transfers. Requesting a read
|
||||||
|
// transfer > blocksize means block transfer will be used.
|
||||||
|
// - To simplify the use of DMA transfers and avoid intermediate buffers,
|
||||||
|
// drivers must have room to accomodate a whole block transfer, e.g.: blocksize
|
||||||
|
// = 64, read 65 => 2 blocks = 128 bytes
|
||||||
|
// - Transfers of more than 1 byte assume (uint32_t *) data. 1-byte transfers
|
||||||
|
// use (uint8_t *) data
|
||||||
|
// - 'len' is the number of _bytes_ to transfer
|
||||||
|
bool mg_sdio_transfer(struct mg_tcpip_sdio *sdio, bool write, unsigned int f,
|
||||||
|
uint32_t addr, void *data, uint32_t len) {
|
||||||
|
uint32_t arg, val = 0;
|
||||||
|
unsigned int blksz = 64; // TODO(): mg_sdio_set_blksz() stores in an array,
|
||||||
|
// index on f, skip if 0
|
||||||
|
if (len == 1) {
|
||||||
|
arg = (write ? MG_SDIO_WR : 0) | MG_SDIO_FUNC(f) | MG_SDIO_ADDR(addr) |
|
||||||
|
(write ? MG_SDIO_DATA(*(uint8_t *) data) : 0);
|
||||||
|
bool res = sdio->txn(sdio, 52, arg, &val); // IO_RW_DIRECT
|
||||||
|
if (!write) *(uint8_t *) data = (uint8_t) val;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
// IO_RW_EXTENDED
|
||||||
|
arg = (write ? MG_SDIO_WR : 0) | MG_SDIO_OPINC | MG_SDIO_FUNC(f) |
|
||||||
|
MG_SDIO_ADDR(addr);
|
||||||
|
if (len > 512 || (blksz != 0 && len > blksz)) { // SDIO 5.3 512 -> len=0
|
||||||
|
unsigned int blkcnt;
|
||||||
|
if (blksz == 0) return false; // > 512 requires block size set
|
||||||
|
blkcnt = (len + blksz - 1) / blksz;
|
||||||
|
if (blkcnt > 511) return false; // we don't support "infinite" blocks
|
||||||
|
arg |= MG_SDIO_BLKMODE | MG_SDIO_LEN(blkcnt); // block transfer
|
||||||
|
len = blksz * blkcnt;
|
||||||
|
} else {
|
||||||
|
arg |= MG_SDIO_LEN(len); // multi-byte transfer
|
||||||
|
}
|
||||||
|
return sdio->xfr(sdio, write, arg,
|
||||||
|
(arg & MG_SDIO_BLKMODE) ? (uint16_t) blksz : 0,
|
||||||
|
(uint32_t *) data, len, &val);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mg_sdio_set_blksz(struct mg_tcpip_sdio *sdio, unsigned int f,
|
||||||
|
uint16_t blksz) {
|
||||||
|
uint32_t val = blksz & 0xff;
|
||||||
|
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_FBR_FnBLKSZ(f), &val, 1))
|
||||||
|
return false;
|
||||||
|
val = (blksz >> 8) & 0x0f; // SDIO 6.10 Table 6-4, max 2048
|
||||||
|
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_FBR_FnBLKSZ(f) + 1, &val, 1))
|
||||||
|
return false;
|
||||||
|
// TODO(): store in an array, index on f. Static 8-element array
|
||||||
|
MG_VERBOSE(("F%c block size set", (f & 7) + '0'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable Fx
|
||||||
|
bool mg_sdio_enable_f(struct mg_tcpip_sdio *sdio, unsigned int f) {
|
||||||
|
uint8_t bit = 1U << (f & 7), bits;
|
||||||
|
uint32_t val = 0;
|
||||||
|
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IOEN, &val, 1))
|
||||||
|
return false;
|
||||||
|
bits = (uint8_t) val | bit;
|
||||||
|
unsigned int times = 501;
|
||||||
|
while (times--) {
|
||||||
|
val = bits; /* IOEf */
|
||||||
|
;
|
||||||
|
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_IOEN, &val, 1))
|
||||||
|
return false;
|
||||||
|
mg_delayms(1);
|
||||||
|
val = 0;
|
||||||
|
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IOEN, &val, 1))
|
||||||
|
return false;
|
||||||
|
if (val & bit) break;
|
||||||
|
}
|
||||||
|
if (times == (unsigned int) ~0) return false;
|
||||||
|
MG_VERBOSE(("F%c enabled", (f & 7) + '0'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for Fx to be ready
|
||||||
|
bool mg_sdio_waitready_f(struct mg_tcpip_sdio *sdio, unsigned int f) {
|
||||||
|
uint8_t bit = 1U << (f & 7);
|
||||||
|
unsigned int times = 501;
|
||||||
|
while (times--) {
|
||||||
|
uint32_t val;
|
||||||
|
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_IORDY, &val, 1))
|
||||||
|
return false;
|
||||||
|
if (val & bit) break; // IORf
|
||||||
|
mg_delayms(1);
|
||||||
|
}
|
||||||
|
if (times == (unsigned int) ~0) return false;
|
||||||
|
MG_VERBOSE(("F%c ready", (f & 7) + '0'));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDIO 6.14 Bus State Diagram
|
||||||
|
bool mg_sdio_init(struct mg_tcpip_sdio *sdio) {
|
||||||
|
uint32_t val = 0;
|
||||||
|
if (!sdio->txn(sdio, 0, 0, NULL)) return false; // GO_IDLE_STATE
|
||||||
|
sdio->txn(sdio, 5, 0, &val); // IO_SEND_OP_COND, no CRC
|
||||||
|
MG_VERBOSE(("IO Functions: %u, Memory: %c", 1 + ((val >> 28) & 7),
|
||||||
|
(val & MG_BIT(27)) ? 'Y' : 'N'));
|
||||||
|
if (!sdio->txn(sdio, 3, 0, &val)) return false; // SEND_RELATIVE_ADDR
|
||||||
|
val = ((uint32_t) val) >> 16; // RCA
|
||||||
|
if (!sdio->txn(sdio, 7, val << 16, &val))
|
||||||
|
return false; // SELECT/DESELECT_CARD
|
||||||
|
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_SDIOREV, &val, 1);
|
||||||
|
MG_DEBUG(("CCCR: %u.%u, SDIO: %u.%u", 1 + ((val >> 2) & 3), (val >> 0) & 3,
|
||||||
|
1 + ((val >> 6) & 3), (val >> 4) & 3));
|
||||||
|
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_SDREV, &val, 1);
|
||||||
|
MG_VERBOSE(("SD: %u.%u", 1 + ((val >> 2) & 3), (val >> 0) & 3));
|
||||||
|
mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_BIC, &val, 1);
|
||||||
|
MG_SET_BITS(val, 3,
|
||||||
|
MG_BIT(7) | MG_BIT(1)); // SDIO 6.9 Tables 6-1 6-2, 4-bit bus
|
||||||
|
mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_BIC, &val, 1);
|
||||||
|
// All Full-Speed SDIO cards support a 4-bit bus. Skip for Low-Speed SDIO
|
||||||
|
// cards, we don't provide separate low-level functions for width and speed
|
||||||
|
sdio->cfg(sdio, 0); // set DS;
|
||||||
|
if (!mg_sdio_transfer(sdio, false, 0, MG_SDIO_CCCR_HISPD, &val, 1))
|
||||||
|
return false;
|
||||||
|
if (val & MG_BIT(0) /* SHS */) {
|
||||||
|
val = MG_BIT(1); /* EHS */
|
||||||
|
if (!mg_sdio_transfer(sdio, true, 0, MG_SDIO_CCCR_HISPD, &val, 1))
|
||||||
|
return false;
|
||||||
|
sdio->cfg(sdio, 1); // set HS;
|
||||||
|
MG_VERBOSE(("Bus set to 4-bit @50MHz"));
|
||||||
|
} else {
|
||||||
|
MG_VERBOSE(("Bus set to 4-bit @25MHz"));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// - 6.11 Card Information Structure (CIS): 0x0001000-0x017FF; for card common
|
||||||
|
// and all functions
|
||||||
|
// - 16.5 SDIO Card Metaformat
|
||||||
|
// - 16.7.2 CISTPL_FUNCE (0x22): Function Extension Tuple, provides standard
|
||||||
|
// information about the card (common) and each individual function. One
|
||||||
|
// CISTPL_FUNCE in each function’s CIS, immediately following the CISTPL_FUNCID
|
||||||
|
// tuple
|
||||||
|
// - 16.7.3 CISTPL_FUNCE Tuple for Function 0 (common)
|
||||||
|
// - 16.7.4 CISTPL_FUNCE Tuple for Function 1-7
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if MG_ENABLE_TCPIP && \
|
||||||
|
(defined(MG_ENABLE_DRIVER_CYW_SDIO) && MG_ENABLE_DRIVER_CYW_SDIO)
|
||||||
|
|
||||||
|
// Specific chip/card driver --> SDIO driver --> HAL --> SDIO hw controller
|
||||||
|
|
||||||
|
// API with HAL for hardware controller
|
||||||
|
// - Provide a function to init the controller (external)
|
||||||
|
// - Provide these functions:
|
||||||
|
struct mg_tcpip_sdio {
|
||||||
|
void *sdio; // Opaque SDIO bus descriptor
|
||||||
|
void (*cfg)(void *, uint8_t); // select operating parameters
|
||||||
|
// SDIO transaction: send cmd with a possible 1-byte read or write
|
||||||
|
bool (*txn)(void *, uint8_t cmd, uint32_t arg, uint32_t *r);
|
||||||
|
// SDIO extended transaction: write or read len bytes, using blksz blocks
|
||||||
|
bool (*xfr)(void *, bool write, uint32_t arg, uint16_t blksz, uint32_t *,
|
||||||
|
uint32_t len, uint32_t *r);
|
||||||
|
};
|
||||||
|
|
||||||
|
// API with driver (e.g.: cyw.c)
|
||||||
|
// Once the hardware controller has been initialized:
|
||||||
|
// - Init card: selects the card, sets F0 block size, sets bus width and speed
|
||||||
|
bool mg_sdio_init(struct mg_tcpip_sdio *sdio);
|
||||||
|
// - Enable other possible functions (F1 to F7)
|
||||||
|
bool mg_sdio_enable_f(struct mg_tcpip_sdio *sdio, unsigned int f);
|
||||||
|
// - Wait for them to be ready
|
||||||
|
bool mg_sdio_waitready_f(struct mg_tcpip_sdio *sdio, unsigned int f);
|
||||||
|
// - Set their transfer block length
|
||||||
|
bool mg_sdio_set_blksz(struct mg_tcpip_sdio *sdio, unsigned int f,
|
||||||
|
uint16_t blksz);
|
||||||
|
// - Transfer data to/from a function (abstracts from transaction type)
|
||||||
|
// - Requesting a read transfer > blocksize means block transfer will be used.
|
||||||
|
// - Drivers must have room to accomodate a whole block transfer, see sdio.c
|
||||||
|
// - Transfers of > 1 byte --> (uint32_t *) data. 1-byte --> (uint8_t *) data
|
||||||
|
bool mg_sdio_transfer(struct mg_tcpip_sdio *sdio, bool write, unsigned int f,
|
||||||
|
uint32_t addr, void *data, uint32_t len);
|
||||||
|
|
||||||
|
#endif
|
||||||
Loaded 100 of 4000 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user