├── .github └── workflows │ ├── issue_comment.yml │ ├── new_issues.yml │ └── new_prs.yml ├── .gitignore ├── .gitlab-ci.yml ├── .gitmodules ├── CMakeLists.txt ├── Kconfig ├── LICENSE ├── README.md ├── component.mk ├── examples └── smart_outlet │ ├── CMakeLists.txt │ ├── Makefile │ ├── README.md │ └── main │ ├── CMakeLists.txt │ ├── Kconfig.projbuild │ ├── certs │ ├── .dummy │ └── private_key.pem │ ├── component.mk │ └── smart_outlet_example.c └── port ├── include └── iotc_bsp_hton.h └── src ├── iotc_bsp_io_net_posix.c ├── iotc_bsp_mem_posix.c ├── iotc_bsp_rng_posix.c └── iotc_bsp_time_posix.c /.github/workflows/issue_comment.yml: -------------------------------------------------------------------------------- 1 | name: Sync issue comments to JIRA 2 | 3 | # This workflow will be triggered when new issue comment is created (including PR comments) 4 | on: issue_comment 5 | 6 | jobs: 7 | sync_issue_comments_to_jira: 8 | name: Sync Issue Comments to Jira 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@master 12 | - name: Sync issue comments to JIRA 13 | uses: espressif/github-actions/sync_issues_to_jira@master 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | JIRA_PASS: ${{ secrets.JIRA_PASS }} 17 | JIRA_PROJECT: CA 18 | JIRA_URL: ${{ secrets.JIRA_URL }} 19 | JIRA_USER: ${{ secrets.JIRA_USER }} 20 | -------------------------------------------------------------------------------- /.github/workflows/new_issues.yml: -------------------------------------------------------------------------------- 1 | name: Sync issues to Jira 2 | 3 | # This workflow will be triggered when a new issue is opened 4 | on: issues 5 | 6 | jobs: 7 | sync_issues_to_jira: 8 | name: Sync issues to Jira 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@master 12 | - name: Sync GitHub issues to Jira project 13 | uses: espressif/github-actions/sync_issues_to_jira@master 14 | env: 15 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 16 | JIRA_PASS: ${{ secrets.JIRA_PASS }} 17 | JIRA_PROJECT: CA 18 | JIRA_URL: ${{ secrets.JIRA_URL }} 19 | JIRA_USER: ${{ secrets.JIRA_USER }} 20 | -------------------------------------------------------------------------------- /.github/workflows/new_prs.yml: -------------------------------------------------------------------------------- 1 | name: Sync remain PRs to Jira 2 | 3 | # This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project 4 | # Note that, PRs can also get synced when new PR comment is created 5 | on: 6 | schedule: 7 | - cron: "0 * * * *" 8 | 9 | jobs: 10 | sync_prs_to_jira: 11 | name: Sync PRs to Jira 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@master 15 | - name: Sync PRs to Jira project 16 | uses: espressif/github-actions/sync_issues_to_jira@master 17 | with: 18 | cron_job: true 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | JIRA_PASS: ${{ secrets.JIRA_PASS }} 22 | JIRA_PROJECT: CA 23 | JIRA_URL: ${{ secrets.JIRA_URL }} 24 | JIRA_USER: ${{ secrets.JIRA_USER }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # gtags 2 | GTAGS 3 | GRTAGS 4 | GPATH 5 | 6 | # emacs 7 | .dir-locals.el 8 | 9 | # emacs temp file suffixes 10 | *~ 11 | .#* 12 | \#*# 13 | 14 | # eclipse setting 15 | .settings 16 | 17 | # MacOS directory files 18 | .DS_Store 19 | 20 | # Example project files 21 | examples/**/sdkconfig 22 | examples/**/sdkconfig.old 23 | examples/**/build 24 | 25 | # VS Code Settings 26 | .vscode/ 27 | 28 | # VIM files 29 | *.swp 30 | *.swo 31 | 32 | # Clion IDE CMake build & config 33 | .idea/ 34 | cmake-build-*/ 35 | 36 | # ESP-IDF default build directory name 37 | build 38 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | 4 | variables: 5 | BATCH_BUILD: "1" 6 | V: "0" 7 | MAKEFLAGS: "-j5 --no-keep-going" 8 | IDF_PATH: "$CI_PROJECT_DIR/esp-idf" 9 | 10 | build_demo: 11 | stage: build 12 | image: $CI_DOCKER_REGISTRY/esp32-ci-env 13 | tags: 14 | - build 15 | script: 16 | # add gitlab ssh key 17 | - export PATH="$IDF_PATH/tools:$PATH" 18 | - mkdir -p ~/.ssh 19 | - chmod 700 ~/.ssh 20 | - echo -n $GITLAB_KEY > ~/.ssh/id_rsa_base64 21 | - base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa 22 | - chmod 600 ~/.ssh/id_rsa 23 | - echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config 24 | - git --version 25 | - git submodule update --init --recursive 26 | - git clone --recursive --depth 1 $GITLAB_SSH_SERVER/idf/esp-idf.git 27 | - cd esp-idf 28 | - ./install.sh 29 | - . export.sh 30 | - cd .. 31 | - cd examples/smart_outlet 32 | - make defconfig && make -j4 33 | - make clean && rm -rf build 34 | - idf.py build 35 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "iot-device-sdk-embedded-c"] 2 | path = iot-device-sdk-embedded-c 3 | url = https://github.com/GoogleCloudPlatform/iot-device-sdk-embedded-c.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | 5 | set (GOOGLE_IOT_SDK ${CMAKE_CURRENT_LIST_DIR}/iot-device-sdk-embedded-c) 6 | 7 | set (COMPONENT_ADD_INCLUDEDIRS 8 | "${GOOGLE_IOT_SDK}/src/bsp" 9 | "${GOOGLE_IOT_SDK}/include/bsp" 10 | "${GOOGLE_IOT_SDK}/include" 11 | "${GOOGLE_IOT_SDK}/src/libiotc/control_topic" 12 | "${GOOGLE_IOT_SDK}/src/libiotc/datastructures" 13 | "${GOOGLE_IOT_SDK}/src/libiotc/debug_extensions/memory_limiter" 14 | "${GOOGLE_IOT_SDK}/src/libiotc/event_dispatcher" 15 | "${GOOGLE_IOT_SDK}/src/libiotc/event_loop" 16 | "${GOOGLE_IOT_SDK}/src/libiotc/io/fs/memory" 17 | "${GOOGLE_IOT_SDK}/src/libiotc/io/fs" 18 | "${GOOGLE_IOT_SDK}/src/libiotc/io/net" 19 | "${GOOGLE_IOT_SDK}/src/libiotc/mqtt/logic" 20 | "${GOOGLE_IOT_SDK}/src/libiotc/mqtt/codec" 21 | "${GOOGLE_IOT_SDK}/src/libiotc/platform/iotc_thread" 22 | "${GOOGLE_IOT_SDK}/src/libiotc/platform/posix/iotc_thread" 23 | "${GOOGLE_IOT_SDK}/src/libiotc/tls" 24 | "${GOOGLE_IOT_SDK}/src/libiotc/tls/certs" 25 | "${GOOGLE_IOT_SDK}/src/libiotc/memory" 26 | "${GOOGLE_IOT_SDK}/src/libiotc" 27 | "${GOOGLE_IOT_SDK}/third_party/mqtt-protocol-c" 28 | "${GOOGLE_IOT_SDK}/../port/include") 29 | 30 | set (COMPONENT_SRCDIRS 31 | "${GOOGLE_IOT_SDK}/src/bsp/tls/mbedtls" 32 | "${GOOGLE_IOT_SDK}/src/bsp/crypto/mbedtls" 33 | "${GOOGLE_IOT_SDK}/src/libiotc" 34 | "${GOOGLE_IOT_SDK}/src/libiotc/control_topic" 35 | "${GOOGLE_IOT_SDK}/src/libiotc/datastructures" 36 | "${GOOGLE_IOT_SDK}/src/libiotc/debug_extensions/memory_limiter" 37 | "${GOOGLE_IOT_SDK}/src/libiotc/event_dispatcher" 38 | "${GOOGLE_IOT_SDK}/src/libiotc/event_loop" 39 | "${GOOGLE_IOT_SDK}/src/libiotc/io/fs/memory" 40 | "${GOOGLE_IOT_SDK}/src/libiotc/io/fs" 41 | "${GOOGLE_IOT_SDK}/src/libiotc/io/net" 42 | "${GOOGLE_IOT_SDK}/src/libiotc/memory" 43 | "${GOOGLE_IOT_SDK}/src/libiotc/mqtt/codec" 44 | "${GOOGLE_IOT_SDK}/src/libiotc/mqtt/logic" 45 | "${GOOGLE_IOT_SDK}/src/libiotc/tls" 46 | "${GOOGLE_IOT_SDK}/src/libiotc/tls/certs" 47 | "${GOOGLE_IOT_SDK}/third_party/mqtt-protocol-c" 48 | "${GOOGLE_IOT_SDK}/../port/src") 49 | 50 | set (COMPONENT_SUBMODULES "${GOOGLE_IOT_SDK}") 51 | 52 | set (COMPONENT_OBJEXCLUDE "${GOOGLE_IOT_SDK}/src/libiotc/iotc_test.o") 53 | 54 | set(COMPONENT_REQUIRES "mbedtls") 55 | 56 | register_component() 57 | 58 | target_compile_definitions(${COMPONENT_TARGET} PUBLIC 59 | -DIOTC_TLS_LIB_MBEDTLS 60 | -DIOTC_FS_MEMORY 61 | -DIOTC_MEMORY_LIMITER_APPLICATION_MEMORY_LIMIT=524288 62 | -DIOTC_MEMORY_LIMITER_SYSTEM_MEMORY_LIMIT=2024 63 | -DIOTC_MEMORY_LIMITER_ENABLED 64 | ) 65 | -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | menu "Google IoT Core Configuration" 2 | 3 | config GIOT_PROJECT_ID 4 | string "Google Cloud Project ID" 5 | default "project_id" 6 | help 7 | Google Cloud project ID 8 | 9 | config GIOT_LOCATION 10 | string "Google Cloud location" 11 | default "us-central1" 12 | help 13 | Google Cloud region 14 | 15 | config GIOT_REGISTRY_ID 16 | string "Google IoT Core Registry ID" 17 | default "registry_id" 18 | help 19 | Google IoT Core registry id 20 | 21 | config GIOT_DEVICE_ID 22 | string "Google IoT Core Device ID" 23 | default "device_id" 24 | help 25 | Google IoT Core device id 26 | 27 | config GIOT_DEBUG_OUTPUT 28 | bool "Enable debugging" 29 | help 30 | Select this option to enable debugging support 31 | 32 | endmenu 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP-Google-IoT 2 | 3 | This framework enables Google Cloud IoT Core connectivity with ESP32 based platforms using [Google Cloud IoT Device SDK](https://github.com/GoogleCloudPlatform/iot-device-sdk-embedded-c/blob/master/README.md). 4 | 5 | 6 | ## Supported Hardware 7 | 8 | - [ESP32-DevKitC](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp32-devkitc-v4) 9 | - [ESP-WROVER-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp-wrover-kit-v4-1) 10 | - [ESP32-PICO-KIT](https://docs.espressif.com/projects/esp-idf/en/latest/hw-reference/modules-and-boards.html#esp32-pico-kit-v4-1) 11 | 12 | ## Getting Started 13 | 14 | - Please refer to https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html for setting ESP-IDF 15 | - ESP-IDF can be downloaded from https://github.com/espressif/esp-idf/ 16 | - ESP-IDF v3.2 and above is recommended version 17 | - Please refer to [example README](examples/smart_outlet/README.md) for setting up smart outlet use case which allows to control load connected to configurable GPIO on ESP32 using Google Cloud IoT Core 18 | -------------------------------------------------------------------------------- /component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Component Makefile 3 | # 4 | 5 | COMPONENT_ADD_INCLUDEDIRS := \ 6 | iot-device-sdk-embedded-c/src/bsp \ 7 | iot-device-sdk-embedded-c/include/bsp \ 8 | iot-device-sdk-embedded-c/include \ 9 | iot-device-sdk-embedded-c/src/libiotc/control_topic \ 10 | iot-device-sdk-embedded-c/src/libiotc/datastructures \ 11 | iot-device-sdk-embedded-c/src/libiotc/debug_extensions/memory_limiter \ 12 | iot-device-sdk-embedded-c/src/libiotc/event_dispatcher \ 13 | iot-device-sdk-embedded-c/src/libiotc/event_loop \ 14 | iot-device-sdk-embedded-c/src/libiotc/io/fs/memory \ 15 | iot-device-sdk-embedded-c/src/libiotc/io/fs \ 16 | iot-device-sdk-embedded-c/src/libiotc/io/net \ 17 | iot-device-sdk-embedded-c/src/libiotc/mqtt/logic \ 18 | iot-device-sdk-embedded-c/src/libiotc/mqtt/codec \ 19 | iot-device-sdk-embedded-c/src/libiotc/platform/iotc_thread \ 20 | iot-device-sdk-embedded-c/src/libiotc/platform/posix/iotc_thread \ 21 | iot-device-sdk-embedded-c/src/libiotc/tls \ 22 | iot-device-sdk-embedded-c/src/libiotc/tls/certs \ 23 | iot-device-sdk-embedded-c/src/libiotc/memory \ 24 | iot-device-sdk-embedded-c/src/libiotc \ 25 | iot-device-sdk-embedded-c/third_party/mqtt-protocol-c \ 26 | port/include 27 | 28 | 29 | 30 | COMPONENT_SRCDIRS := \ 31 | iot-device-sdk-embedded-c/src/bsp/tls/mbedtls \ 32 | iot-device-sdk-embedded-c/src/bsp/crypto/mbedtls \ 33 | iot-device-sdk-embedded-c/src/libiotc \ 34 | iot-device-sdk-embedded-c/src/libiotc/control_topic \ 35 | iot-device-sdk-embedded-c/src/libiotc/datastructures \ 36 | iot-device-sdk-embedded-c/src/libiotc/debug_extensions/memory_limiter \ 37 | iot-device-sdk-embedded-c/src/libiotc/event_dispatcher \ 38 | iot-device-sdk-embedded-c/src/libiotc/event_loop \ 39 | iot-device-sdk-embedded-c/src/libiotc/io/fs \ 40 | iot-device-sdk-embedded-c/src/libiotc/io/fs/memory \ 41 | iot-device-sdk-embedded-c/src/libiotc/io/net \ 42 | iot-device-sdk-embedded-c/src/libiotc/memory \ 43 | iot-device-sdk-embedded-c/src/libiotc/mqtt/codec \ 44 | iot-device-sdk-embedded-c/src/libiotc/mqtt/logic \ 45 | iot-device-sdk-embedded-c/src/libiotc/mqtt/tls \ 46 | iot-device-sdk-embedded-c/src/libiotc/tls \ 47 | iot-device-sdk-embedded-c/src/libiotc/tls/certs \ 48 | iot-device-sdk-embedded-c/third_party/mqtt-protocol-c \ 49 | port/src 50 | 51 | COMPONENT_SUBMODULES := iot-device-sdk-embedded-c 52 | 53 | COMPONENT_OBJEXCLUDE := iot-device-sdk-embedded-c/src/libiotc/iotc_test.o \ 54 | iot-device-sdk-embedded-c/src/libiotc/iotc_jwt_test.o \ 55 | iot-device-sdk-embedded-c/src/libiotc/event_dispatcher/iotc_event_dispatcher_test.o \ 56 | iot-device-sdk-embedded-c/src/libiotc/event_dispatcher/iotc_event_handle_test.o 57 | 58 | CFLAGS += -DIOTC_FS_MEMORY \ 59 | -DIOTC_MEMORY_LIMITER_APPLICATION_MEMORY_LIMIT=524288 \ 60 | -DIOTC_MEMORY_LIMITER_SYSTEM_MEMORY_LIMIT=2024 \ 61 | -DIOTC_MEMORY_LIMITER_ENABLED \ 62 | -DIOTC_TLS_LIB_MBEDTLS \ 63 | 64 | ifdef CONFIG_GIOT_DEBUG_OUTPUT 65 | CFLAGS += -DIOTC_DEBUG_OUTPUT=1 66 | endif 67 | -------------------------------------------------------------------------------- /examples/smart_outlet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The following five lines of boilerplate have to be in your project's 2 | # CMakeLists in this exact order for cmake to work correctly 3 | cmake_minimum_required(VERSION 3.5) 4 | 5 | include($ENV{IDF_PATH}/tools/cmake/project.cmake) 6 | set (EXTRA_COMPONENT_DIRS "../..") 7 | project(smart_outlet) 8 | -------------------------------------------------------------------------------- /examples/smart_outlet/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a 3 | # project subdirectory. 4 | # 5 | 6 | PROJECT_NAME := smart_outlet 7 | 8 | EXTRA_COMPONENT_DIRS := $(realpath ../..) 9 | 10 | include $(IDF_PATH)/make/project.mk 11 | -------------------------------------------------------------------------------- /examples/smart_outlet/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Smart Outlet Example 3 | 4 | ---------------------- 5 | 6 | ## Google IoT Core Setup 7 | 8 | 9 | Follow this [getting-started-guide ](https://cloud.google.com/iot/docs/how-tos/getting-started) to do 10 | the initial Google Cloud IoT Core setup. 11 | 12 | ### Create Public/Private Key pair 13 | 14 | As of now, only Elliptic curve algorithm is supported for device authentication. 15 | Navigate to `Generating an ES256 key` sub section in this [guide](https://cloud.google.com/iot/docs/how-tos/credentials/keys#generating_an_es256_key) to generate key pair. 16 | 17 | ### Create Registry and Devices 18 | 19 | Step-by-step guide for creating Cloud IoT Core registry and devices is given [here](https://cloud.google.com/iot/docs/how-tos/devices). While creating a device, use the public key from the key pair generated in the previous step. 20 | 21 | *NOTE: location of the registry, registry ID and device ID will be used for ESP32 configuration later on* 22 | 23 | ## Getting started with ESP32 24 | 25 | ### Setting up ESP-IDF 26 | 27 | ESP-IDF is the official development framework for the ESP32 chip. 28 | 29 | - Please refer [this](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for setting ESP-IDF 30 | 31 | ### Connecting ESP32 to a local network 32 | 33 | Code snippet to connect ESP32 to a WiFi station: 34 | 35 | ```c 36 | 37 | static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) 38 | { 39 | switch (event->event_id) 40 | { 41 | case SYSTEM_EVENT_STA_START: 42 | esp_wifi_connect(); 43 | break; 44 | case SYSTEM_EVENT_STA_GOT_IP: 45 | xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); 46 | break; 47 | case SYSTEM_EVENT_STA_DISCONNECTED: 48 | esp_wifi_connect(); 49 | xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); 50 | break; 51 | default: 52 | break; 53 | } 54 | return ESP_OK; 55 | } 56 | 57 | static void wifi_init(void) 58 | { 59 | tcpip_adapter_init(); 60 | wifi_event_group = xEventGroupCreate(); 61 | ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); 62 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); 63 | ESP_ERROR_CHECK(esp_wifi_init(&cfg)); 64 | ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); 65 | wifi_config_t wifi_config = { 66 | .sta = { 67 | .ssid = CONFIG_ESP_WIFI_SSID, 68 | .password = CONFIG_ESP_WIFI_PASSWORD, 69 | }, 70 | }; 71 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); 72 | ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); 73 | ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_ESP_WIFI_SSID); 74 | ESP_ERROR_CHECK(esp_wifi_start()); 75 | ESP_LOGI(TAG, "Waiting for wifi"); 76 | xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); 77 | } 78 | 79 | ``` 80 | 81 | ### Connecting ESP32 to Cloud IoT Core 82 | 83 | After wifi connection is established, invoke `iotc_connect()` API in the application which initiates a connection to Cloud IoT Core. 84 | 85 | #### Connect Callback 86 | 87 | While making a connection request, your client application must provide a callback function, which is invoked when a connection to the Cloud IoT Core service has been established, as well as if the connection was unsuccessful. 88 | 89 | ```c 90 | // Connection callback function signature 91 | void on_connection_state_changed( iotc_context_handle_t in_context_handle, 92 | void* data, 93 | iotc_state_t state ) 94 | ``` 95 | 96 | ### Publishing data 97 | 98 | Once a connection has been established, the client application can publish messages to the Cloud IoT Core service. 99 | 100 | To publish a message to a topic, use either `iotc_publish()` or `iotc_publish_data()`. Each message must include the following: 101 | 102 | - The topic name 103 | - A message payload 104 | - A QoS level 105 | 106 | #### Publish callback 107 | 108 | While invoking publish API, the client application can also supply a callback function. This callback function is optional; it is intended to notify embedded devices after the message has been fully sent/acknowledged. This callback is invoked when the client application successfully publishes to Cloud IoT Core. 109 | 110 | ```c 111 | // Publish callback function signature 112 | 113 | void on_publication( iotc_context_handle_t in_context_handle, 114 | void* data, 115 | iotc_state_t state ) 116 | 117 | ``` 118 | 119 | ### Subscribing to MQTT topics 120 | 121 | To subscribe to a topic, call `iotc_subscribe()`. Subscription must include: 122 | 123 | - The topic name 124 | - A subscription callback function 125 | - A QoS level. 126 | 127 | #### Subscribe callback 128 | 129 | The subscription callback is invoked when Cloud IoT Core sends a MQTT SUBACK response with the granted QoS level of the subscription request. This function is also invoked each time Cloud IoT Core delivers a message to the subscribed topic. 130 | 131 | ```c 132 | // Subscribe callback function signature 133 | 134 | void on_message( iotc_context_handle_t in_context_handle, 135 | iotc_sub_call_type_t call_type, 136 | const iotc_sub_call_params_t* const params, 137 | iotc_state_t state, 138 | void* user_data ) 139 | 140 | ``` 141 | 142 | ## Example Setup 143 | 144 | ### Installing Private Key 145 | 146 | Copy the private key created in the earlier step to `main/certs/private_key.pem` subdirectory. 147 | 148 | *NOTE: Don't accidentally commit private key to public source* 149 | 150 | ### ESP32 Configuration 151 | 152 | #### Wifi Setting 153 | 154 | In the `smart-outlet` example directory, run `make menuconfig` and navigate to `Example Configuration` to set `WiFi SSID` and `WiFI Password` 155 | 156 | #### Google IoT Core Device Setting 157 | 158 | Set Project ID, Location, Registry ID and Device ID under `make menuconfig` -> `Component config` -> `Google IoT Core Configuration` 159 | 160 | `project_id` of your project can be fetched from [resources page](https://console.cloud.google.com/cloud-resource-manager) 161 | 162 | Fetch `location`, `registry_id` and `device_id` from the Google IoT Core registry. 163 | 164 | ### Flashing client application 165 | 166 | ``` 167 | make -j8 flash monitor 168 | ``` 169 | 170 | ## Example Workflow 171 | 172 | After flashing the example to your ESP32, it should connect to Google IoT Core and start subscribing/publishing MQTT data. 173 | 174 | ### Telemetry Event 175 | 176 | This example publishes temperature data every 10 seconds to the topic `/devices/{device-id}/events` 177 | 178 | ### Sending Device Configuration from Google IoT Core 179 | 180 | To know more about configuring devices from Google IoT Core visit [here](https://cloud.google.com/iot/docs/how-tos/config/configuring-devices) 181 | 182 | A subscription to the topic `/devices/{device-id}/config` is established on start-up, thus you receive configuration details in the registered subscribe callback `iotc_mqttlogic_subscribe_callback` 183 | 184 | ### Sending Device Command 185 | 186 | A subscription to the wildcard topic `/devices/{device-id}/commands/#` is established in this example, you can send commands to the device by following instruction given [here](https://cloud.google.com/iot/docs/how-tos/commands). 187 | 188 | - Set Output GPIO under `make menuconfig` -> `Example Configuration` -> `Output GPIO` 189 | - Send `{"outlet": 0}` or `{"outlet": 1}` from Google Cloud IoT Core Device Console to change GPIO output. 190 | -------------------------------------------------------------------------------- /examples/smart_outlet/main/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPONENT_SRCS "smart_outlet_example.c") 2 | set(COMPONENT_ADD_INCLUDEDIRS ".") 3 | 4 | register_component() 5 | 6 | if(IDF_CI_BUILD) 7 | add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/certs/private_key.pem 8 | COMMAND echo "Dummy certificate data for continuous integration" > 9 | certs/private_key.pem 10 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 11 | VERBATIM) 12 | add_custom_target(example_certificates DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/certs/private_key.pem) 13 | 14 | add_dependencies(${COMPONENT_TARGET} example_certificates) 15 | 16 | target_add_binary_data(${COMPONENT_TARGET} "${CMAKE_CURRENT_BINARY_DIR}/certs/private_key.pem" TEXT) 17 | else() 18 | target_add_binary_data(${COMPONENT_TARGET} "certs/private_key.pem" TEXT) 19 | endif() 20 | 21 | -------------------------------------------------------------------------------- /examples/smart_outlet/main/Kconfig.projbuild: -------------------------------------------------------------------------------- 1 | menu "Example Configuration" 2 | 3 | config ESP_WIFI_SSID 4 | string "WiFi SSID" 5 | default "myssid" 6 | help 7 | SSID (network name) for the example to connect to. 8 | 9 | config ESP_WIFI_PASSWORD 10 | string "WiFi Password" 11 | default "mypassword" 12 | help 13 | WiFi password (WPA or WPA2) for the example to use. 14 | 15 | config OUTPUT_GPIO 16 | int "Output GPIO" 17 | default 27 18 | help 19 | This is the GPIO on which output will be set. 20 | 21 | endmenu 22 | -------------------------------------------------------------------------------- /examples/smart_outlet/main/certs/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp-google-iot/418c34690939307fbfe9dd92e7163a9d92ac5ab9/examples/smart_outlet/main/certs/.dummy -------------------------------------------------------------------------------- /examples/smart_outlet/main/certs/private_key.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/espressif/esp-google-iot/418c34690939307fbfe9dd92e7163a9d92ac5ab9/examples/smart_outlet/main/certs/private_key.pem -------------------------------------------------------------------------------- /examples/smart_outlet/main/component.mk: -------------------------------------------------------------------------------- 1 | # 2 | # Main component makefile. 3 | # 4 | # This Makefile can be left empty. By default, it will take the sources in the 5 | # src/ directory, compile them and link them into lib(subdirectory_name).a 6 | # in the build directory. This behaviour is entirely configurable, 7 | # please read the ESP-IDF documents if you need to do this. 8 | # 9 | COMPONENT_EMBED_TXTFILES := certs/private_key.pem 10 | 11 | ifndef IDF_CI_BUILD 12 | # Print an error if the certificate/key files are missing 13 | $(COMPONENT_PATH)/certs/private_key.pem: 14 | @echo "Missing PEM file $@. This file identifies the ESP32 to Google Cloud IoT Core for the example, see README for details." 15 | exit 1 16 | else # IDF_CI_BUILD 17 | # this case is for the internal Continuous Integration build which 18 | # compiles all examples. Add some dummy certs so the example can 19 | # compile (even though it won't work) 20 | $(COMPONENT_PATH)/certs/private_key.pem: 21 | echo "Dummy certificate data for continuous integration" > $@ 22 | endif 23 | -------------------------------------------------------------------------------- /examples/smart_outlet/main/smart_outlet_example.c: -------------------------------------------------------------------------------- 1 | /* Smart Outlet Example 2 | 3 | This example code is in the Public Domain (or CC0 licensed, at your option.) 4 | 5 | Unless required by applicable law or agreed to in writing, this 6 | software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 7 | CONDITIONS OF ANY KIND, either express or implied. 8 | */ 9 | #include 10 | #include 11 | #include "freertos/FreeRTOS.h" 12 | #include "freertos/task.h" 13 | #include "freertos/event_groups.h" 14 | #include "esp_system.h" 15 | #include "esp_wifi.h" 16 | #include "esp_event_loop.h" 17 | #include "esp_log.h" 18 | #include "nvs_flash.h" 19 | #include "jsmn.h" 20 | #include 21 | #include "lwip/apps/sntp.h" 22 | #include "driver/gpio.h" 23 | 24 | #include "lwip/err.h" 25 | #include "lwip/sys.h" 26 | #include 27 | #include 28 | 29 | extern const uint8_t ec_pv_key_start[] asm("_binary_private_key_pem_start"); 30 | extern const uint8_t ec_pv_key_end[] asm("_binary_private_key_pem_end"); 31 | 32 | static const char *TAG = "APP"; 33 | 34 | static EventGroupHandle_t wifi_event_group; 35 | const static int CONNECTED_BIT = BIT0; 36 | 37 | #define IOTC_UNUSED(x) (void)(x) 38 | 39 | #define DEVICE_PATH "projects/%s/locations/%s/registries/%s/devices/%s" 40 | #define SUBSCRIBE_TOPIC_COMMAND "/devices/%s/commands/#" 41 | #define SUBSCRIBE_TOPIC_CONFIG "/devices/%s/config" 42 | #define PUBLISH_TOPIC_EVENT "/devices/%s/events" 43 | #define PUBLISH_TOPIC_STATE "/devices/%s/state" 44 | #define TEMPERATURE_DATA "{temp : %d}" 45 | #define MIN_TEMP 20 46 | #define OUTPUT_GPIO CONFIG_OUTPUT_GPIO 47 | 48 | char *subscribe_topic_command, *subscribe_topic_config; 49 | 50 | iotc_mqtt_qos_t iotc_example_qos = IOTC_MQTT_QOS_AT_LEAST_ONCE; 51 | static iotc_timed_task_handle_t delayed_publish_task = 52 | IOTC_INVALID_TIMED_TASK_HANDLE; 53 | iotc_context_handle_t iotc_context = IOTC_INVALID_CONTEXT_HANDLE; 54 | 55 | 56 | static void driver_init() 57 | { 58 | /* Configure output */ 59 | gpio_config_t io_conf = { 60 | .mode = GPIO_MODE_OUTPUT, 61 | .pull_up_en = 1, 62 | }; 63 | io_conf.pin_bit_mask = ((uint64_t)1 << OUTPUT_GPIO); 64 | /* Configure the GPIO */ 65 | gpio_config(&io_conf); 66 | } 67 | 68 | static void initialize_sntp(void) 69 | { 70 | ESP_LOGI(TAG, "Initializing SNTP"); 71 | sntp_setoperatingmode(SNTP_OPMODE_POLL); 72 | sntp_setservername(0, "time.google.com"); 73 | sntp_init(); 74 | } 75 | 76 | static void obtain_time(void) 77 | { 78 | initialize_sntp(); 79 | // wait for time to be set 80 | time_t now = 0; 81 | struct tm timeinfo = {0}; 82 | while (timeinfo.tm_year < (2016 - 1900)) { 83 | ESP_LOGI(TAG, "Waiting for system time to be set..."); 84 | vTaskDelay(2000 / portTICK_PERIOD_MS); 85 | time(&now); 86 | localtime_r(&now, &timeinfo); 87 | } 88 | ESP_LOGI(TAG, "Time is set..."); 89 | } 90 | 91 | void publish_telemetry_event(iotc_context_handle_t context_handle, 92 | iotc_timed_task_handle_t timed_task, void *user_data) 93 | { 94 | IOTC_UNUSED(timed_task); 95 | IOTC_UNUSED(user_data); 96 | 97 | char *publish_topic = NULL; 98 | asprintf(&publish_topic, PUBLISH_TOPIC_EVENT, CONFIG_GIOT_DEVICE_ID); 99 | char *publish_message = NULL; 100 | asprintf(&publish_message, TEMPERATURE_DATA, MIN_TEMP + rand() % 10); 101 | ESP_LOGI(TAG, "publishing msg \"%s\" to topic: \"%s\"", publish_message, publish_topic); 102 | 103 | iotc_publish(context_handle, publish_topic, publish_message, 104 | iotc_example_qos, 105 | /*callback=*/NULL, /*user_data=*/NULL); 106 | free(publish_topic); 107 | free(publish_message); 108 | } 109 | 110 | void iotc_mqttlogic_subscribe_callback( 111 | iotc_context_handle_t in_context_handle, iotc_sub_call_type_t call_type, 112 | const iotc_sub_call_params_t *const params, iotc_state_t state, 113 | void *user_data) 114 | { 115 | IOTC_UNUSED(in_context_handle); 116 | IOTC_UNUSED(call_type); 117 | IOTC_UNUSED(state); 118 | IOTC_UNUSED(user_data); 119 | if (params != NULL && params->message.topic != NULL) { 120 | ESP_LOGI(TAG, "Subscription Topic: %s", params->message.topic); 121 | char *sub_message = (char *)malloc(params->message.temporary_payload_data_length + 1); 122 | if (sub_message == NULL) { 123 | ESP_LOGE(TAG, "Failed to allocate memory"); 124 | return; 125 | } 126 | memcpy(sub_message, params->message.temporary_payload_data, params->message.temporary_payload_data_length); 127 | sub_message[params->message.temporary_payload_data_length] = '\0'; 128 | ESP_LOGI(TAG, "Message Payload: %s ", sub_message); 129 | if (strcmp(subscribe_topic_command, params->message.topic) == 0) { 130 | int value; 131 | sscanf(sub_message, "{\"outlet\": %d}", &value); 132 | ESP_LOGI(TAG, "value: %d", value); 133 | if (value == 1) { 134 | gpio_set_level(OUTPUT_GPIO, true); 135 | } else if (value == 0) { 136 | gpio_set_level(OUTPUT_GPIO, false); 137 | } 138 | } 139 | free(sub_message); 140 | } 141 | } 142 | 143 | void on_connection_state_changed(iotc_context_handle_t in_context_handle, 144 | void *data, iotc_state_t state) 145 | { 146 | iotc_connection_data_t *conn_data = (iotc_connection_data_t *)data; 147 | 148 | switch (conn_data->connection_state) { 149 | /* IOTC_CONNECTION_STATE_OPENED means that the connection has been 150 | established and the IoTC Client is ready to send/recv messages */ 151 | case IOTC_CONNECTION_STATE_OPENED: 152 | ESP_LOGI(TAG, "connected!"); 153 | 154 | /* Publish immediately upon connect. 'publish_function' is defined 155 | in this example file and invokes the IoTC API to publish a 156 | message. */ 157 | asprintf(&subscribe_topic_command, SUBSCRIBE_TOPIC_COMMAND, CONFIG_GIOT_DEVICE_ID); 158 | ESP_LOGI(TAG, "subscribing to topic: \"%s\"", subscribe_topic_command); 159 | iotc_subscribe(in_context_handle, subscribe_topic_command, IOTC_MQTT_QOS_AT_LEAST_ONCE, 160 | &iotc_mqttlogic_subscribe_callback, /*user_data=*/NULL); 161 | 162 | asprintf(&subscribe_topic_config, SUBSCRIBE_TOPIC_CONFIG, CONFIG_GIOT_DEVICE_ID); 163 | ESP_LOGI(TAG, "subscribing to topic: \"%s\"", subscribe_topic_config); 164 | iotc_subscribe(in_context_handle, subscribe_topic_config, IOTC_MQTT_QOS_AT_LEAST_ONCE, 165 | &iotc_mqttlogic_subscribe_callback, /*user_data=*/NULL); 166 | 167 | /* Create a timed task to publish every 10 seconds. */ 168 | delayed_publish_task = iotc_schedule_timed_task(in_context_handle, 169 | publish_telemetry_event, 10, 170 | 15, /*user_data=*/NULL); 171 | break; 172 | 173 | /* IOTC_CONNECTION_STATE_OPEN_FAILED is set when there was a problem 174 | when establishing a connection to the server. The reason for the error 175 | is contained in the 'state' variable. Here we log the error state and 176 | exit out of the application. */ 177 | 178 | /* Publish immediately upon connect. 'publish_function' is defined 179 | in this example file and invokes the IoTC API to publish a 180 | message. */ 181 | case IOTC_CONNECTION_STATE_OPEN_FAILED: 182 | ESP_LOGI(TAG, "ERROR! Connection has failed reason %d", state); 183 | 184 | /* exit it out of the application by stopping the event loop. */ 185 | iotc_events_stop(); 186 | break; 187 | 188 | /* IOTC_CONNECTION_STATE_CLOSED is set when the IoTC Client has been 189 | disconnected. The disconnection may have been caused by some external 190 | issue, or user may have requested a disconnection. In order to 191 | distinguish between those two situation it is advised to check the state 192 | variable value. If the state == IOTC_STATE_OK then the application has 193 | requested a disconnection via 'iotc_shutdown_connection'. If the state != 194 | IOTC_STATE_OK then the connection has been closed from one side. */ 195 | case IOTC_CONNECTION_STATE_CLOSED: 196 | free(subscribe_topic_command); 197 | free(subscribe_topic_config); 198 | /* Prevent dangling pointers that may happen if IOTC_CONNECTION_STATE_CLOSED 199 | state is called twice in a row. */ 200 | subscribe_topic_command = NULL; 201 | subscribe_topic_config = NULL; 202 | 203 | /* When the connection is closed it's better to cancel some of previously 204 | registered activities. Using cancel function on handler will remove the 205 | handler from the timed queue which prevents the registered handle to be 206 | called when there is no connection. */ 207 | if (IOTC_INVALID_TIMED_TASK_HANDLE != delayed_publish_task) { 208 | iotc_cancel_timed_task(delayed_publish_task); 209 | delayed_publish_task = IOTC_INVALID_TIMED_TASK_HANDLE; 210 | } 211 | 212 | if (state == IOTC_STATE_OK) { 213 | /* The connection has been closed intentionally. Therefore, stop 214 | the event processing loop as there's nothing left to do 215 | in this example. */ 216 | iotc_events_stop(); 217 | } else { 218 | ESP_LOGE(TAG, "connection closed - reason %d!", state); 219 | /* The disconnection was unforeseen. Try reconnect to the server 220 | with previously set configuration, which has been provided 221 | to this callback in the conn_data structure. */ 222 | iotc_connect( 223 | in_context_handle, conn_data->username, conn_data->password, conn_data->client_id, 224 | conn_data->connection_timeout, conn_data->keepalive_timeout, 225 | &on_connection_state_changed); 226 | } 227 | break; 228 | 229 | default: 230 | ESP_LOGE(TAG, "incorrect connection state value."); 231 | break; 232 | } 233 | } 234 | 235 | static esp_err_t wifi_event_handler(void *ctx, system_event_t *event) 236 | { 237 | switch (event->event_id) { 238 | case SYSTEM_EVENT_STA_START: 239 | esp_wifi_connect(); 240 | break; 241 | case SYSTEM_EVENT_STA_GOT_IP: 242 | xEventGroupSetBits(wifi_event_group, CONNECTED_BIT); 243 | break; 244 | case SYSTEM_EVENT_STA_DISCONNECTED: 245 | esp_wifi_connect(); 246 | xEventGroupClearBits(wifi_event_group, CONNECTED_BIT); 247 | break; 248 | default: 249 | break; 250 | } 251 | return ESP_OK; 252 | } 253 | 254 | static void wifi_init(void) 255 | { 256 | tcpip_adapter_init(); 257 | wifi_event_group = xEventGroupCreate(); 258 | ESP_ERROR_CHECK(esp_event_loop_init(wifi_event_handler, NULL)); 259 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); 260 | ESP_ERROR_CHECK(esp_wifi_init(&cfg)); 261 | ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); 262 | wifi_config_t wifi_config = { 263 | .sta = { 264 | .ssid = CONFIG_ESP_WIFI_SSID, 265 | .password = CONFIG_ESP_WIFI_PASSWORD, 266 | }, 267 | }; 268 | ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); 269 | ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); 270 | ESP_LOGI(TAG, "start the WIFI SSID:[%s]", CONFIG_ESP_WIFI_SSID); 271 | ESP_ERROR_CHECK(esp_wifi_start()); 272 | ESP_LOGI(TAG, "Waiting for wifi"); 273 | xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); 274 | } 275 | 276 | static void mqtt_task(void *pvParameters) 277 | { 278 | /* Format the key type descriptors so the client understands 279 | which type of key is being represented. In this case, a PEM encoded 280 | byte array of a ES256 key. */ 281 | iotc_crypto_key_data_t iotc_connect_private_key_data; 282 | iotc_connect_private_key_data.crypto_key_signature_algorithm = IOTC_CRYPTO_KEY_SIGNATURE_ALGORITHM_ES256; 283 | iotc_connect_private_key_data.crypto_key_union_type = IOTC_CRYPTO_KEY_UNION_TYPE_PEM; 284 | iotc_connect_private_key_data.crypto_key_union.key_pem.key = (char *) ec_pv_key_start; 285 | 286 | /* initialize iotc library and create a context to use to connect to the 287 | * GCP IoT Core Service. */ 288 | const iotc_state_t error_init = iotc_initialize(); 289 | 290 | if (IOTC_STATE_OK != error_init) { 291 | ESP_LOGE(TAG, " iotc failed to initialize, error: %d", error_init); 292 | vTaskDelete(NULL); 293 | } 294 | 295 | /* Create a connection context. A context represents a Connection 296 | on a single socket, and can be used to publish and subscribe 297 | to numerous topics. */ 298 | iotc_context = iotc_create_context(); 299 | if (IOTC_INVALID_CONTEXT_HANDLE >= iotc_context) { 300 | ESP_LOGE(TAG, " iotc failed to create context, error: %d", -iotc_context); 301 | vTaskDelete(NULL); 302 | } 303 | 304 | /* Queue a connection request to be completed asynchronously. 305 | The 'on_connection_state_changed' parameter is the name of the 306 | callback function after the connection request completes, and its 307 | implementation should handle both successful connections and 308 | unsuccessful connections as well as disconnections. */ 309 | const uint16_t connection_timeout = 0; 310 | const uint16_t keepalive_timeout = 20; 311 | 312 | /* Generate the client authentication JWT, which will serve as the MQTT 313 | * password. */ 314 | char jwt[IOTC_JWT_SIZE] = {0}; 315 | size_t bytes_written = 0; 316 | iotc_state_t state = iotc_create_iotcore_jwt( 317 | CONFIG_GIOT_PROJECT_ID, 318 | /*jwt_expiration_period_sec=*/3600, &iotc_connect_private_key_data, jwt, 319 | IOTC_JWT_SIZE, &bytes_written); 320 | 321 | if (IOTC_STATE_OK != state) { 322 | ESP_LOGE(TAG, "iotc_create_iotcore_jwt returned with error: %ul", state); 323 | vTaskDelete(NULL); 324 | } 325 | 326 | char *device_path = NULL; 327 | asprintf(&device_path, DEVICE_PATH, CONFIG_GIOT_PROJECT_ID, CONFIG_GIOT_LOCATION, CONFIG_GIOT_REGISTRY_ID, CONFIG_GIOT_DEVICE_ID); 328 | iotc_connect(iotc_context, NULL, jwt, device_path, connection_timeout, 329 | keepalive_timeout, &on_connection_state_changed); 330 | free(device_path); 331 | /* The IoTC Client was designed to be able to run on single threaded devices. 332 | As such it does not have its own event loop thread. Instead you must 333 | regularly call the function iotc_events_process_blocking() to process 334 | connection requests, and for the client to regularly check the sockets for 335 | incoming data. This implementation has the loop operate endlessly. The loop 336 | will stop after closing the connection, using iotc_shutdown_connection() as 337 | defined in on_connection_state_change logic, and exit the event handler 338 | handler by calling iotc_events_stop(); */ 339 | iotc_events_process_blocking(); 340 | 341 | iotc_delete_context(iotc_context); 342 | 343 | iotc_shutdown(); 344 | 345 | vTaskDelete(NULL); 346 | } 347 | 348 | void app_main() 349 | { 350 | //Initialize NVS 351 | esp_err_t ret = nvs_flash_init(); 352 | if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { 353 | ESP_ERROR_CHECK(nvs_flash_erase()); 354 | ret = nvs_flash_init(); 355 | } 356 | ESP_ERROR_CHECK(ret); 357 | ESP_LOGI(TAG, "ESP_WIFI_MODE_STA"); 358 | wifi_init(); 359 | obtain_time(); 360 | driver_init(); 361 | xTaskCreate(&mqtt_task, "mqtt_task", 8192, NULL, 5, NULL); 362 | } 363 | -------------------------------------------------------------------------------- /port/include/iotc_bsp_hton.h: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /port/src/iotc_bsp_io_net_posix.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2018-2020 Google LLC 2 | * 3 | * This is part of the Google Cloud IoT Device SDK for Embedded C. 4 | * It is licensed under the BSD 3-Clause license; you may not use this file 5 | * except in compliance with the License. 6 | * 7 | * You may obtain a copy of the License at: 8 | * https://opensource.org/licenses/BSD-3-Clause 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "iotc_macros.h" 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | #ifndef MAX 35 | #define MAX(a, b) (((a) > (b)) ? (a) : (b)) 36 | #endif 37 | 38 | iotc_bsp_io_net_state_t iotc_bsp_io_net_socket_connect( 39 | iotc_bsp_socket_t* iotc_socket, const char* host, uint16_t port, 40 | iotc_bsp_socket_type_t socket_type) { 41 | struct addrinfo hints; 42 | struct addrinfo *result, *rp = NULL; 43 | int status; 44 | 45 | memset(&hints, 0, sizeof(hints)); 46 | hints.ai_family = AF_UNSPEC; 47 | hints.ai_socktype = socket_type; 48 | hints.ai_flags = 0; 49 | hints.ai_protocol = 0; 50 | 51 | // Address resolution. 52 | status = getaddrinfo(host, NULL, &hints, &result); 53 | if (0 != status) { 54 | return IOTC_BSP_IO_NET_STATE_ERROR; 55 | } 56 | 57 | for (rp = result; rp != NULL; rp = rp->ai_next) { 58 | *iotc_socket = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 59 | if (-1 == *iotc_socket) continue; 60 | 61 | // Set the socket to be non-blocking. 62 | const int flags = fcntl(*iotc_socket, F_GETFL); 63 | if (-1 == fcntl(*iotc_socket, F_SETFL, flags | O_NONBLOCK)) { 64 | freeaddrinfo(result); 65 | return IOTC_BSP_IO_NET_STATE_ERROR; 66 | } 67 | 68 | switch (rp->ai_family) { 69 | case AF_INET6: 70 | ((struct sockaddr_in6*)(rp->ai_addr))->sin6_port = htons(port); 71 | break; 72 | case AF_INET: 73 | ((struct sockaddr_in*)(rp->ai_addr))->sin_port = htons(port); 74 | break; 75 | default: 76 | return IOTC_BSP_IO_NET_STATE_ERROR; 77 | break; 78 | } 79 | 80 | // Attempt to connect. 81 | status = connect(*iotc_socket, rp->ai_addr, rp->ai_addrlen); 82 | 83 | if (-1 != status) { 84 | freeaddrinfo(result); 85 | return IOTC_BSP_IO_NET_STATE_OK; 86 | } else { 87 | if (EINPROGRESS == errno) { 88 | freeaddrinfo(result); 89 | return IOTC_BSP_IO_NET_STATE_OK; 90 | } else { 91 | close(*iotc_socket); 92 | } 93 | } 94 | } 95 | freeaddrinfo(result); 96 | return IOTC_BSP_IO_NET_STATE_ERROR; 97 | } 98 | 99 | iotc_bsp_io_net_state_t iotc_bsp_io_net_connection_check( 100 | iotc_bsp_socket_t iotc_socket, const char* host, uint16_t port) { 101 | IOTC_UNUSED(host); 102 | IOTC_UNUSED(port); 103 | 104 | int valopt = 0; 105 | socklen_t lon = sizeof(int); 106 | 107 | if (getsockopt(iotc_socket, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 108 | 0) { 109 | return IOTC_BSP_IO_NET_STATE_ERROR; 110 | } 111 | 112 | if (valopt) { 113 | return IOTC_BSP_IO_NET_STATE_ERROR; 114 | } 115 | 116 | return IOTC_BSP_IO_NET_STATE_OK; 117 | } 118 | 119 | iotc_bsp_io_net_state_t iotc_bsp_io_net_write(iotc_bsp_socket_t iotc_socket, 120 | int* out_written_count, 121 | const uint8_t* buf, 122 | size_t count) { 123 | if (NULL == out_written_count || NULL == buf) { 124 | return IOTC_BSP_IO_NET_STATE_ERROR; 125 | } 126 | 127 | int errval = 0; 128 | socklen_t lon = sizeof(int); 129 | 130 | if (getsockopt(iotc_socket, SOL_SOCKET, SO_ERROR, (void*)(&errval), &lon) < 131 | 0) { 132 | errval = errno; 133 | errno = 0; 134 | return IOTC_BSP_IO_NET_STATE_ERROR; 135 | } 136 | 137 | if (errval != 0) { 138 | return IOTC_BSP_IO_NET_STATE_ERROR; 139 | } 140 | 141 | *out_written_count = write(iotc_socket, buf, count); 142 | 143 | if (*out_written_count < 0) { 144 | *out_written_count = 0; 145 | 146 | errval = errno; 147 | errno = 0; 148 | 149 | if (EAGAIN == errval) { 150 | return IOTC_BSP_IO_NET_STATE_BUSY; 151 | } 152 | 153 | if (ECONNRESET == errval || EPIPE == errval) { 154 | return IOTC_BSP_IO_NET_STATE_CONNECTION_RESET; 155 | } 156 | return IOTC_BSP_IO_NET_STATE_ERROR; 157 | } 158 | 159 | return IOTC_BSP_IO_NET_STATE_OK; 160 | } 161 | 162 | iotc_bsp_io_net_state_t iotc_bsp_io_net_read(iotc_bsp_socket_t iotc_socket, 163 | int* out_read_count, uint8_t* buf, 164 | size_t count) { 165 | if (NULL == out_read_count || NULL == buf) { 166 | return IOTC_BSP_IO_NET_STATE_ERROR; 167 | } 168 | 169 | int errval = 0; 170 | *out_read_count = read(iotc_socket, buf, count); 171 | 172 | if (*out_read_count < 0) { 173 | *out_read_count = 0; 174 | 175 | errval = errno; 176 | errno = 0; 177 | 178 | if (EAGAIN == errval) { 179 | return IOTC_BSP_IO_NET_STATE_BUSY; 180 | } 181 | 182 | if (ECONNRESET == errval || EPIPE == errval) { 183 | return IOTC_BSP_IO_NET_STATE_CONNECTION_RESET; 184 | } 185 | 186 | return IOTC_BSP_IO_NET_STATE_ERROR; 187 | } 188 | 189 | if (0 == *out_read_count) { 190 | return IOTC_BSP_IO_NET_STATE_CONNECTION_RESET; 191 | } 192 | 193 | return IOTC_BSP_IO_NET_STATE_OK; 194 | } 195 | 196 | iotc_bsp_io_net_state_t iotc_bsp_io_net_close_socket( 197 | iotc_bsp_socket_t* iotc_socket) { 198 | if (NULL == iotc_socket) { 199 | return IOTC_BSP_IO_NET_STATE_ERROR; 200 | } 201 | 202 | shutdown(*iotc_socket, SHUT_RDWR); 203 | 204 | close(*iotc_socket); 205 | 206 | *iotc_socket = 0; 207 | 208 | return IOTC_BSP_IO_NET_STATE_OK; 209 | } 210 | 211 | iotc_bsp_io_net_state_t iotc_bsp_io_net_select( 212 | iotc_bsp_socket_events_t* socket_events_array, 213 | size_t socket_events_array_size, long timeout_sec) { 214 | fd_set rfds; 215 | fd_set wfds; 216 | fd_set efds; 217 | 218 | FD_ZERO(&rfds); 219 | FD_ZERO(&wfds); 220 | FD_ZERO(&efds); 221 | 222 | int max_fd_read = 0; 223 | int max_fd_write = 0; 224 | int max_fd_error = 0; 225 | 226 | struct timeval tv = {0, 0}; 227 | 228 | /* translate the library socket events settings to the event sets used by 229 | * posix select 230 | */ 231 | size_t socket_id = 0; 232 | for (socket_id = 0; socket_id < socket_events_array_size; ++socket_id) { 233 | iotc_bsp_socket_events_t* socket_events = &socket_events_array[socket_id]; 234 | 235 | if (NULL == socket_events) { 236 | return IOTC_BSP_IO_NET_STATE_ERROR; 237 | } 238 | 239 | if (1 == socket_events->in_socket_want_read) { 240 | FD_SET(socket_events->iotc_socket, &rfds); 241 | max_fd_read = socket_events->iotc_socket > max_fd_read 242 | ? socket_events->iotc_socket 243 | : max_fd_read; 244 | } 245 | 246 | if ((1 == socket_events->in_socket_want_write) || 247 | (1 == socket_events->in_socket_want_connect)) { 248 | FD_SET(socket_events->iotc_socket, &wfds); 249 | max_fd_write = socket_events->iotc_socket > max_fd_write 250 | ? socket_events->iotc_socket 251 | : max_fd_write; 252 | } 253 | 254 | if (1 == socket_events->in_socket_want_error) { 255 | FD_SET(socket_events->iotc_socket, &efds); 256 | max_fd_error = socket_events->iotc_socket > max_fd_error 257 | ? socket_events->iotc_socket 258 | : max_fd_error; 259 | } 260 | } 261 | 262 | /* calculate max fd */ 263 | const int max_fd = MAX(max_fd_read, MAX(max_fd_write, max_fd_error)); 264 | 265 | tv.tv_sec = timeout_sec; 266 | 267 | /* call the actual posix select */ 268 | const int result = select(max_fd + 1, &rfds, &wfds, &efds, &tv); 269 | 270 | if (0 < result) { 271 | /* translate the result back to the socket events structure */ 272 | for (socket_id = 0; socket_id < socket_events_array_size; ++socket_id) { 273 | iotc_bsp_socket_events_t* socket_events = &socket_events_array[socket_id]; 274 | 275 | if (FD_ISSET(socket_events->iotc_socket, &rfds)) { 276 | socket_events->out_socket_can_read = 1; 277 | } 278 | 279 | if (FD_ISSET(socket_events->iotc_socket, &wfds)) { 280 | if (1 == socket_events->in_socket_want_connect) { 281 | socket_events->out_socket_connect_finished = 1; 282 | } 283 | 284 | if (1 == socket_events->in_socket_want_write) { 285 | socket_events->out_socket_can_write = 1; 286 | } 287 | } 288 | 289 | if (FD_ISSET(socket_events->iotc_socket, &efds)) { 290 | socket_events->out_socket_error = 1; 291 | } 292 | } 293 | 294 | return IOTC_BSP_IO_NET_STATE_OK; 295 | } else if (0 == result) { 296 | return IOTC_BSP_IO_NET_STATE_TIMEOUT; 297 | } 298 | 299 | return IOTC_BSP_IO_NET_STATE_ERROR; 300 | } 301 | 302 | #ifdef __cplusplus 303 | } 304 | #endif 305 | -------------------------------------------------------------------------------- /port/src/iotc_bsp_mem_posix.c: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | IRAM_ATTR void *iotc_bsp_mem_alloc(size_t byte_count) 22 | { 23 | #if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) 24 | return heap_caps_malloc(byte_count, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); 25 | #else 26 | return malloc(byte_count); 27 | #endif 28 | } 29 | 30 | IRAM_ATTR void *iotc_bsp_mem_realloc(void* ptr, size_t byte_count) 31 | { 32 | #if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) 33 | return heap_caps_realloc(ptr, byte_count, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT); 34 | #else 35 | return realloc(ptr, byte_count); 36 | #endif 37 | } 38 | 39 | IRAM_ATTR void iotc_bsp_mem_free(void* ptr) 40 | { 41 | heap_caps_free(ptr); 42 | } 43 | -------------------------------------------------------------------------------- /port/src/iotc_bsp_rng_posix.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2018-2020 Google LLC 2 | * 3 | * This is part of the Google Cloud IoT Device SDK for Embedded C. 4 | * It is licensed under the BSD 3-Clause license; you may not use this file 5 | * except in compliance with the License. 6 | * 7 | * You may obtain a copy of the License at: 8 | * https://opensource.org/licenses/BSD-3-Clause 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | /* No TLS option choosen */ 20 | #if !defined(IOTC_TLS_LIB_MBEDTLS) && !defined(IOTC_TLS_LIB_WOLFSSL) 21 | 22 | #include 23 | #include 24 | 25 | void iotc_bsp_rng_init() { srand(time(NULL)); } 26 | 27 | uint32_t iotc_bsp_rng_get() { 28 | #ifdef IOTC_BSP_RNG_16BIT_INT_PLATFORM 29 | const uint32_t half_a = rand(); 30 | const uint32_t half_b = rand(); 31 | 32 | return (half_a << 16) | (half_b & 0x0000FFFF); 33 | #else 34 | return rand(); 35 | #endif 36 | } 37 | 38 | void iotc_bsp_rng_shutdown() { /* nothing to do here */ 39 | } 40 | 41 | #elif defined(IOTC_TLS_LIB_MBEDTLS) /* MBEDTLS version of RNG implementation \ 42 | */ 43 | 44 | #include 45 | #include 46 | #include 47 | 48 | #include 49 | 50 | static mbedtls_entropy_context entropy; 51 | mbedtls_ctr_drbg_context ctr_drbg; 52 | 53 | void iotc_bsp_rng_init() { 54 | const char personalization[] = "iotc_bsp_mbedtls_more_entropy_pls"; 55 | 56 | mbedtls_entropy_init(&entropy); 57 | mbedtls_ctr_drbg_init(&ctr_drbg); 58 | 59 | const int ret_state = mbedtls_ctr_drbg_seed( 60 | &ctr_drbg, mbedtls_entropy_func, &entropy, 61 | (const unsigned char*)personalization, sizeof(personalization)); 62 | 63 | if (ret_state != 0) { 64 | printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret_state); 65 | goto exit; 66 | } 67 | 68 | exit:; 69 | } 70 | 71 | uint32_t iotc_bsp_rng_get() { 72 | uint32_t random = 0; 73 | 74 | mbedtls_ctr_drbg_random(&ctr_drbg, (unsigned char*)&random, 4); 75 | 76 | return random; 77 | } 78 | 79 | void iotc_bsp_rng_shutdown() { 80 | mbedtls_ctr_drbg_free(&ctr_drbg); 81 | mbedtls_entropy_free(&entropy); 82 | } 83 | 84 | #elif defined(IOTC_TLS_LIB_WOLFSSL) /* WOLFSSL version of RNG implementation \ 85 | */ 86 | 87 | #include 88 | #include 89 | #include 90 | 91 | WC_RNG wolfcrypt_rng; 92 | 93 | void iotc_bsp_rng_init() { 94 | /* check if already initialized */ 95 | if (NULL == wolfcrypt_rng.drbg) { 96 | CyaSSL_SetAllocators(iotc_alloc_ptr, iotc_free_ptr, iotc_realloc_ptr); 97 | 98 | wc_InitRng(&wolfcrypt_rng); 99 | } 100 | } 101 | 102 | uint32_t iotc_bsp_rng_get() { 103 | uint32_t random = 0; 104 | 105 | wc_RNG_GenerateBlock(&wolfcrypt_rng, (byte*)&random, 4); 106 | 107 | return random; 108 | } 109 | 110 | void iotc_bsp_rng_shutdown() { wc_FreeRng(&wolfcrypt_rng); } 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /port/src/iotc_bsp_time_posix.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2018-2020 Google LLC 2 | * 3 | * This is part of the Google Cloud IoT Device SDK for Embedded C. 4 | * It is licensed under the BSD 3-Clause license; you may not use this file 5 | * except in compliance with the License. 6 | * 7 | * You may obtain a copy of the License at: 8 | * https://opensource.org/licenses/BSD-3-Clause 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | void iotc_bsp_time_init() { /* empty */ 24 | } 25 | 26 | iotc_time_t iotc_bsp_time_getcurrenttime_seconds() { 27 | struct timeval current_time; 28 | gettimeofday(¤t_time, NULL); 29 | return (iotc_time_t)((current_time.tv_sec) + 30 | (current_time.tv_usec + 500000) / 31 | 1000000); /* round the microseconds to seconds */ 32 | } 33 | 34 | iotc_time_t iotc_bsp_time_getcurrenttime_milliseconds() { 35 | struct timeval current_time; 36 | gettimeofday(¤t_time, NULL); 37 | return (iotc_time_t)((current_time.tv_sec * 1000) + 38 | (current_time.tv_usec + 500) / 39 | 1000); /* round the microseconds to milliseconds */ 40 | } 41 | 42 | iotc_time_t iotc_bsp_time_getmonotonictime_milliseconds() { 43 | struct timespec current_time; 44 | clock_gettime(CLOCK_MONOTONIC, ¤t_time); 45 | return (iotc_time_t)((current_time.tv_sec * 1000) + 46 | (current_time.tv_nsec / 1000000)); 47 | } --------------------------------------------------------------------------------