From dfb86f939ca34fe0fb353c4ae3e0ec8796cf5a92 Mon Sep 17 00:00:00 2001 From: Yilin Sun Date: Sun, 21 May 2023 18:43:13 +0800 Subject: [PATCH] Updated IDF, connect to TB. Signed-off-by: Yilin Sun --- .clang-format | 12 ++ .gitignore | 6 + CMakeLists.txt | 4 - assets/ca/ca-bundle.pem | 124 ++++++++------- assets/client.crt | 29 ---- assets/client.key | 31 ---- main/CMakeLists.txt | 1 + main/Kconfig.projbuild | 18 +-- main/aht10/aht10.h | 9 +- main/app_dht.c | 72 +++------ main/app_mqtt.c | 213 ++++++++++++++++++-------- main/app_report_rb.c | 107 +++++++++++++ main/app_wifi.c | 58 ++++--- main/include/app_dht.h | 1 + main/include/app_mqtt.h | 3 +- main/include/app_report_rb.h | 18 +++ main/include/app_wifi.h | 10 +- main/main.c | 284 +++++++++++++++++++++++++++++++++-- partitions.csv | 12 +- pytest_hello_world.py | 22 --- sdkconfig.ci | 0 sdkconfig.defaults | 7 +- tools/gen_credentials.rb | 23 +++ 23 files changed, 732 insertions(+), 332 deletions(-) create mode 100644 .clang-format create mode 100644 .gitignore delete mode 100644 assets/client.crt delete mode 100644 assets/client.key create mode 100644 main/app_report_rb.c create mode 100644 main/include/app_report_rb.h delete mode 100644 pytest_hello_world.py delete mode 100644 sdkconfig.ci create mode 100644 tools/gen_credentials.rb diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..214adf0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,12 @@ +BasedOnStyle: Google +IndentWidth: 4 +AlignConsecutiveMacros: Consecutive +AlignConsecutiveDeclarations: Consecutive +AlignConsecutiveAssignments: Consecutive +AllowShortFunctionsOnASingleLine: None +BreakBeforeBraces: Custom +BraceWrapping: + AfterEnum: false + AfterStruct: false + SplitEmptyFunction: false +ColumnLimit: 120 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed6e74e --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/assets/certs +/build +/cmake-build-* +/managed_components +/sdkconfig +/sdkconfig.old diff --git a/CMakeLists.txt b/CMakeLists.txt index 00f5b3f..d0ac48d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,3 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(dht_temp) - -# Add client certificate, private key and CA bundle to project: -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "assets/client.crt" TEXT) -target_add_binary_data(${CMAKE_PROJECT_NAME}.elf "assets/client.key" TEXT) diff --git a/assets/ca/ca-bundle.pem b/assets/ca/ca-bundle.pem index 6dea76a..c007ff7 100644 --- a/assets/ca/ca-bundle.pem +++ b/assets/ca/ca-bundle.pem @@ -1,68 +1,64 @@ -----BEGIN CERTIFICATE----- -MIIF1DCCA7ygAwIBAgIBATANBgkqhkiG9w0BAQsFADB7MRMwEQYKCZImiZPyLGQB -GRYDbW9lMRMwEQYKCZImiZPyLGQBGRYDaW1pMQ8wDQYDVQQKDAZpTS5JbmMxHjAc -BgNVBAsMFWlNLkluYyBJb1QgUm9vdCBDQSBHMjEeMBwGA1UEAwwVaU0uSW5jIElv -VCBSb290IENBIEcyMB4XDTIwMTEyMTEyMTk0NVoXDTMwMTEyMTEyMTk0NVowezET -MBEGCgmSJomT8ixkARkWA21vZTETMBEGCgmSJomT8ixkARkWA2ltaTEPMA0GA1UE -CgwGaU0uSW5jMR4wHAYDVQQLDBVpTS5JbmMgSW9UIFJvb3QgQ0EgRzIxHjAcBgNV -BAMMFWlNLkluYyBJb1QgUm9vdCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBAOjHqAyz7LVqG0yQV6aEaoaEIXaF3dK5vr/in4vyu/ylp7aBmJi0 -UkFV1TYbaT4EEGguYaigyOWPUlyIgrDDMdpEGefNeLPh2wiPeHGe7NBsu/7PcyD6 -1eoM7tKX11C6LtoMpH7hTudfRBj86xUqXib0KofbnqvtwcihbEj60M/TWqafwflJ -hO5tBzpq4Tgcj8UFRYN7SSKgUG9XI00sH8g3WBKwIPfAI8lbr7UfDvbuIAyedzCp -7wYQbfY6SQWl9ORig6b50TnJpJQa4J3dwi/d0I0wJmKMLUD1OXSzwYSP/0ra6hx0 -0VAy/HqWD6aPea/Pt+yp7RrtoLhmNRmOg65vrguYDffUc4SLm/A77yWmjFyx5Nla -G/NgltND9YbD/hD3URyKlXMiKvBCJkXiQnnUcAkVOSp8SftsZZnIOH1yTsKDQ5Ya -m/CufjUQNrA7cPszwjRLPnNTiTN7YBYIPzr+6rpHfCYT2RFQ6+s9c0xBwgZGleLh -XAa0Ky/JadU1trpOYwQn5m+HWrDyYivE32PfddSumUbiNOPxQzmePFcZ4YPiqWhf -DDB+miFr7Nc+r2ptGUBDXGt1bOojtVGqxMMQGmqIz93JQs5jgn1kltcakwyZSYQL -htplyOlXMDqieMYIgKnLnnTd8un5nCFfVJzPnKRNUANW9A1htLfpAHu5AgMBAAGj -YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQd -mQ8/CUEz8dt/eS2ROb6Ng8HS7DAfBgNVHSMEGDAWgBQdmQ8/CUEz8dt/eS2ROb6N -g8HS7DANBgkqhkiG9w0BAQsFAAOCAgEAQIoSPNiVeKA8kuGv44KskhCxAyKyjaRZ -muLSYiOeHVI8EqywsFNN8ObMx1zvQwGbNlKjMDIE4o0H1S+CsSpCWMWDLybYCIyN -w2InHE25SXJks/vz5B9sP1PDZ1ekDD0X4CrqFqEpd0aQxg/4ykl+zEov/+ivC8Y4 -TN7/CtGO6rxIM+yG7hQZBj8VZmIURc90+Nb9RMSSx6or8zt0NCz1fEqc7M/MLtxj -FvSu8Dcm8YT+yaXhGtRQscH9aXb4J3iOXm2G4//WgYuJ5bjo3CFuSyqFtvhGWwOP -A7DsK/yS+Wx/ZXMqCDp2lCU2s1Fmav3b47iqBvZUESYgwq8gOSslM9W8MnwaaylZ -+DO2ij+ISNJgURFbDFENxll2fTrSS7gMXaMdXB15PEng/DthsE6j5vJrWpUAXqei -KBnA9UYrkg/6s+H7yKDEh/YLaWA2EyIzWV/EE6ZTcdbMfuFz1sPKJRxqNgWfWOr1 -gO3c4UVWv3hs1ooj4DQV/4tHodh9Q+lbZNpzq1Jxgx+A4I/TODhnf/2W1bAehWOu -RZ/7QI+Hd5TZ0pDpHnyMu03i2Felo25Tff2i78Lypxw0bjCCvr/uP6NV7jLDOYST -US7IDJgrvAycyZNADuW2qpzMmpdMj4HP3axG6O7Y1qR7g3ExiVk679nWEhubdSsD -OBsrrOf8vtk= +MIIFsDCCA5igAwIBAgIIV8SXmpyaArYwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE +BhMCQ04xDzANBgNVBAoTBmlNLkluYzEMMAoGA1UECxMDSW9UMRswGQYDVQQDExJp +TS5JbmMgSW9UIFJvb3QgRzMwHhcNMjMwNTIxMDI1NTAwWhcNMjgwNTIxMDI1NTAw +WjBMMQswCQYDVQQGEwJDTjEPMA0GA1UEChMGaU0uSW5jMQwwCgYDVQQLEwNJb1Qx +HjAcBgNVBAMTFWlNLkluYyBJb1QgR2VuZXJhbCBDQTCCAiIwDQYJKoZIhvcNAQEB +BQADggIPADCCAgoCggIBAJjgX2un2L1LVIbZO9uGvMLxFOy8Z+27drWw7pBAV4eO +OpRsxW2Ai8xiHtdSz5fwSlPEIoBG0TsPS2NczNdlpUkjX3Io6kC+hoGonAwVueki +kIaap3rx5XeJtzOiLvWFrPJF6iKzkHZ77fDRrmeeALJ7goYH9s+QZhkQFkyqA1Ft +8isLY4dORXD0ZahWJvSq3n2scpspmkC3a+WYsIjx91YLUKh3AmNw8umsMfqVSu5P +22V4olmTZHXMZTjR/WKu4/WsNMPcdj9zR6xVu17T92wIrkQKxKZxvQDVtL2jYULG +YHPvCJjhskiiA5O/ERnTGmQU9tb1E76AQMnLTwvSB60fOBUlQVaMly7PfxTGrZpC +J8f/pc70j8qTN7HqPmEFcFTymaHI7UTrbj6oCAp0oalLQ/II+yFlGJnJ/9DGbfGX +qzJCJqe9sx20yFPVd1/lcKhHpC+bF6e2/eoN0ATuSUi2PWBVseQaJY7TkDoUTTP3 +6016G6mfSHGDO07QeWysBC/Sq+2ngO4obsyhx02NAXRBBQ5X3jcdRlnfKHO/30zN +yU9BA4EMFwkZG8udP63ndvq6yokjW71QGgK6SUEO/QMIWJAkOo8GMv2nNsUE5DSF +psBhIMObp2A8AY42zV7bPPx3Rn8lVKpTzxEsO1SNPQKMvbdkLIbY1uLv6Z9j8npT +AgMBAAGjgZgwgZUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUh+j/sQfC +RNTcHUZUPxUC0Q/WqxcwDgYDVR0PAQH/BAQDAgEGMB0GA1UdJQQWMBQGCCsGAQUF +BwMBBggrBgEFBQcDAjARBglghkgBhvhCAQEEBAMCAAcwHgYJYIZIAYb4QgENBBEW +D3hjYSBjZXJ0aWZpY2F0ZTANBgkqhkiG9w0BAQsFAAOCAgEAI6n4BQO7Y75a7Evk +NH58tcjUvHVb5vKHg3i2+UV36hTiXHdcWaDpq1fgeDUMHetdLn9YEH8EXaCUisYA +chmQ1o5OMyp+vU6rC9hhCPkREYdGRRO6lHjXw40v+nCtKl8oDKgDbC+qgaczNM3J +397bL6kYUhEHHuE8zZqhCSw9iZOJubEB3gQ1J8K91rvZqCXstOAQ9nqFZkxZQu1y +rbDxXr3xc7TEj33Jct2DlB5T6J/wAXEkVhwXafrjz+FQfkNHyMNcNZbYFKDioNGA +/JDYvKoUN/K7ZZtDh7ldCLIANZswIb+zAU2URnxIMJVdM5u8tkcy6qDO2SwI1766 +1xyB61qNcupI+kUgxwXQ5DfWGrBQZ6HpYO+77pH5yuPnFlFwORvblhn+kk6VpoWe +NYfHBQjDBq0iCutX/oGB4sA3Iwh8QLQIGka+0MYoWM5AtygMU6byHpzm2JdfsVCJ +YJVAFxVpgfy82s7iWWorHimLlkeNpjdovTLK+fZhz6o24ZoYCWvyEbHuvFrR9ct0 +tSP50Ulf9Vb7qQ+w94rplVe09K8jIfi7i4OPWR4aSX1VqtOBZ36tsjxuD+uCs2Ok +ZPOWwxkSbJMkfvzG03IFfmjQp0dolT9Ev9wyp6qrJVVZZydzqJO5qAzYqafLtU3O +9WslzbtdtaD4TSXd2OvbRehTPsU= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -MIIF1zCCA7+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADB7MRMwEQYKCZImiZPyLGQB -GRYDbW9lMRMwEQYKCZImiZPyLGQBGRYDaW1pMQ8wDQYDVQQKDAZpTS5JbmMxHjAc -BgNVBAsMFWlNLkluYyBJb1QgUm9vdCBDQSBHMjEeMBwGA1UEAwwVaU0uSW5jIElv -VCBSb290IENBIEcyMB4XDTIwMTEyMTEyMjAxNloXDTMwMTEyMTEyMjAxNlowezET -MBEGCgmSJomT8ixkARkWA21vZTETMBEGCgmSJomT8ixkARkWA2ltaTEPMA0GA1UE -CgwGaU0uSW5jMR4wHAYDVQQLDBVpTS5JbmMgSW9UIFNpZ25pbmcgQ0ExHjAcBgNV -BAMMFWlNLkluYyBJb1QgU2lnbmluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP -ADCCAgoCggIBALrdwJEXhTNlb6WIN0BC+5zYD8BsLk3QiHswtnGbFG6JjCMtW6KO -U7EjN1i5LfJjHuZyqy7s2ztDFeMsTAdUq6qSInaZxoAxG0wJ0FvL13wHoab9Y454 -5MIWjOWgV30RwD6D74IxJz43+4GOnzwZipD6G2Qok6jEYeLDOsO0r/idYaEfrz81 -U8+845jeifDVMW+ZCsc6770hKNl+SbtsrpI1Gef2UtMf7W/gxQOILv05b5YOYODC -RqJZ2LnTZyZklzWhFxUqqSFbRoxsqEZppcVQR926c86VslKyuKuuLcVHaN53KkF0 -W2fGnHvFQrHV9UZfOn0RQiaFe91uZrXf5nufeNYHJznDiQ+Lvm+0ywJ+oEaTn1sp -/ZW+qOJ7Af9QuF5CXzdlbR/eTTub+40sSIiHp93NxFUswZAbcKew9/YnW6VxDMkG -uaaYQNEY3vEOtocAu1ReBwPnp0v5nI7iOOMZuBki81tjO7oOjl6V5mw2iRUnICfc -Y/jKp49YT+L7y/6wB+0uY6xQyR+dcVF+0ANHgGsu1l4vMaOI7DzIzbVagGL1fsJR -WP7sdERiinO9kgx0FxKz8okYxQ0+JpDgjVkwuvXRc4neW55gRXv/3PKrAW8JRSCk -ve8/L/JFxAbnQH0hsV66ehQGJuTxl5EvzC+ljSq8h2qdcGNhMWP4SSopAgMBAAGj -ZjBkMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW -BBT6gJ+WDsxRWpAg8gM+Ro8abstW7jAfBgNVHSMEGDAWgBQdmQ8/CUEz8dt/eS2R -Ob6Ng8HS7DANBgkqhkiG9w0BAQsFAAOCAgEAlT8CkihB4u4WWL6py5xGBKSnz0KZ -5Fx/OJuqOe5LloMs7TFQsU0rDogx+CD9DVStIeJqyk0v3SK3JTpghVgMfZC+me+h -8PNIL30ZOjMF/+BolGzcTDqwNXpFdqL9A8V+C2+grJw81EdHl6ap6/jBwqAWato3 -xpElWxSFaF8MkJwns/Dr2e8u9IH+jcWXrueaY8lYI3i+sLUDCBG1Z0jvu7thSDRV -lYywVUFIMGZz91BkmBtAYasXSo2fWjXJNwjpu0f+stlig5YuxmZ7CAfxrzMNllUM -6mJ+rJj4KTCD1DUChAUlGn++SCpXon+4drjp3fmilnF5PUKQ4NVlLuMTIta2OO/k -CeEbyKORmiUCKpnbzouOz6Pl6alW3PSlmU2qP58gYSbDa7OSyP1xb0e4gD9Wh7d5 -UlD9oDxQyWRLD40K669IfZoXZVnQoefGvxjhPJse5XYD/4w6Pnf83ZG6pzXl6kxL -/+zx4uGc4Wwnl/GAZ/YbVvudB3zMRuwQwpG/WDuXYAyGoep5znIAe39i0KUj2M8/ -cBBXYLO/XmsFK/CL/FZ+J8qYS6EqwUTWb1g2xvonkVIAHPpyFvk21pn22jwGOpFB -pPSeIQhhKQ4wKQnIONWfmVUs+058i6VRFUFkqHYwWmchYNFB96IxTRfdQRpV0YKC -DXBx2FuyJRFR9As= +MIIFbDCCA1SgAwIBAgIIARtSAxfPbhEwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE +BhMCQ04xDzANBgNVBAoTBmlNLkluYzEMMAoGA1UECxMDSW9UMRswGQYDVQQDExJp +TS5JbmMgSW9UIFJvb3QgRzMwHhcNMjMwNTIxMDI0OTAwWhcNNDMwNTIxMDI0OTAw +WjBJMQswCQYDVQQGEwJDTjEPMA0GA1UEChMGaU0uSW5jMQwwCgYDVQQLEwNJb1Qx +GzAZBgNVBAMTEmlNLkluYyBJb1QgUm9vdCBHMzCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMhol1Ne58LkklAUhUsaohwZDFaeeddemHKwvaF0gQ3xfF1Z +49Zf0OMpgPcjmZhZFySRoSblX7ZIoNt42DShTiTQSESwhszeLpOJ2Ls2uJKVkdIn +qyspcUnHk02MtGf9MLvPC+JVM5nal2rV5pM7gqvR4Um4qfjIEBKYnHxx451Mg9QF +lnsOFurnPMEZGbS0DwbeLqCvDo1/8f0DIAxRLixetPjzfjXkR8CKd7Khqvy/fbou +TeV2nHFvWTlFyJjbVqj8XOdVMA97o13lKrdFDom1tf2r4QUywoe6tpbgeEWmxddn +8MSeA8rBB8HdeyzB2NaYoFa0vZG6pvVlbG07YNJ6Y+wLj3Rjid5WuhkN0YMYg7M5 +WNNkaOHa4V6Y8sAQvznBfdJsktxtaatPY9BWQEpJOzfycGZXZMWp5JmRCwFBtaRG +/Wk7f8aLTx+eu5/57pmeW9t1nNHnJKuFQggzRwzqB3f+ghKIw4FfIrAGrxaoT4Lw +DbB5KBS4SieJ20lOz3qtPkJDmOtuu3oHJnrPEZXWO5GXbBe59FCoLlDOtOZJqXuH +Ft3ZkzCYEDgZy94XmgDwAPhEOH0+1kVJ+7sX90y7wGaCyiGh9eoS39tqZl2NR980 +7qUA4yIzDF6KxC/cvUwIdZfO64OHLYai9+lZ5+5GYOe4e+ct58/CZUwQIfGVAgMB +AAGjWDBWMBIGA1UdEwEB/wQIMAYBAf8CAQMwHQYDVR0OBBYEFBkJ75xuhZoReb/k +QvuF1qq0uJxvMA4GA1UdDwEB/wQEAwIBBjARBglghkgBhvhCAQEEBAMCAAcwDQYJ +KoZIhvcNAQELBQADggIBAKu6tobcojcwhOwNhRZE6+aDcZA3lpNVTKZ34FkgSQXf +FNwCurS2kkYOfrZ912Yt/b0ScJ7uQG0NDV+LyzewcO0IV//LkvompQHLhowaTRHG +4NfQ/3sjv3vg3kgro8dEQfDSApC6kif9wZ6ATaM9kxjqrLEbJK3zBjy4IVqh61Zs +xl8QxqOUX4oXH6TiTpuyyFHq3kNEsEHpkGASer4y0RV/frz6+7UoypCdnyLmHDJL +4jJeMmvdgSCwjGBEIxlL1Zt5DUo7TiQXGEhpbiyayMywvqmis8RTG0XikYFqC/3o +rbKOxiyt4ij4L3LrmZc/iCKMjoZhFnExcS39gkLj4AMnDqTVQx8vW57Uam+UR0E2 +P5UBxgLOzoHircv50dtL7wds7UtzFF5GsogMZjaT+S2xTr/T+pjNRxVFO39flf+y +BmPoS3Kbv0Efbl8XMxKYolVDf7Vb4IG+WdkJJgA+ioAKzrs8ZumT58ihm5NNWQtw +q+RFuXLlHnA3ILubGzalT0iwYHdDTnNLr4N/APcwqlxQqjyC0ieuO15+b6x6S8wx +vKTtx1Kwo+1MMsrreh2KjFmn8Y/krWmqI4a/5bDFbqX7ZeR5eAU9WG/RNeZITbgI +34uqEApf6gPNv/sTIIBPXm9T6hpAcKwNNDhWbU0RrpAGKiCu54H2Gxzc1qJahASX -----END CERTIFICATE----- diff --git a/assets/client.crt b/assets/client.crt deleted file mode 100644 index 1162675..0000000 --- a/assets/client.crt +++ /dev/null @@ -1,29 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIE5jCCAs6gAwIBAgIBBDANBgkqhkiG9w0BAQsFADB7MRMwEQYKCZImiZPyLGQB -GRYDbW9lMRMwEQYKCZImiZPyLGQBGRYDaW1pMQ8wDQYDVQQKDAZpTS5JbmMxHjAc -BgNVBAsMFWlNLkluYyBJb1QgU2lnbmluZyBDQTEeMBwGA1UEAwwVaU0uSW5jIElv -VCBTaWduaW5nIENBMB4XDTIyMDcwNDEzNDkxNVoXDTI0MDcwMzEzNDkxNVowZzET -MBEGCgmSJomT8ixkARkWA21vZTETMBEGCgmSJomT8ixkARkWA2ltaTEPMA0GA1UE -CgwGaU0uSW5jMRMwEQYDVQQLDApJb1QgU3lzdGVtMRUwEwYDVQQDDAxFU1BfREhU -X1RlbXAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtKqSGU7OsJQKE -/ap3FWFS8d9P0ZPDhwr8FBfGnU9Os9tuERENM7mDFdAISUiKD3t3xfGX+hOLStYm -9A0vZtWoq6Qhl2pPd7O7yi7Jw5OLSlNmoovClp78dyA82ECszYsEp32fw6nSbhmL -YKTZMYYcdGQO96NWUXvHjuimpCbcUeaDD8yad2TYkb57na3DJp+UNxdf+mvR2beY -RGkmsIn84UP9edmV2lPgx8rNQOGH8mxTMDtU4D0taQF+n/2W/awi+yMtsdjf811+ -CwSipyVvo8Sb2zl3IHBcI2uD3gSpJ6pjMkExB6TnO+bE3o4iby+iBAmm9rREiO5l -y9WmGYsfAgMBAAGjgYgwgYUwDgYDVR0PAQH/BAQDAgeAMAkGA1UdEwQCMAAwEwYD -VR0lBAwwCgYIKwYBBQUHAwIwHQYDVR0OBBYEFPealnfk4PmDut1rni1pUF5c7lPq -MB8GA1UdIwQYMBaAFPqAn5YOzFFakCDyAz5Gjxpuy1buMBMGA1UdEQQMMAqCCGRo -dF90ZW1wMA0GCSqGSIb3DQEBCwUAA4ICAQAFwWkFP/qrYamU7JCRsReW0BTtPxQD -qPYkdff7IO5mwXcbJZKK9HaueCtItMgl8l9SUMdiNdHETodOAuTRtjI9vaDm1bai -nnQdxNYUQHDZc0NHurTKzLr7gTlE61Hk84Y6Erd/AiwfyqT+832jCinjS3bpY37s -rWMxRbo1Abe+4V/+giV4Qqk5yYUHyevkO2zliyCk1FLpczRAGYBvQFBN+2Ggvimj -lcGhi6O5UCUgqbral3pgNgJ3W0ZPCZqd03B4aaauTvQ7QHk3d++kc/RYanHuWaD+ -SEVgMVv13pG7ITggQxoRgKv51sNFcib3WZeJnisIQ4CnzILVaKTNbHKOg0K2YCk0 -xnfcESJazQiaGHC0PFoVBqdO3NP/ISstr6vltJ1hHP6hUeOii0zJXbecD+I5rnsN -L6UapEfWvP+/Wt0Hv2ROp8Y2vPkjn9MXCgv5+MsbafnlpP98C8aifexgeygTXZGJ -pQCeqD39ZMvLwoMHjD9y+Qn6prJHrOAaH41S0mmYF7UirRjVVUp9J8BAnfTLhvgX -0CCWVipPChXM3r+w4j2+/Y7KuBuOtmPxLDVp6d/Tf96Bg33ZvD2GY7PetPeB7j5x -Ps+5+9X8cVfNUngzf8LlwTNDsUmECDXpLWri8rRfBBJiGT0CP4EqELvhTrle4uu3 -8PHQZfCgDH9WJQ== ------END CERTIFICATE----- diff --git a/assets/client.key b/assets/client.key deleted file mode 100644 index 64467ba..0000000 --- a/assets/client.key +++ /dev/null @@ -1,31 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -Proc-Type: 4,ENCRYPTED -DEK-Info: AES-256-CBC,18E77130CD1EB69EB57399009D3AED8D - -wEtOb6CifHIbPIXUnIWxUVkwyMWx0B4/y6JGEN//1v6zS0tvLKwKw0kUp6ZQlZEU -mHujXTIP4u/4X1Na6SacibDHeNi4GYP1T3Sp4rc1xKFTU4lQ4FlCXMmmGOKm05gZ -gFXyxqOjBlqYkqWYZnh+C2YEov6xX/OrAkZcSzQ6onjgwsrpbfQffiMxt1zDjCl9 -OsDp3xn1TLmwH33oy1qpqxvn2TxETh+gF2HLWqQtnF4dugxun11E/PCiHCTT0QCP -E/xh4EJvUXtW7kwvqRW2kXFwnrRUzGTLnBfDGTEte9Dh1bJN+/tcmU7noU+WIw7j -0CzTfOMHv5tF1KcowLSU67Nofx7L3jWD2Ac6bwZv1uWlCJEltRO0G1WCcoDAw/Ha -SWCzk9CEf8x80IObAjgC3C3cdZfTYnfonMgdBC9yK1dS5zllq9Q4EbNPvhbjNz4L -UggiXEfu3N9DFvt0EZVGeqipqIThs7wJBiYp9WK7yruMeTRmSPbNlu1nITiwQEcy -bFC8nGU5QCt0mBymAxQ4YXeMdTmIbartuSoTivyNkgkzWOkGKjDP5oxb8F0ENCb8 -a2Dbu4kXIgTJSVj4w1Hy/UiNiQSKEjlVNJwHm6WDEB7VC2GlfNeVKfhpfAxTAl4F -xF69A+aUalcT7pCOMtS5gPJCFHM+Up73fBnm5Ahh5psvNlIA0ZwjElVxkQCdrGDw -EUG0b7VurSe1+nnYoq+7LlUGMNAUb4VZkFofOG+3SszoKaK5CFwgLliWiQNByJSz -C0Wm8qDqUQNWAP5f0dKkNxCz7HP/lgmm6ZHwMIWzUWmgynHPre805ZM8zKkdA6eE -7WeUzdovl4skSG4DaSULXROXsHfnO4xySi+xc8pIYujBbmKOOqvwsN4trqz2kY9j -dSYrj12DGvvl1PCZQVCyUzVAsGGQLK4nRsf5viKLP5ghWa1MIA4/3Dlf5QxIIFPl -03+vRUjdOxtQssOZ1huyQA2Bvimw1nvRr2l4XJtgLbwkls7ikUot+rKMOn11QGCp -SVynTr2xL6XsvZy9pFt3TxcVmyuIu0DWsDx2Mc0I/vSMsXPmHLaBGNk8T8FLT3Y4 -r1e2iPnwRuS4POsXr0VS4d+U0SbV51O3+OL2kD6iCS06UJE/XGJG1PhS1PgbNDPI -nmcr1ZRTTFDwmpgvdrQg+kAXW4OcsjCdFxeD6XnZaZRHpNjkNXIKSsd3N1j0DDJn -qFhHuWkJtRLCdssEQ8BNCHPfrSNID4NOnDJaP35hO5EulMqYleojKHoq2zPDpJiV -fl4HnuhQseiv5RxyF/XKfwZjG+nojI7IfQWEvQQ4Ny3jGzEmuXPYnh/wxgHSUhtq -B4wDfStM+YBixIXP6WKc+YpAgkxHoOpOtxX1RfrzcQr/4vciPIzvlMHWEl241Pq+ -TPx9VT7FBsxf2CK0vfTWvOnInctg1FAJLO55rvC4Dk/ME0s/PSr6L+tIGADan38B -H3Xa1A72JhE3IKLdwjQud4kjIFhPVTaM14f3WbuRjb+/Xa7ATFAAlooY/d0KG4we -uB9qkU70SgXVCVxuE0almKQBEYoZFDO6tkZ/LGWo+uKd0wLpnmjRgCn/eMpAa5If ------END RSA PRIVATE KEY----- - diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index fd2ed3f..b46f769 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -2,6 +2,7 @@ idf_component_register( SRCS "app_dht.c" "app_mqtt.c" + "app_report_rb.c" "app_wifi.c" "main.c" "aht10/aht10.c" diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index edf77bf..2bcfb72 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -1,4 +1,4 @@ -menu "Application Configuration" +menu "Application specific configuration" config APP_I2C_SCL_PIN int "I2C SCL IO number" default 22 @@ -21,29 +21,17 @@ menu "Application Configuration" string "WiFi SSID" default "myssid" help - SSID (network name) for the application to connect to. + SSID for the access point. config APP_WIFI_PASSWORD string "WiFi Password" default "mypassword" help - WiFi password (WPA or WPA2) for the application to use. - - config APP_MAXIMUM_RETRY - int "Maximum retry" - default 5 - help - Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent. + Password for the access point. config APP_MQTT_BROKER_ADDR string "MQTT broker connection string" default "mqtt://127.0.0.1:1883" help Connection string for MQTT broker, use scheme://host:port format. - - config APP_MQTT_TLS_CLIENT_PASSPHRASE - string "MQTT TLS Client Passphrase" - default "AAAAAAAAAAAAAAAA" - help - Passphrase to decrypt MQTT client private key. endmenu diff --git a/main/aht10/aht10.h b/main/aht10/aht10.h index f83ddef..6714808 100644 --- a/main/aht10/aht10.h +++ b/main/aht10/aht10.h @@ -21,22 +21,21 @@ typedef aht10_ret_t (*aht10_i2c_xfer_t)(void *pdev, aht10_xfer_desc_t *xfer); typedef aht10_ret_t (*aht10_delay_t)(void *pdev, uint32_t delay_msec); typedef struct { - double temperature; - double humidity; + float temperature; + float humidity; } aht10_result_t; typedef struct { aht10_i2c_xfer_t xfer; - aht10_delay_t delay; + aht10_delay_t delay; } aht10_cb_t; typedef struct { aht10_cb_t cb; - void *user_data; + void *user_data; } aht10_t; aht10_ret_t aht10_init(aht10_t *aht); aht10_ret_t aht10_measure(aht10_t *aht, aht10_result_t *result); - #endif \ No newline at end of file diff --git a/main/app_dht.c b/main/app_dht.c index 70b4d73..6d2e263 100644 --- a/main/app_dht.c +++ b/main/app_dht.c @@ -12,7 +12,7 @@ /* MQTT */ #include "app_mqtt.h" -/* AHT10 */ +/* DHT sensor */ #include "aht10/aht10.h" /* Log tag */ @@ -25,29 +25,25 @@ #define APP_DHT_I2C_TIMEOUT 100 #define APP_DHT_AHT10_ADDR 0x38 -#define INFLUX_TOPIC "iot/metric" -#define INFLUX_HOSTNAME "DHT_Temp" -#define INFLUX_FORMATTED_STRING \ - "dht,hostname=" INFLUX_HOSTNAME \ - " " \ - "temperature=%.02lf," \ - "humidity=%.02lf" \ - " " \ - "%llu" - -static void app_dht_task(void *pvParameters); -static uint64_t app_get_nsec_timestamp(void); static aht10_ret_t app_dht_impl_xfer(void *pdev, aht10_xfer_desc_t *xfer); static aht10_ret_t app_dht_impl_delay(void *pdev, uint32_t delay_msec); +static aht10_t aht = { + .cb = + { + .xfer = app_dht_impl_xfer, + .delay = app_dht_impl_delay, + }, +}; + esp_err_t app_dht_init(void) { i2c_config_t cfg = { .mode = I2C_MODE_MASTER, .sda_io_num = APP_DHT_I2C_SDA_IO, .scl_io_num = APP_DHT_I2C_SCL_IO, - .sda_pullup_en = GPIO_PULLUP_DISABLE, - .scl_pullup_en = GPIO_PULLUP_DISABLE, - .master.clk_speed = 400000, + .sda_pullup_en = GPIO_PULLUP_ENABLE, + .scl_pullup_en = GPIO_PULLUP_ENABLE, + .master.clk_speed = 100000, }; i2c_param_config(APP_DHT_I2C_INSTANCE, &cfg); @@ -56,46 +52,22 @@ esp_err_t app_dht_init(void) { return ESP_FAIL; } - if (xTaskCreate(app_dht_task, "DHT_TASK", 2048, NULL, 1U, NULL) != pdPASS) { - return ESP_FAIL; - } - + aht10_init(&aht); return ESP_OK; } -static void app_dht_task(void *pvParameters) { - aht10_t aht = { - .cb = - { - .xfer = app_dht_impl_xfer, - .delay = app_dht_impl_delay, - }, - }; - - aht10_init(&aht); +esp_err_t app_dht_read(float *temperature, float *humidity) { + esp_err_t ret = ESP_OK; aht10_result_t result; - char report_buf[256]; - uint64_t ns_ts; - - for (;;) { - aht10_measure(&aht, &result); - ns_ts = app_get_nsec_timestamp(); - - /* Simple check to see if NTP is synchronized... */ - if (ns_ts > (uint64_t)(1600000000L) * 1000000000) { - snprintf(report_buf, 256, INFLUX_FORMATTED_STRING, result.temperature, result.humidity, ns_ts); - app_mqtt_publish(INFLUX_TOPIC, report_buf); - } - vTaskDelay(pdMS_TO_TICKS(500)); + if (aht10_measure(&aht, &result) != AHT10_OK) { + return -1; } -} -static uint64_t app_get_nsec_timestamp(void) { - struct timeval tv_now; - gettimeofday(&tv_now, NULL); - int64_t time_ns = (int64_t)tv_now.tv_sec * 1000000000L + (int64_t)tv_now.tv_usec * 1000; - return time_ns; + *temperature = result.temperature; + *humidity = result.humidity; + + return ret; } static aht10_ret_t app_dht_impl_xfer(void *pdev, aht10_xfer_desc_t *xfer) { @@ -122,4 +94,4 @@ static aht10_ret_t app_dht_impl_delay(void *pdev, uint32_t delay_msec) { vTaskDelay(pdMS_TO_TICKS(delay_msec)); return AHT10_OK; -} \ No newline at end of file +} diff --git a/main/app_mqtt.c b/main/app_mqtt.c index b40f96b..72b5357 100644 --- a/main/app_mqtt.c +++ b/main/app_mqtt.c @@ -1,11 +1,12 @@ /* ESP drivers */ #include "esp_log.h" +#include "esp_partition.h" #include "esp_system.h" #include "esp_tls.h" /* FreeRTOS */ #include "freertos/FreeRTOS.h" -#include "freertos/queue.h" +#include "freertos/semphr.h" #include "freertos/task.h" /* Cert bundle */ @@ -14,87 +15,167 @@ /* MQTT client */ #include "mqtt_client.h" -#define APP_LOG_TAG "APP_MQTT" +#define LOG_TAG "APP_MQTT" + +#define APP_MQTT_PART_TYPE ((esp_partition_type_t)0x40) +#define APP_MQTT_PART_CRT_NAME "tls_crt" +#define APP_MQTT_PART_KEY_NAME "tls_key" +#define APP_MQTT_PART_CRT_SUBTYPE 0x00 +#define APP_MQTT_PART_KEY_SUBTYPE 0x01 +#define APP_MQTT_PART_HEADER_VALID_SIGNATURE (0x66CCFFAA) typedef struct { - char *topic; - char *payload; -} app_mqtt_queue_item_t; + uint32_t signature; + uint32_t length; + char data; +} app_mqtt_part_header_t; -extern const char mqtt_client_cert_start[] asm("_binary_client_crt_start"); -extern const char mqtt_client_cert_end[] asm("_binary_client_crt_end"); -extern const char mqtt_client_key_start[] asm("_binary_client_key_start"); -extern const char mqtt_client_key_end[] asm("_binary_client_key_end"); +static SemaphoreHandle_t s_mqtt_semaphore; + +static esp_mqtt_client_handle_t s_mqtt_client; +static esp_partition_mmap_handle_t s_mqtt_crt_mmap_handle; +static esp_partition_mmap_handle_t s_mqtt_key_mmap_handle; static void app_mqtt_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); -static void app_mqtt_task(void *pvParameters); -static QueueHandle_t s_app_mqtt_publish_queue; +esp_err_t app_mqtt_init(uint32_t timeout_ms) { + esp_err_t ret = ESP_OK; -esp_err_t app_mqtt_init(void) { - s_app_mqtt_publish_queue = xQueueCreate(4, sizeof(app_mqtt_queue_item_t)); - if(s_app_mqtt_publish_queue == NULL) { - return ESP_FAIL; + s_mqtt_semaphore = xSemaphoreCreateBinary(); + if (s_mqtt_semaphore == NULL) { + ESP_LOGE(LOG_TAG, "Failed to create semaphore"); + return ESP_ERR_NO_MEM; } - if (xTaskCreate(app_mqtt_task, "MQ_TASK", 2048, NULL, 2U, NULL) != pdPASS) { - return ESP_FAIL; + const esp_partition_t *part_crt = + esp_partition_find_first(APP_MQTT_PART_TYPE, APP_MQTT_PART_CRT_SUBTYPE, APP_MQTT_PART_CRT_NAME); + + const esp_partition_t *part_key = + esp_partition_find_first(APP_MQTT_PART_TYPE, APP_MQTT_PART_KEY_SUBTYPE, APP_MQTT_PART_KEY_NAME); + + if (part_crt == NULL) { + ESP_LOGE(LOG_TAG, "Failed to find certificate partition."); + goto destroy_semaphore_exit; } + ESP_LOGI(LOG_TAG, "Found certificate partition at 0x%08lx", part_crt->address); + + if (part_key == NULL) { + ESP_LOGE(LOG_TAG, "Failed to find key partition."); + goto destroy_semaphore_exit; + } + + ESP_LOGI(LOG_TAG, "Found key partition at 0x%08lx", part_key->address); + + app_mqtt_part_header_t *ptr_crt; + app_mqtt_part_header_t *ptr_key; + + ret = esp_partition_mmap(part_crt, 0, part_crt->size, ESP_PARTITION_MMAP_DATA, (const void **)(&ptr_crt), + &s_mqtt_crt_mmap_handle); + if (ret != ESP_OK) { + ESP_LOGE(LOG_TAG, "Failed to map certificate partition"); + goto destroy_semaphore_exit; + } + + ret = esp_partition_mmap(part_key, 0, part_key->size, ESP_PARTITION_MMAP_DATA, (const void **)(&ptr_key), + &s_mqtt_key_mmap_handle); + if (ret != ESP_OK) { + ESP_LOGE(LOG_TAG, "Failed to map key partition"); + goto unmap_cert_exit; + } + + if (ptr_crt->signature != APP_MQTT_PART_HEADER_VALID_SIGNATURE) { + ESP_LOGE(LOG_TAG, "Certificate partition content is invalid"); + goto unmap_cert_exit; + } + + ESP_LOGI(LOG_TAG, "Certificate length: %ld", ptr_crt->length); + + if (ptr_key->signature != APP_MQTT_PART_HEADER_VALID_SIGNATURE) { + ESP_LOGE(LOG_TAG, "Key partition content is invalid"); + goto unmap_cert_exit; + } + + ESP_LOGI(LOG_TAG, "Key length: %ld", ptr_key->length); + + const esp_mqtt_client_config_t mqtt_cfg = { + .broker = + { + .address.uri = CONFIG_APP_MQTT_BROKER_ADDR, + .verification.crt_bundle_attach = esp_crt_bundle_attach, + }, + .credentials.authentication = + { + .certificate = &ptr_crt->data, + .key = &ptr_key->data, + }, + }; + + s_mqtt_client = esp_mqtt_client_init(&mqtt_cfg); + if (s_mqtt_client == NULL) { + ret = ESP_ERR_NO_MEM; + goto unmap_cert_exit; + } + + ret = esp_mqtt_client_register_event(s_mqtt_client, ESP_EVENT_ANY_ID, app_mqtt_event_handler, NULL); + if (ret != ESP_OK) { + ESP_LOGE(LOG_TAG, "Failed to register MQTT event."); + goto destroy_client_exit; + } + + ret = esp_mqtt_client_start(s_mqtt_client); + if (ret != ESP_OK) { + ESP_LOGE(LOG_TAG, "Failed to start MQTT client."); + goto destroy_client_exit; + } + + if (xSemaphoreTake(s_mqtt_semaphore, pdMS_TO_TICKS(timeout_ms)) != pdPASS) { + ESP_LOGE(LOG_TAG, "Failed to connect to broker in time."); + goto destroy_client_exit; + } + + return ESP_OK; + +destroy_client_exit: + esp_mqtt_client_destroy(s_mqtt_client); + +unmap_cert_exit: + esp_partition_munmap(s_mqtt_crt_mmap_handle); + +destroy_semaphore_exit: + vSemaphoreDelete(s_mqtt_semaphore); + + return ret; +} + +esp_err_t app_mqtt_deinit(void) { + esp_err_t ret; + esp_mqtt_client_stop(s_mqtt_client); + + ret = esp_mqtt_client_destroy(s_mqtt_client); + if (ret != ESP_OK) { + return ret; + } + + vSemaphoreDelete(s_mqtt_semaphore); + + esp_partition_munmap(s_mqtt_crt_mmap_handle); + esp_partition_munmap(s_mqtt_key_mmap_handle); + return ESP_OK; } esp_err_t app_mqtt_publish(char *topic, char *payload) { - app_mqtt_queue_item_t item; - item.topic = malloc(strlen(topic) + 1); - if(item.topic == NULL) return ESP_FAIL; - - item.payload = malloc(strlen(payload) + 1); - if(item.payload == NULL) { - free(item.topic); - return ESP_FAIL; - } - - strcpy(item.topic, topic); - strcpy(item.payload, payload); - - if(xQueueSend(s_app_mqtt_publish_queue, &item, portMAX_DELAY) != pdPASS) { - free(item.topic); - free(item.payload); - return ESP_FAIL; - } - - return ESP_OK; -} - -static void app_mqtt_task(void *pvParameters) { - const esp_mqtt_client_config_t mqtt_cfg = { - .uri = CONFIG_APP_MQTT_BROKER_ADDR, - .client_cert_pem = mqtt_client_cert_start, - .client_key_pem = mqtt_client_key_start, - .clientkey_password = CONFIG_APP_MQTT_TLS_CLIENT_PASSPHRASE, - .clientkey_password_len = strlen(CONFIG_APP_MQTT_TLS_CLIENT_PASSPHRASE), - .crt_bundle_attach = esp_crt_bundle_attach, - }; - - esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); - esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, app_mqtt_event_handler, NULL); - - esp_mqtt_client_start(client); - - app_mqtt_queue_item_t item; - - for (;;) { - if(xQueueReceive(s_app_mqtt_publish_queue, &item, portMAX_DELAY) == pdPASS) { - esp_mqtt_client_publish(client, item.topic, item.payload, strlen(item.payload), 0, 0); - - /* This is alloc'ed by us. */ - free(item.topic); - free(item.payload); - } - } + return esp_mqtt_client_publish(s_mqtt_client, topic, payload, (int)strlen(payload), 0, 0); } static void app_mqtt_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { - /**/ + switch ((esp_mqtt_event_id_t)event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(LOG_TAG, "Connected to broker."); + xSemaphoreGive(s_mqtt_semaphore); + break; + default: + break; + } } \ No newline at end of file diff --git a/main/app_report_rb.c b/main/app_report_rb.c new file mode 100644 index 0000000..3210f09 --- /dev/null +++ b/main/app_report_rb.c @@ -0,0 +1,107 @@ +#include + +/* FreeRTOS */ +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/task.h" + +/* App */ +#include "app_report_rb.h" + +#define APP_REPORT_RB_SIZE 4800 + +static app_report_rb_t s_report_rb[APP_REPORT_RB_SIZE]; +static volatile uint32_t s_report_rb_rptr = 0U; +static volatile uint32_t s_report_rb_wptr = 0U; + +static SemaphoreHandle_t s_report_rb_semphr = NULL; + +int app_report_rb_init(void) { + s_report_rb_semphr = xSemaphoreCreateMutex(); + if (s_report_rb_semphr == NULL) { + return -1; + } + + s_report_rb_rptr = 0U; + s_report_rb_wptr = 0U; + + return 0; +} + +void app_report_rb_append(app_report_rb_t *rpt) { + if (xSemaphoreTake(s_report_rb_semphr, portMAX_DELAY) != pdPASS) { + return; + } + + memcpy(&s_report_rb[s_report_rb_wptr], rpt, sizeof(app_report_rb_t)); + + if (s_report_rb_wptr < APP_REPORT_RB_SIZE - 1) { + s_report_rb_wptr++; + } else { + s_report_rb_wptr = 0UL; + } + + xSemaphoreGive(s_report_rb_semphr); +} + +void app_report_rb_consume(app_report_rb_t *rpt) { + if (xSemaphoreTake(s_report_rb_semphr, portMAX_DELAY) != pdPASS) { + return; + } + + memcpy(rpt, &s_report_rb[s_report_rb_rptr], sizeof(app_report_rb_t)); + + if (s_report_rb_rptr < APP_REPORT_RB_SIZE - 1) { + s_report_rb_rptr++; + } else { + s_report_rb_rptr = 0UL; + } + + xSemaphoreGive(s_report_rb_semphr); +} + +void app_report_rb_flush(void) { + if (xSemaphoreTake(s_report_rb_semphr, portMAX_DELAY) != pdPASS) { + return; + } + + s_report_rb_wptr = 0U; + s_report_rb_rptr = 0U; + + xSemaphoreGive(s_report_rb_semphr); +} + +uint32_t app_report_rb_get_count(void) { + uint32_t ret = 0; + + if (xSemaphoreTake(s_report_rb_semphr, portMAX_DELAY) != pdPASS) { + return ret; + } + + if (s_report_rb_wptr >= s_report_rb_rptr) { + ret = s_report_rb_wptr - s_report_rb_rptr; + } else { + ret = (APP_REPORT_RB_SIZE - s_report_rb_rptr) + s_report_rb_wptr; + } + + xSemaphoreGive(s_report_rb_semphr); + + return ret; +} + +uint32_t app_report_rb_get_total_size(void) { + return APP_REPORT_RB_SIZE; +} + +void app_report_rb_discard(uint32_t num) { + if (num > app_report_rb_get_count()) { + return; + } + + uint32_t tmp_ptr = s_report_rb_wptr + num; + if (tmp_ptr > APP_REPORT_RB_SIZE) { + tmp_ptr -= APP_REPORT_RB_SIZE; + } + + s_report_rb_wptr = tmp_ptr; +} diff --git a/main/app_wifi.c b/main/app_wifi.c index dfdf33b..5fc6aa3 100644 --- a/main/app_wifi.c +++ b/main/app_wifi.c @@ -14,21 +14,24 @@ #define APP_LOG_TAG "APP_WIFI" -EventGroupHandle_t g_app_wifi_event_group; +#define APP_WIFI_EVENT_GROUP_EVENT_CONNECTED (1 << 0U) -static uint8_t s_retries = 0U; +EventGroupHandle_t s_app_wifi_event_group; + +static uint8_t s_retries = 0U; +static esp_netif_t *s_sta_netif; static void app_wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data); esp_err_t app_wifi_init(void) { - g_app_wifi_event_group = xEventGroupCreate(); - if (g_app_wifi_event_group == NULL) { + s_app_wifi_event_group = xEventGroupCreate(); + if (s_app_wifi_event_group == NULL) { return ESP_FAIL; } ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); - esp_netif_create_default_wifi_sta(); + s_sta_netif = esp_netif_create_default_wifi_sta(); wifi_init_config_t wifi_init_cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&wifi_init_cfg)); @@ -55,11 +58,34 @@ esp_err_t app_wifi_init(void) { ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); - ESP_LOGI(APP_LOG_TAG, "WiFi initialized, heap free: %d.", esp_get_free_heap_size()); + ESP_LOGI(APP_LOG_TAG, "WiFi initialized, heap free: %lu.", esp_get_free_heap_size()); return ESP_OK; } +esp_err_t app_wifi_deinit(void) { + esp_wifi_stop(); + esp_wifi_deinit(); + + esp_netif_destroy_default_wifi(s_sta_netif); + + esp_event_loop_delete_default(); + vEventGroupDelete(s_app_wifi_event_group); + + return ESP_OK; +} + +app_wifi_event_t app_wifi_wait_event(uint32_t max_timeout_ms) { + EventBits_t bits = xEventGroupWaitBits(s_app_wifi_event_group, APP_WIFI_EVENT_GROUP_EVENT_CONNECTED, pdFALSE, + pdFALSE, pdMS_TO_TICKS(max_timeout_ms)); + + if (bits & APP_WIFI_EVENT_GROUP_EVENT_CONNECTED) { + return APP_WIFI_EVENT_CONNECTED; + } else { + return APP_WIFI_EVENT_TIMEOUT; + } +} + static void app_wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { /* Event handler */ @@ -69,25 +95,17 @@ static void app_wifi_event_handler(void *arg, esp_event_base_t event_base, int32 } if (event_id == WIFI_EVENT_STA_DISCONNECTED) { - if (s_retries < CONFIG_APP_MAXIMUM_RETRY) { - esp_wifi_connect(); - s_retries++; - - ESP_LOGI(APP_LOG_TAG, "Connection lost, retrying #%d/%d...", s_retries, CONFIG_APP_MAXIMUM_RETRY); - } else { - xEventGroupSetBits(g_app_wifi_event_group, APP_WIFI_EVENT_GROUP_EVENT_FAILED); - - ESP_LOGW(APP_LOG_TAG, "Connection lost, maximum retries reached."); - } + esp_wifi_connect(); + ESP_LOGI(APP_LOG_TAG, "Disconnected"); } - } else if(event_base == IP_EVENT) { - if(event_id == IP_EVENT_STA_GOT_IP) { - xEventGroupSetBits(g_app_wifi_event_group, APP_WIFI_EVENT_GROUP_EVENT_CONNECTED); + } else if (event_base == IP_EVENT) { + if (event_id == IP_EVENT_STA_GOT_IP) { + xEventGroupSetBits(s_app_wifi_event_group, APP_WIFI_EVENT_GROUP_EVENT_CONNECTED); s_retries = 0U; ip_event_got_ip_t *event = event_data; - ESP_LOGI(APP_LOG_TAG, "Connected, IP address: "IPSTR, IP2STR(&event->ip_info.ip)); + ESP_LOGI(APP_LOG_TAG, "Connected, IP address: " IPSTR, IP2STR(&event->ip_info.ip)); } } } diff --git a/main/include/app_dht.h b/main/include/app_dht.h index 092a58d..6aa705f 100644 --- a/main/include/app_dht.h +++ b/main/include/app_dht.h @@ -4,5 +4,6 @@ #include "esp_system.h" esp_err_t app_dht_init(void); +esp_err_t app_dht_read(float *temperature, float *humidity); #endif \ No newline at end of file diff --git a/main/include/app_mqtt.h b/main/include/app_mqtt.h index bdfa5a1..e4390fe 100644 --- a/main/include/app_mqtt.h +++ b/main/include/app_mqtt.h @@ -3,7 +3,8 @@ #include "esp_system.h" -esp_err_t app_mqtt_init(void); +esp_err_t app_mqtt_init(uint32_t timeout_ms); +esp_err_t app_mqtt_deinit(void); esp_err_t app_mqtt_publish(char *topic, char *payload); #endif \ No newline at end of file diff --git a/main/include/app_report_rb.h b/main/include/app_report_rb.h new file mode 100644 index 0000000..e08d7cf --- /dev/null +++ b/main/include/app_report_rb.h @@ -0,0 +1,18 @@ +#ifndef APP_REPORT_RB_H +#define APP_REPORT_RB_H + +typedef struct { + uint64_t ts; + uint32_t voltage; + float temperature; + float humidity; +} app_report_rb_t; + +int app_report_rb_init(void); +void app_report_rb_append(app_report_rb_t *rpt); +void app_report_rb_consume(app_report_rb_t *rpt); +uint32_t app_report_rb_get_count(void); +uint32_t app_report_rb_get_total_size(void); +void app_report_rb_flush(void); + +#endif // APP_REPORT_RB_H diff --git a/main/include/app_wifi.h b/main/include/app_wifi.h index d6d9f9a..0a2c064 100644 --- a/main/include/app_wifi.h +++ b/main/include/app_wifi.h @@ -8,11 +8,13 @@ #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" -#define APP_WIFI_EVENT_GROUP_EVENT_CONNECTED (1 << 0U) -#define APP_WIFI_EVENT_GROUP_EVENT_FAILED (1 << 1U) - -extern EventGroupHandle_t g_app_wifi_event_group; +typedef enum { + APP_WIFI_EVENT_TIMEOUT, + APP_WIFI_EVENT_CONNECTED, +} app_wifi_event_t; esp_err_t app_wifi_init(void); +esp_err_t app_wifi_deinit(void); +app_wifi_event_t app_wifi_wait_event(uint32_t max_timeout_ms); #endif \ No newline at end of file diff --git a/main/main.c b/main/main.c index 42ad371..bebecb8 100644 --- a/main/main.c +++ b/main/main.c @@ -4,10 +4,17 @@ * SPDX-License-Identifier: CC0-1.0 */ +#include #include +#include /* ESP drivers */ +#include "driver/gpio.h" +#include "esp_adc/adc_cali.h" +#include "esp_adc/adc_cali_scheme.h" +#include "esp_adc/adc_oneshot.h" #include "esp_log.h" +#include "esp_sleep.h" #include "esp_sntp.h" /* FreeRTOS */ @@ -18,43 +25,290 @@ #include "nvs_flash.h" /* Config */ -#include "app_dht.h" -#include "app_mqtt.h" -#include "app_wifi.h" #include "sdkconfig.h" -#define APP_LOG_TAG "APP_MAIN" +/* App */ +#include "app_dht.h" +#include "app_mqtt.h" +#include "app_report_rb.h" +#include "app_wifi.h" + +#define LOG_TAG "APP_MAIN" + +#define APP_WIFI_TIMEOUT_SECS 120 +#define APP_MQTT_TIMEOUT_SECS 10 +#define APP_SNTP_TIMEOUT_SECS 60 + +#define APP_SENSOR_INTERVAL_SECS 1 +#define APP_SENSOR_REPORT_TRIGGER_POINTS 20 /* Count of the trigger points which triggers telemetry reporting */ +#define APP_SENSOR_REPORT_WATERMARK_PERCENT 80 /* when the buffer reaches this watermark in each trigger point */ +#define APP_SENSOR_REPORT_CRITICAL_PERCENT 95 /* Critical level, when this is reached, reports will be flushed */ + +/* Report interval: (RB Size / Nr. Trigger Points) * (Watermark / 100) * Interval secs */ + +#define APP_LED_PIN 16 +#define APP_ADC_CH ADC_CHANNEL_6 + +static void app_report_task(void *pvParameters); + +static uint64_t app_get_msec_timestamp(void); + +static void app_led_init(void); +static void app_led_set(uint8_t on); + +static void app_adc_init(void); +static uint32_t app_adc_read(void); + +static volatile uint8_t s_report_task_running = 0; +static adc_oneshot_unit_handle_t s_adc_handle; +static adc_cali_handle_t s_adc_cal_handle = NULL; void app_main(void) { - printf("Hello world!\n"); + esp_err_t ret; - esp_err_t ret = nvs_flash_init(); + ESP_LOGI(LOG_TAG, "Main application started."); + + ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_LOGW(LOG_TAG, "NVS content appears to be corrupted or outdated, erase and recreate NVS structure."); + + /* Erase NVS region and give it another try. */ ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); - - ESP_LOGW(APP_LOG_TAG, "NVS content corrupted or outdated, cleared."); } + /* NVS initialization reported failure, this should not happen. In this case, abort! */ ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(app_wifi_init()); - EventBits_t bits = xEventGroupWaitBits(g_app_wifi_event_group, - APP_WIFI_EVENT_GROUP_EVENT_CONNECTED | APP_WIFI_EVENT_GROUP_EVENT_FAILED, - pdFALSE, pdFALSE, portMAX_DELAY); + app_wifi_event_t a_wifi_evt = app_wifi_wait_event(APP_WIFI_TIMEOUT_SECS * 1000); + if (a_wifi_evt != APP_WIFI_EVENT_CONNECTED) { + ESP_LOGE(LOG_TAG, "WiFi failed to come up within time limit."); - if (bits & APP_WIFI_EVENT_GROUP_EVENT_FAILED) { - return; + esp_restart(); } + /* On first start, we need to know the actual start time for timestamp tracking in report */ sntp_setoperatingmode(SNTP_OPMODE_POLL); sntp_setservername(0, CONFIG_APP_SNTP_POOL_ADDR); sntp_init(); - ESP_ERROR_CHECK(app_mqtt_init()); + uint16_t sntp_trials = APP_SNTP_TIMEOUT_SECS; + + /* If the NTP does not finish synchronization in 10 seconds... Required for initial boot up */ + while (sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED) { + vTaskDelay(pdMS_TO_TICKS(1000)); + + sntp_trials--; + if (sntp_trials == 0U) { + ESP_LOGE(LOG_TAG, "Failed to synchronize NTP in-time."); + + esp_restart(); + } + } + + sntp_stop(); + + ESP_ERROR_CHECK(app_mqtt_init(APP_MQTT_TIMEOUT_SECS * 1000)); + ESP_ERROR_CHECK(app_mqtt_deinit()); + + /* + * We have acquired NTP time, de-init Wi-Fi. + * Something terribly wrong happens if this function is not completed successfully. + */ + ESP_ERROR_CHECK(app_wifi_deinit()); + + /* Some indication... */ + app_led_init(); + app_adc_init(); + + /* Initialize DHT sensors, abort if error occurs */ ESP_ERROR_CHECK(app_dht_init()); - /* This task will be deleted if this function returns. */ + if (app_report_rb_init() < 0) { + ESP_LOGE(LOG_TAG, "Failed to init RB"); + + esp_restart(); + } + + app_report_rb_t rpt; + + for (;;) { + app_led_set(1); + ret = app_dht_read(&rpt.temperature, &rpt.humidity); + if (ret != ESP_OK) { + continue; + } + + rpt.voltage = app_adc_read() * 2; + app_led_set(0); + + rpt.ts = app_get_msec_timestamp(); + + app_report_rb_append(&rpt); + + uint32_t current_count = app_report_rb_get_count(); + uint32_t rb_size = app_report_rb_get_total_size(); + + if (current_count % 10 == 0) { + ESP_LOGI(LOG_TAG, "Last: %.2fC, %.2f%%", rpt.temperature, rpt.humidity); + ESP_LOGI(LOG_TAG, "RB level: %lu%%", current_count * 100 / rb_size); + ESP_LOGI(LOG_TAG, "Battery voltage: %lumV", rpt.voltage); + } + + /** + * Trigger report task at each threshold point or above the last threshold point. + * If the last threshold trigger failed, the ring buffer will be cleared. + */ + + uint32_t rb_trigger_level = rb_size / APP_SENSOR_REPORT_TRIGGER_POINTS; + uint32_t rb_trigger_watermark = rb_trigger_level * APP_SENSOR_REPORT_WATERMARK_PERCENT / 100; + uint32_t rb_critical_point = rb_size * APP_SENSOR_REPORT_CRITICAL_PERCENT / 100; + + if (((current_count % rb_trigger_level) == rb_trigger_watermark) || (current_count > rb_critical_point)) { + if (!s_report_task_running) { + xTaskCreate(app_report_task, "RPT_TASK", 4096, NULL, 4, NULL); + s_report_task_running = 1U; + } + } + + if (s_report_task_running) { + vTaskDelay(pdMS_TO_TICKS(1000)); + } else { + esp_sleep_enable_timer_wakeup(APP_SENSOR_INTERVAL_SECS * 1000 * 1000); + esp_light_sleep_start(); + esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); + } + } } + +static void app_report_task(void *pvParameters) { + app_report_rb_t rpt; + char *rpt_buffer; + + ESP_ERROR_CHECK(app_wifi_init()); + app_wifi_event_t a_wifi_evt = app_wifi_wait_event(APP_WIFI_TIMEOUT_SECS * 1000); + if (a_wifi_evt != APP_WIFI_EVENT_CONNECTED) { + ESP_LOGE(LOG_TAG, "WiFi failed to come up within time limit."); + + goto drop_data_exit; + } + + sntp_init(); + + uint16_t sntp_trials = APP_SNTP_TIMEOUT_SECS; + + /* If the NTP does not finish synchronization in 10 seconds... Required for initial boot up */ + while (sntp_get_sync_status() != SNTP_SYNC_STATUS_COMPLETED) { + vTaskDelay(pdMS_TO_TICKS(1000)); + + sntp_trials--; + if (sntp_trials == 0U) { + ESP_LOGE(LOG_TAG, "Failed to synchronize NTP in-time."); + + goto stop_sntp_exit; + } + } + + ESP_ERROR_CHECK(app_mqtt_init(APP_MQTT_TIMEOUT_SECS * 1000)); + + rpt_buffer = malloc(512); + + while (app_report_rb_get_count() > 0) { + app_report_rb_consume(&rpt); + + // TODO: Create new report + // app_mqtt_publish(INFLUX_TOPIC, rpt_buffer); + } + + free(rpt_buffer); + + ESP_ERROR_CHECK(app_mqtt_deinit()); + + sntp_stop(); + + ESP_ERROR_CHECK(app_wifi_deinit()); + + s_report_task_running = 0U; + + vTaskDelete(NULL); + + return; + +stop_sntp_exit: + sntp_stop(); + +drop_data_exit: + ESP_ERROR_CHECK(app_wifi_deinit()); + + /* Flush ring buffer */ + if (app_report_rb_get_count() > (app_report_rb_get_total_size() * APP_SENSOR_REPORT_CRITICAL_PERCENT / 100)) { + app_report_rb_flush(); + } + + s_report_task_running = 0U; + + vTaskDelete(NULL); +} + +static uint64_t app_get_msec_timestamp(void) { + struct timeval tv_now; + gettimeofday(&tv_now, NULL); + uint64_t time_ms = (int64_t)tv_now.tv_sec * 1000 + (int64_t)tv_now.tv_usec / 1000; + return time_ms; +} + +static void app_adc_init(void) { + adc_oneshot_unit_init_cfg_t init_cfg = { + .unit_id = ADC_UNIT_1, + }; + + ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_cfg, &s_adc_handle)); + + adc_oneshot_chan_cfg_t chan_cfg = { + .atten = ADC_ATTEN_DB_11, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + + ESP_ERROR_CHECK(adc_oneshot_config_channel(s_adc_handle, APP_ADC_CH, &chan_cfg)); + + adc_cali_line_fitting_config_t cali_config = { + .unit_id = ADC_UNIT_1, + .atten = ADC_ATTEN_DB_11, + .bitwidth = ADC_BITWIDTH_DEFAULT, + }; + ESP_ERROR_CHECK(adc_cali_create_scheme_line_fitting(&cali_config, &s_adc_cal_handle)); +} + +static uint32_t app_adc_read(void) { + int result; + int voltage; + + ESP_ERROR_CHECK(adc_oneshot_read(s_adc_handle, APP_ADC_CH, &result)); + ESP_ERROR_CHECK(adc_cali_raw_to_voltage(s_adc_cal_handle, result, &voltage)); + + return voltage; +} + +static void app_led_init(void) { + gpio_config_t io_cfg = { + .mode = GPIO_MODE_OUTPUT_OD, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .pin_bit_mask = (1U << APP_LED_PIN), + .intr_type = GPIO_INTR_DISABLE, + }; + + gpio_config(&io_cfg); + gpio_set_level(APP_LED_PIN, 1); +} + +static void app_led_set(uint8_t on) { + if (on) { + gpio_set_level(APP_LED_PIN, 0); + } else { + gpio_set_level(APP_LED_PIN, 1); + } +} \ No newline at end of file diff --git a/partitions.csv b/partitions.csv index e8b4a69..f744d5a 100644 --- a/partitions.csv +++ b/partitions.csv @@ -1,5 +1,9 @@ # ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x6000, -phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 3M, \ No newline at end of file +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x00009000, 0x00004000, +otadata, data, ota, 0x0000d000, 0x00002000, +phy_init, data, phy, 0x0000f000, 0x00001000, +ota_0, app, ota_0, 0x00010000, 0x00180000, +ota_1, app, ota_1, 0x00190000, 0x00180000, +tls_crt, 0x40, 0x00, 0x00310000, 0x00008000, +tls_key, 0x40, 0x01, 0x00318000, 0x00008000, \ No newline at end of file diff --git a/pytest_hello_world.py b/pytest_hello_world.py deleted file mode 100644 index 3cb161c..0000000 --- a/pytest_hello_world.py +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: CC0-1.0 - -from typing import Callable - -import pytest -from pytest_embedded_idf.dut import IdfDut -from pytest_embedded_qemu.dut import QemuDut - - -@pytest.mark.supported_targets -@pytest.mark.generic -def test_hello_world(dut: IdfDut, log_minimum_free_heap_size: Callable[..., None]) -> None: - dut.expect('Hello world!') - log_minimum_free_heap_size() - - -@pytest.mark.esp32 # we only support qemu on esp32 for now -@pytest.mark.host_test -@pytest.mark.qemu -def test_hello_world_host(dut: QemuDut) -> None: - dut.expect('Hello world!') diff --git a/sdkconfig.ci b/sdkconfig.ci deleted file mode 100644 index e69de29..0000000 diff --git a/sdkconfig.defaults b/sdkconfig.defaults index edc2f42..2756632 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -1,11 +1,14 @@ # Minimum flash size set to 4MB CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y -# Use custom partition table, 3MB application. +# Use custom partition table CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" # Custom CA bundle for mbedTLS +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=16384 +CONFIG_MBEDTLS_DYNAMIC_BUFFER=y +CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y -CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="assets/ca" \ No newline at end of file +CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="assets/ca" diff --git a/tools/gen_credentials.rb b/tools/gen_credentials.rb new file mode 100644 index 0000000..b46301b --- /dev/null +++ b/tools/gen_credentials.rb @@ -0,0 +1,23 @@ +if ARGV.length < 1 then + puts 'No parameter given' + exit 255 +end + +File.open(ARGV[0], 'r') do |f| + raw_size = f.size + + puts "Credential file size: #{raw_size}" + + hdr = [0xAA, 0xFF, 0xCC, 0x66] + + hdr.push raw_size & 0xFF + hdr.push (raw_size >> 8) & 0xFF + hdr.push (raw_size >> 16) & 0xFF + hdr.push (raw_size >> 24) & 0xFF + + File.open("#{ARGV[0]}.bin", 'w+') do |wf| + wf.write(hdr.pack('C*')) + wf.write(f.read) + wf.write([0].pack('C*')) + end +end