├── .github ├── ISSUE_TEMPLATE │ └── issue-report.yml └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs └── logo.png ├── examples ├── ESP32 │ ├── ActionsHandling │ │ ├── ActionsHandling.ino │ │ ├── README.md │ │ └── arduino_secrets.h │ ├── BasicOTA │ │ ├── BasicOTA.ino │ │ ├── README.md │ │ └── arduino_secrets.h │ ├── BasicOTA_GSM │ │ ├── BasicOTA_GSM.ino │ │ ├── README.md │ │ └── arduino_secrets.h │ ├── CloudLogging │ │ ├── CloudLogging.ino │ │ ├── README.md │ │ └── arduino_secrets.h │ ├── EspTouch │ │ ├── EspTouch.ino │ │ ├── README.md │ │ └── arduino_secrets.h │ ├── HelloWokwi │ │ ├── HelloWokwi.ino │ │ ├── README.md │ │ ├── arduino_secrets.h │ │ ├── diagram.json │ │ └── wokwi.toml │ ├── PublishChipTemperature │ │ ├── PublishChipTemperature.ino │ │ ├── README.md │ │ └── arduino_secrets.h │ ├── PushData │ │ ├── PushData.ino │ │ ├── README.md │ │ └── arduino_secrets.h │ ├── README.md │ ├── SetupClient │ │ ├── README.md │ │ ├── SetupClient.ino │ │ └── arduino_secrets.h │ ├── SetupClient_GSM │ │ ├── README.md │ │ ├── SetupClient_GSM.ino │ │ └── arduino_secrets.h │ ├── ToggleLED │ │ ├── README.md │ │ ├── ToggleLED.ino │ │ └── arduino_secrets.h │ └── UpdateConfig │ │ ├── README.md │ │ ├── UpdateConfig.ino │ │ └── arduino_secrets.h ├── ESP8266 │ ├── README.md │ └── ToggleLED │ │ ├── README.md │ │ ├── ToggleLED.ino │ │ └── arduino_secrets.h ├── Provisioning │ ├── FATFSProvisioning │ │ ├── FATFSProvisioning.ino │ │ └── README.md │ ├── LITTLEFSProvisioning │ │ ├── LITTLEFSProvisioning.ino │ │ └── README.md │ ├── README.md │ └── SPIFFSProvisioning │ │ ├── README.md │ │ └── SPIFFSProvisioning.ino └── README.md ├── library.json ├── library.properties └── src ├── BytebeamArduino.cpp ├── BytebeamArduino.h ├── BytebeamArduinoDefines.h ├── BytebeamHTTPUpdate.cpp ├── BytebeamHTTPUpdate.h ├── BytebeamLog.cpp ├── BytebeamLog.h ├── BytebeamLogger.h ├── BytebeamOTA.cpp ├── BytebeamOTA.h ├── BytebeamTime.cpp └── BytebeamTime.h /.github/ISSUE_TEMPLATE/issue-report.yml: -------------------------------------------------------------------------------- 1 | name: Issue report 2 | description: Report any problem here 3 | labels: ["bug", "triage"] 4 | body: 5 | - type: input 6 | id: board 7 | attributes: 8 | label: Board 9 | description: On which Board does this issue occur? 10 | placeholder: eg. ESP32 Dev Module, ESP32-S2, NodeMCU 1.0 (ESP-12E Module)... 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: devboard 15 | attributes: 16 | label: Device Description 17 | description: What development board or other hardware is the chip attached to? 18 | placeholder: ex. DevKitC, plain module on breadboard, etc. If your hardware is custom or unusual, please attach a photo. 19 | validations: 20 | required: true 21 | - type: input 22 | id: arduino-esp32-version 23 | attributes: 24 | label: Arduino-ESP32 Version 25 | description: What version of Arduino ESP32 are you running? If possible, consider updating to the latest version. 26 | validations: 27 | required: true 28 | - type: input 29 | id: bytebeam-arduino-sdk-version 30 | attributes: 31 | label: Bytebeam Arduino SDK Version 32 | description: What version of Bytebeam Arduino SDK are you running? If possible, consider updating to the latest version. 33 | validations: 34 | required: true 35 | - type: input 36 | id: ide 37 | attributes: 38 | label: IDE Name 39 | description: What IDE are you using? 40 | placeholder: eg. Arduino IDE, PlatformIO... 41 | validations: 42 | required: true 43 | - type: input 44 | id: host-os 45 | attributes: 46 | label: Operating System 47 | description: On which OS does this issue occur? 48 | placeholder: ex. macOS 12.1, Windows 10... 49 | validations: 50 | required: true 51 | - type: textarea 52 | id: problem-escription 53 | attributes: 54 | label: Problem Description 55 | description: Please describe your problem here and expected behaviour 56 | placeholder: ex. Can't connect/weird behaviour/wrong function/missing parameter.. 57 | validations: 58 | required: true 59 | - type: textarea 60 | id: sketch 61 | attributes: 62 | label: Sketch 63 | description: Please provide full minimal sketch/code which can be run to reproduce your issue 64 | placeholder: ex. Related part of the code to replicate the issue 65 | render: cpp 66 | validations: 67 | required: true 68 | - type: textarea 69 | id: Debug 70 | attributes: 71 | label: Debug Message 72 | description: Please provide a debug message or error message. If you have a Guru Meditation Error or Backtrace, please decode it with [ExceptionDecoder](https://github.com/me-no-dev/EspExceptionDecoder) 73 | placeholder: Enable SDK debug level - Use BytebeamLogger::LOG_DEBUG in begin method, then put the serial output here. 74 | render: plain 75 | validations: 76 | required: true 77 | - type: textarea 78 | id: other-remarks 79 | attributes: 80 | label: More Information 81 | description: Is there any other information you can think of which will help us reproduce this problem? Any additional info can be added as well. 82 | placeholder: ex. I also tried on other OS, HW...it works correctly on that setup. -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | 5 | Closes # 6 | 7 | 9 | 10 | ### Why: 11 | Please describe why the changes had to be made. 12 | 13 | ## Changes Description 14 | Please describe your proposed Pull Request and it's impact. 15 | 16 | ## Tests Scenarios 17 | Please describe on what Hardware and Software combinations you have tested this Pull Request and how. 18 | 19 | (for eg. I have tested my Pull Request on Arduino-ESP32 Core SDK v2.0.7 and Bytebeam Arduino SDK Version 1.0.1 with ESP32 and ESP32-S2 Board with this scenario) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## [1.0.2] - 2022-05-17 8 | 9 | ### Added 10 | - Device Heartbeat 11 | - OTA Action Failure Message 12 | - Issue and Pull Request Template 13 | - Changelog 14 | 15 | ### Fixed 16 | - Improve Example's Documentation 17 | - Custom Action Failure Message and Action Progress State 18 | - Handle Unregistered and Retried Actions 19 | 20 | ## [1.0.1] - 2022-03-22 21 | 22 | ### Added 23 | - Arduino Secrets File 24 | - None Log Level in Bytebeam Logger 25 | 26 | ### Fixed 27 | - Improve Example's Documentation 28 | - Replaced boolean to standard bool 29 | - Renamed `isBegined()` to `isInitialized()` and kept as private 30 | 31 | ## [1.0.0] - 2023-03-16 32 | 33 | ### Added 34 | - The Initial Release that just works :) -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, caste, color, religion, or sexual 10 | identity and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the overall 26 | community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or advances of 31 | any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email address, 35 | without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | [Bytebeam GitHub organisation][git-org] or to [contact@bytebeam.io][email]. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series of 86 | actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or permanent 93 | ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within the 113 | community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.1, available at 119 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. 120 | 121 | Community Impact Guidelines were inspired by 122 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC]. 123 | 124 | For answers to common questions about this code of conduct, see the FAQ at 125 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at 126 | [https://www.contributor-covenant.org/translations][translations]. 127 | 128 | [homepage]: https://www.contributor-covenant.org 129 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html 130 | [Mozilla CoC]: https://github.com/mozilla/diversity 131 | [FAQ]: https://www.contributor-covenant.org/faq 132 | [translations]: https://www.contributor-covenant.org/translations 133 | 134 | [git-org]: https://github.com/orgs/bytebeamio/people 135 | [email]: mailto:contact@bytebeam.io -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to BytebeamArduino 2 | 3 | If you have loved using BytebeamArduino and want to give back, we would love to have you open GitHub issues and PRs for features, bugs and documentation improvements. 4 | 5 | Before you start, please make yourself familiar with the architecture of BytebeamArduino and read the [design docs][design] before making your first contribution to increase it's chances of being adopted. Please follow the [Code of Conduct][coc] when communicating with other members of the community and keep discussions civil, we are excited to have you make your first of many contributiions to this repository, welcome! 6 | 7 | ## Steps to Contribute 8 | 9 | ### Getting the library 10 | 11 | Go to and fork the library repository. 12 | 13 | ```bash 14 | # Open the terminal in the arduino libraries directory 15 | $ cd path_to_arduino_libraries 16 | 17 | # Remove the BytebeamArduino library if any 18 | $ rmdir /s /q BytebeamArduino 19 | 20 | # Clone your fork 21 | $ git clone git@github.com:/BytebeamArduino.git 22 | 23 | # Step into library directory 24 | $ cd BytebeamArduino 25 | 26 | # Create a branch for your changes (say my_topical_branch) 27 | $ git checkout -b my_topical_branch 28 | 29 | # Open the library in your favorite text editor (say vs code) 30 | $ code . 31 | ``` 32 | 33 | ### Library Setup 34 | 35 | Before stepping into library setup, launch the Arduino IDE. If you have not installed the Arduino IDE yet then the best place to get started will be the [Arduino Getting Started Guide][arduino-get-started] 36 | 37 | Look at the example sketch (say ToggleLED) for reference. See File > Examples > BytebeamArduino > ToggleLED within the Arduino IDE. You can use Arduino IDE GUI to verify and upload the example sketch 38 | 39 | ### Making Changes 40 | 41 | Please make sure your changes conform to Arduino Style Guide. 42 | 43 | - For core library refer [Arduino Library Style Guide][arduino-library-style] 44 | - For tutorials and example sketches refer [Arduino Writing Style Guide][arduino-writing-style] 45 | 46 | ### Testing & CI 47 | 48 | Tests Suite is not yet added to the repo, will add it once we are done with the development cycle of the first release. By the way you can contribute this too :) 49 | 50 | ## Add yourself to Contributors 51 | 52 | Thank you for contributing to BytebeamArduino, Please feel free to add yourself to [Contributors][contributors] 53 | 54 | ## License 55 | 56 | BytebeamArduino is licensed under the permissive [Apache License Version 2.0][license] and we accept contributions under the implied notion that they are made in complete renunciation of the contributors any rights or claims to the same after the code has been merged into the codebase. 57 | 58 | [license]: LICENSE 59 | [design]: docs/design.md 60 | [coc]: CODE_OF_CONDUCT.md 61 | [arduino-get-started]: https://docs.arduino.cc/learn/starting-guide/getting-started-arduino 62 | [arduino-library-style]: https://docs.arduino.cc/learn/contributions/arduino-library-style-guide 63 | [arduino-writing-style]: https://docs.arduino.cc/learn/contributions/arduino-writing-style-guide 64 | [contributors]: AUTHORS.md#contributors -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BytebeamArduino 2 | 3 |
4 | Bytebeam Arduino Logo 5 |
6 | 7 | --- 8 | 9 | [![arduino-library-badge](https://www.ardu-badge.com/badge/BytebeamArduino.svg?)](https://www.ardu-badge.com/BytebeamArduino) 10 | [![PlatformIO Registry](https://badges.registry.platformio.org/packages/bytebeamio/library/BytebeamArduino.svg)](https://registry.platformio.org/libraries/bytebeamio/BytebeamArduino) 11 | 12 | This Library provides a simple client for connecting ESP devices to [Bytebeam](https://bytebeam.io/) IoT platform. 13 | 14 | ## Features :- 15 | - Efficiently send data to cloud. 16 | - Receive commands from the cloud, execute them and update progress of execution. 17 | - Download Firmware images from cloud in case of OTA updates being triggered from cloud. 18 | 19 | 20 | ## What's included in the Library :- 21 | 22 | - **src** :- This section contains source code for various functions that can be used by applications for interacting with Bytebeam platform. 23 | - **examples** :- This folder conatins few example sketch which demonstrates establishing secure connection with Bytebeam platform. Also, it demonstrates periodic data pushing and receiving actions. 24 | 25 | ## Dependencies :- 26 | - [PubSubClient](https://github.com/knolleary/pubsubclient) 27 | - [Arduinojson](https://github.com/bblanchon/ArduinoJson) 28 | - [NTPClient](https://github.com/arduino-libraries/NTPClient) 29 | - Core SDK ( [ESP32](https://github.com/espressif/arduino-esp32) or [ESP8266](https://github.com/esp8266/Arduino) ) 30 | - Dev Board ( ESP32 or ESP8266 ) 31 | 32 | We recommend to install the latest versions of the libraries and Core SDK. 33 | 34 | ## Getting Started :- 35 | This Library can be integrated with new as well as existing Arduino ESP32 or Arduino ESP8266 sketches. Follow the [instruction guide](https://bytebeam.io/docs/arduino) for setting up and integrating Library with your Arduino sketch. 36 | 37 | ## Community :- 38 | 39 | - Follow us on [Twitter](https://twitter.com/bytebeamhq) 40 | - Connect with us on [LinkedIn](https://www.linkedin.com/company/bytebeam/) 41 | - Read our official [Blog](https://bytebeam.io/blog/) 42 | 43 | ## Contributing :- 44 | Contributions are welcome! Not only you’ll encourage the development of the Library, but you’ll also learn how to best use the Library and probably some C++ too. 45 | 46 | See [the contributing guide](CONTRIBUTING.md) for detailed instructions on how to get started with the Library. Please follow the [code of conduct](CODE_OF_CONDUCT.md) while contributing. 47 | 48 | ## License :- 49 | 50 | This project is released under The Apache License, Version 2.0 (See [LICENSE](./LICENSE) for details) 51 | -------------------------------------------------------------------------------- /docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bytebeamio/bytebeam-arduino-sdk/2f3d54917f17c70f029129a3c9dd98884010d105/docs/logo.png -------------------------------------------------------------------------------- /examples/ESP32/ActionsHandling/ActionsHandling.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // wifi credentials 7 | const char* WIFI_SSID = SECRET_SSID; 8 | const char* WIFI_PASSWORD = SECRET_PASS; 9 | 10 | // sntp credentials 11 | const long gmtOffset_sec = 19800; // GMT + 5:30h 12 | const int daylightOffset_sec = 0; 13 | const char* ntpServer = "pool.ntp.org"; 14 | 15 | // function to setup the wifi with predefined credentials 16 | void setupWifi() { 17 | // set the wifi to station mode to connect to a access point 18 | WiFi.mode(WIFI_STA); 19 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 20 | 21 | Serial.println(); 22 | Serial.print("Connecting to " + String(WIFI_SSID)); 23 | 24 | // wait till chip is being connected to wifi (Blocking Mode) 25 | while (WiFi.status() != WL_CONNECTED) { 26 | Serial.print("."); 27 | delay(250); 28 | } 29 | 30 | // now it is connected to the access point just print the ip assigned to chip 31 | Serial.println(); 32 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 33 | Serial.println(WiFi.localIP()); 34 | } 35 | 36 | // function to sync time from ntp server with predefined credentials 37 | void syncTimeFromNtp() { 38 | // sync the time from ntp server 39 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 40 | 41 | struct tm timeinfo; 42 | 43 | // get the current time 44 | if(!getLocalTime(&timeinfo)) { 45 | Serial.println("Failed to obtain time"); 46 | return; 47 | } 48 | 49 | // log the time info to serial :) 50 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 51 | Serial.println(); 52 | } 53 | 54 | // handler for hello world action 55 | int HelloWorld_Hanlder(char* args, char* actionId) { 56 | // 57 | // nothing much to do here 58 | // 59 | 60 | Serial.println("Hello World"); 61 | 62 | // publish action completed status 63 | if(!Bytebeam.publishActionCompleted(actionId)) { 64 | Serial.println("Failed to publish action completed response for Hello World action"); 65 | return -1; 66 | } 67 | 68 | return 0; 69 | } 70 | 71 | // yet another handler for hello world action 72 | int YetAnotherHelloWorld_Hanlder(char* args, char* actionId) { 73 | // 74 | // nothing much to do here 75 | // 76 | 77 | Serial.println("Yet Another Hello World"); 78 | 79 | // publish action completed status 80 | if(!Bytebeam.publishActionCompleted(actionId)) { 81 | Serial.println("Failed to publish action completed response for Hello World action"); 82 | return -1; 83 | } 84 | 85 | return 0; 86 | } 87 | 88 | void setup() { 89 | // put your setup code here, to run once: 90 | Serial.begin(115200); 91 | Serial.println(); 92 | 93 | setupWifi(); 94 | syncTimeFromNtp(); 95 | 96 | // setting up the device info i.e to be seen in the device shadow 97 | Bytebeam.status = "Device is Up!"; 98 | Bytebeam.softwareType = "actions-handling-ino"; 99 | Bytebeam.softwareVersion = "1.0.0"; 100 | Bytebeam.hardwareType = "ESP32 Dev Module"; 101 | Bytebeam.hardwareVersion = "rev1"; 102 | 103 | // begin the bytebeam client 104 | if(!Bytebeam.begin()) { 105 | Serial.println("Bytebeam Client Initialization Failed."); 106 | } else { 107 | Serial.println("Bytebeam Client is Initialized Successfully."); 108 | } 109 | 110 | // add the handler for hello world led action 111 | Bytebeam.addActionHandler(HelloWorld_Hanlder, "HelloWorld"); 112 | 113 | // Call the isActionHandlerThere method to check if particular action exists or not at any point of time in the code 114 | // Bytebeam.isActionHandlerThere("HelloWorld"); 115 | 116 | // Call the updateActionHandler method to update the particular action at any point of time in the code 117 | // Bytebeam.updateActionHandler(YetAnotherHelloWorld_Hanlder, "HelloWorld"); 118 | 119 | // Call the printActionHandlerArray method to print the action handler array at any point of time in the code 120 | // Bytebeam.printActionHandlerArray(); 121 | 122 | // Call the removeActionHandler method to remove the particular action at any point of time in the code 123 | // Bytebeam.removeActionHandler("HelloWorld"); 124 | 125 | // Call the resetActionHandlerArray method to reset the action handler array at any point of time in the code 126 | // Bytebeam.resetActionHandlerArray(); 127 | } 128 | 129 | void loop() { 130 | // put your main code here, to run repeatedly: 131 | 132 | // bytebeam client loop 133 | Bytebeam.loop(); 134 | 135 | // hold on the execution for some time 136 | delay(5000); 137 | } -------------------------------------------------------------------------------- /examples/ESP32/ActionsHandling/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Actions Handling Example 2 | This example will show you how to manage actions with Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/ActionsHandling/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/BasicOTA/BasicOTA.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | const char* fwVersion = "1.0.0"; 7 | 8 | // wifi credentials 9 | const char* WIFI_SSID = SECRET_SSID; 10 | const char* WIFI_PASSWORD = SECRET_PASS; 11 | 12 | // sntp credentials 13 | const long gmtOffset_sec = 19800; // GMT + 5:30h 14 | const int daylightOffset_sec = 0; 15 | const char* ntpServer = "pool.ntp.org"; 16 | 17 | // function to setup the wifi with predefined credentials 18 | void setupWifi() { 19 | // set the wifi to station mode to connect to a access point 20 | WiFi.mode(WIFI_STA); 21 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 22 | 23 | Serial.println(); 24 | Serial.print("Connecting to " + String(WIFI_SSID)); 25 | 26 | // wait till chip is being connected to wifi (Blocking Mode) 27 | while (WiFi.status() != WL_CONNECTED) { 28 | Serial.print("."); 29 | delay(250); 30 | } 31 | 32 | // now it is connected to the access point just print the ip assigned to chip 33 | Serial.println(); 34 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 35 | Serial.println(WiFi.localIP()); 36 | } 37 | 38 | // function to sync time from ntp server with predefined credentials 39 | void syncTimeFromNtp() { 40 | // sync the time from ntp server 41 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 42 | 43 | struct tm timeinfo; 44 | 45 | // get the current time 46 | if(!getLocalTime(&timeinfo)) { 47 | Serial.println("Failed to obtain time"); 48 | return; 49 | } 50 | 51 | // log the time info to serial :) 52 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 53 | Serial.println(); 54 | } 55 | 56 | void setup() { 57 | // put your setup code here, to run once: 58 | Serial.begin(115200); 59 | Serial.println(); 60 | 61 | setupWifi(); 62 | syncTimeFromNtp(); 63 | 64 | // setting up the device info i.e to be seen in the device shadow 65 | Bytebeam.status = "Device is Up!"; 66 | Bytebeam.softwareType = "basic-wifi-ota-ino"; 67 | Bytebeam.softwareVersion = "1.0.0"; 68 | Bytebeam.hardwareType = "ESP32 Dev Module"; 69 | Bytebeam.hardwareVersion = "rev1"; 70 | 71 | // begin the bytebeam client 72 | if(!Bytebeam.begin()) { 73 | Serial.println("Bytebeam Client Initialization Failed."); 74 | } else { 75 | Serial.println("Bytebeam Client is Initialized Successfully."); 76 | } 77 | 78 | // check if OTA is enabled or disabled for your device 79 | bool OTAStatus = Bytebeam.isOTAEnabled(); 80 | 81 | if(!OTAStatus) { 82 | Serial.println("OTA is Disabled."); 83 | } else { 84 | Serial.println("OTA is Enabled."); 85 | } 86 | 87 | // enable OTA updates for your device 88 | Bytebeam.enableOTA(); 89 | 90 | // disable OTA updates for your device (default) 91 | // Bytebeam.disableOTA(); 92 | 93 | Serial.printf("Application Firmware Version : %s\n", fwVersion); 94 | } 95 | 96 | void loop() { 97 | // put your main code here, to run repeatedly: 98 | 99 | // bytebeam client loop 100 | Bytebeam.loop(); 101 | 102 | // hold on execution for some time 103 | delay(5000); 104 | } -------------------------------------------------------------------------------- /examples/ESP32/BasicOTA/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Basic OTA Example 2 | This example will show you how to do over the air firmware upgrades with Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/BasicOTA/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/BasicOTA_GSM/BasicOTA_GSM.ino: -------------------------------------------------------------------------------- 1 | #define TINY_GSM_MODEM_SIM7600 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | #define LED_PIN 12 7 | #define MODEM_PWRKEY 4 8 | #define MODEM_FLIGHT 25 9 | #define MODEM_TX 27 10 | #define MODEM_RX 26 11 | 12 | // set GSM PIN, if any 13 | #define GSM_PIN SECRET_PIN 14 | 15 | #define SerialMon Serial 16 | #define SerialAT Serial1 17 | 18 | // Your GPRS credentials, if any 19 | const char apn[] = SECRET_APN; 20 | const char gprsUser[] = SECRET_USER; 21 | const char gprsPass[] = SECRET_PASS; 22 | 23 | const char* fwVersion = "1.0.0"; 24 | 25 | TinyGsm modem(SerialAT); 26 | 27 | // function to setup the modem with predefined credentials 28 | void setupModem() { 29 | // configure your reset, enable pins here if needed 30 | pinMode(LED_PIN, OUTPUT); 31 | pinMode(MODEM_PWRKEY, OUTPUT); 32 | pinMode(MODEM_FLIGHT, OUTPUT); 33 | 34 | // set the status led pin low to indicate the start process 35 | digitalWrite(LED_PIN, LOW); 36 | 37 | // pull up power pin (IO:4) Modulator power key, need to powered up the modem 38 | // this pin must be held high for more than 1 second according to manual requirements 39 | digitalWrite(MODEM_PWRKEY, LOW); 40 | delay(100); 41 | digitalWrite(MODEM_PWRKEY, HIGH); 42 | delay(1000); 43 | digitalWrite(MODEM_PWRKEY, LOW); 44 | 45 | // pull up the power pin (IO:25) Modulator flight mode control, need to enable modulator 46 | // this pin must be set to high 47 | digitalWrite(MODEM_FLIGHT, HIGH); 48 | 49 | SerialMon.println("Modem Powered ON"); 50 | 51 | // start the serial communication b/w esp32 and modem 52 | SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX); 53 | delay(6000); 54 | 55 | // Restart takes quite some time 56 | // To skip it, call init() instead of restart() 57 | modem.restart(); 58 | // modem.init(); 59 | 60 | // set the network mode (2 : Automatic) 61 | modem.setNetworkMode(2); 62 | 63 | String modemName = modem.getModemName(); 64 | SerialMon.printf("Modem Name : "); 65 | SerialMon.println(modemName); 66 | 67 | String modemInfo = modem.getModemInfo(); 68 | SerialMon.print("Modem Info : "); 69 | SerialMon.println(modemInfo); 70 | 71 | // Unlock your SIM card with a PIN if needed 72 | if(GSM_PIN && modem.getSimStatus() != 3) { 73 | modem.simUnlock(GSM_PIN); 74 | } 75 | 76 | SimStatus simStatus = modem.getSimStatus(); 77 | 78 | if(simStatus != SIM_READY) { 79 | SerialMon.println("Couldn't Ready the SIM."); 80 | return; 81 | } 82 | SerialMon.println("SIM is Ready."); 83 | 84 | // high indicates the modem is initialized successfully 85 | digitalWrite(LED_PIN, HIGH); 86 | SerialMon.println("Modem Initialized Successfully !"); 87 | 88 | SerialMon.println("Waiting for network..."); 89 | if(!modem.waitForNetwork()) { 90 | SerialMon.println(" fail"); 91 | delay(10000); 92 | return; 93 | } 94 | SerialMon.println(" success"); 95 | 96 | if(modem.isNetworkConnected()) { 97 | SerialMon.println("Network connected"); 98 | } 99 | 100 | // GPRS connection parameters are usually set after network registration 101 | SerialMon.print("Connecting to apn : "); 102 | SerialMon.println(apn); 103 | 104 | if (!modem.gprsConnect(apn)) { 105 | SerialMon.println(" fail"); 106 | delay(10000); 107 | return; 108 | } 109 | SerialMon.println(" success"); 110 | 111 | if(modem.isGprsConnected()) { 112 | SerialMon.println("GPRS connected"); 113 | } 114 | } 115 | 116 | // function to sync time from ntp server with predefined credentials 117 | void syncTimeFromNtp() { 118 | String dateTime = modem.getGSMDateTime(DATE_FULL); 119 | 120 | SerialMon.print("Current Time : "); 121 | SerialMon.println(dateTime); 122 | SerialMon.println(); 123 | } 124 | 125 | void setup() { 126 | // put your setup code here, to run once: 127 | SerialMon.begin(115200); 128 | SerialMon.println(); 129 | 130 | setupModem(); 131 | syncTimeFromNtp(); 132 | 133 | // setting up the device info i.e to be seen in the device shadow 134 | Bytebeam.status = "Device is Up!"; 135 | Bytebeam.softwareType = "basic-gsm-ota-ino"; 136 | Bytebeam.softwareVersion = "1.0.0"; 137 | Bytebeam.hardwareType = "ESP32 Dev Module"; 138 | Bytebeam.hardwareVersion = "rev1"; 139 | 140 | // begin the bytebeam client 141 | if(!Bytebeam.begin(&modem)) { 142 | Serial.println("Bytebeam Client Initialization Failed."); 143 | } else { 144 | Serial.println("Bytebeam Client is Initialized Successfully."); 145 | } 146 | 147 | // check if OTA is enabled or disabled for your device 148 | bool OTAStatus = Bytebeam.isOTAEnabled(); 149 | 150 | if(!OTAStatus) { 151 | SerialMon.println("OTA is Disabled."); 152 | } else { 153 | SerialMon.println("OTA is Enabled."); 154 | } 155 | 156 | // enable OTA updates for your device 157 | Bytebeam.enableOTA(); 158 | 159 | // disable OTA updates for your device (default) 160 | // Bytebeam.disableOTA(); 161 | 162 | SerialMon.printf("Application Firmware Version : %s\n", fwVersion); 163 | } 164 | 165 | void loop() { 166 | // put your main code here, to run repeatedly: 167 | 168 | // bytebeam client loop 169 | Bytebeam.loop(); 170 | 171 | // hold on execution for some time 172 | delay(5000); 173 | } -------------------------------------------------------------------------------- /examples/ESP32/BasicOTA_GSM/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Basic OTA Via GSM Example 2 | This example will show you how to do over the air firmware upgrades with Bytebeam IoT Platform via GSM. 3 | 4 | ## Hardware specification 5 | 1. [TTGO T-SIM7600E](https://www.lilygo.cc/products/t-sim7600) 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library 9 | 2. [TinyGSM Library](https://github.com/vshymanskyy/TinyGSM) 10 | 3. [ArduinoHttpClient Library](https://github.com/arduino-libraries/ArduinoHttpClient) 11 | 4. [SSLClient Library](https://github.com/govorox/SSLClient.git) -------------------------------------------------------------------------------- /examples/ESP32/BasicOTA_GSM/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_PIN "" 6 | #define SECRET_APN "" 7 | #define SECRET_USER "" 8 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/CloudLogging/CloudLogging.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // wifi credentials 7 | const char* WIFI_SSID = SECRET_SSID; 8 | const char* WIFI_PASSWORD = SECRET_PASS; 9 | 10 | // sntp credentials 11 | const long gmtOffset_sec = 19800; // GMT + 5:30h 12 | const int daylightOffset_sec = 0; 13 | const char* ntpServer = "pool.ntp.org"; 14 | 15 | // device status 16 | char deviceStatus[200] = ""; 17 | 18 | // cloud logging tag 19 | const char* TAG = "BYTEBEAM_CLOUD_LOGGING_SKETCH"; 20 | 21 | // function to setup the wifi with predefined credentials 22 | void setupWifi() { 23 | // set the wifi to station mode to connect to a access point 24 | WiFi.mode(WIFI_STA); 25 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 26 | 27 | Serial.println(); 28 | Serial.print("Connecting to " + String(WIFI_SSID)); 29 | 30 | // wait till chip is being connected to wifi (Blocking Mode) 31 | while (WiFi.status() != WL_CONNECTED) { 32 | Serial.print("."); 33 | delay(250); 34 | } 35 | 36 | // now it is connected to the access point just print the ip assigned to chip 37 | Serial.println(); 38 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 39 | Serial.println(WiFi.localIP()); 40 | } 41 | 42 | // function to sync time from ntp server with predefined credentials 43 | void syncTimeFromNtp() { 44 | // sync the time from ntp server 45 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 46 | 47 | struct tm timeinfo; 48 | 49 | // get the current time 50 | if(!getLocalTime(&timeinfo)) { 51 | Serial.println("Failed to obtain time"); 52 | return; 53 | } 54 | 55 | // log the time info to serial :) 56 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 57 | Serial.println(); 58 | } 59 | 60 | // function to test the cloud logging feature 61 | void bytebeamCloudLoggingTest() { 62 | // 63 | // default bytebeam log level is BYTEBEAM_LOG_LEVEL_INFO, so logs beyond info level will not work :) 64 | // 65 | 66 | Bytebeam.logErrorf(TAG, "I am %s Log", "Error"); 67 | Bytebeam.logWarnf(TAG, "I am %s Log", "Warn"); 68 | Bytebeam.logInfof(TAG, "I am %s Log", "Info"); 69 | Bytebeam.logDebugf(TAG, "I am %s Log", "Debug"); // debug log will not appear to cloud 70 | Bytebeam.logVerbosef(TAG, "I am %s Log", "Verbose"); // verbose log will not appear to cloud 71 | 72 | // changing log level to Verbose for showing use case 73 | Bytebeam.setLogLevel(BYTEBEAM_LOG_LEVEL_VERBOSE); 74 | 75 | // 76 | // now bytebeam log level is BYTEBEAM_LOG_LEVEL_VERBOSE, so every logs should work now :) 77 | // 78 | 79 | Bytebeam.logErrorf(TAG, "This is %s Log", "Error"); 80 | Bytebeam.logWarnf(TAG, "This is %s Log", "Warn"); 81 | Bytebeam.logInfof(TAG, "This is %s Log", "Info"); 82 | Bytebeam.logDebugf(TAG, "This is %s Log", "Debug"); // debug log should appear to cloud 83 | Bytebeam.logVerbosef(TAG, "This is %s Log", "Verbose"); // verbose log should appear to cloud 84 | 85 | // changing log level back to Info for meeting initial conditions 86 | Bytebeam.setLogLevel(BYTEBEAM_LOG_LEVEL_INFO); 87 | 88 | Serial.println("Bytebeam Cloud Logging Test Executed Successfully !"); 89 | } 90 | 91 | void setup() { 92 | // put your setup code here, to run once: 93 | Serial.begin(115200); 94 | Serial.println(); 95 | 96 | setupWifi(); 97 | syncTimeFromNtp(); 98 | 99 | // setting up the device info i.e to be seen in the device shadow 100 | Bytebeam.status = "Device is Up!"; 101 | Bytebeam.softwareType = "cloud-logging-ino"; 102 | Bytebeam.softwareVersion = "1.0.0"; 103 | Bytebeam.hardwareType = "ESP32 Dev Module"; 104 | Bytebeam.hardwareVersion = "rev1"; 105 | 106 | // begin the bytebeam client 107 | if(!Bytebeam.begin()) { 108 | Serial.println("Bytebeam Client Initialization Failed."); 109 | } else { 110 | Serial.println("Bytebeam Client is Initialized Successfully."); 111 | } 112 | 113 | // check if cloud logging is enabled or disabled for your device 114 | bool cloudLoggingStatus = Bytebeam.isCloudLoggingEnabled(); 115 | 116 | if(!cloudLoggingStatus) { 117 | Serial.println("Cloud Logging is Disabled."); 118 | } else { 119 | Serial.println("Cloud Logging is Enabled."); 120 | } 121 | 122 | // enable cloud logging for your device (default) 123 | // Bytebeam.enableCloudLogging(); 124 | 125 | // disable cloud logging for your device 126 | // Bytebeam.disableCloudLogging(); 127 | 128 | // get the log stream name 129 | // char* log_stream_name = Bytebeam.getLogStream(); 130 | 131 | // configure the log stream if needed, defaults to "logs" 132 | // Bytebeam.setLogStream("device_logs"); 133 | 134 | // get the bytebeam log level 135 | // int current_log_level = Bytebeam.getLogLevel(); 136 | 137 | // set the bytebeam log level 138 | // Bytebeam.setLogLevel(log_level_to_set); 139 | 140 | // test the cloud logging feature 141 | // bytebeamCloudLoggingTest(); 142 | } 143 | 144 | void loop() { 145 | // put your main code here, to run repeatedly: 146 | 147 | // bytebeam client loop 148 | Bytebeam.loop(); 149 | 150 | // get the connection status 151 | bool connectionStatus = Bytebeam.isConnected(); 152 | 153 | // get the device status 154 | sprintf(deviceStatus, "Device Status : %s !", connectionStatus? "Connected" : "Disconnected"); 155 | 156 | // log the device status to cloud 157 | Bytebeam.logInfoln(TAG, deviceStatus); 158 | 159 | // hold on the execution for some time 160 | delay(10000); 161 | } -------------------------------------------------------------------------------- /examples/ESP32/CloudLogging/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Cloud Logging Example 2 | This example will show you how to log the useful information to Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/CloudLogging/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/EspTouch/EspTouch.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // touch gpio pin number 7 | #define TOUCH_GPIO_PIN 15 8 | 9 | // esp touch stream name 10 | char espTouchStream[] = "esp_touch"; 11 | 12 | // wifi credentials 13 | const char* WIFI_SSID = SECRET_SSID; 14 | const char* WIFI_PASSWORD = SECRET_PASS; 15 | 16 | // sntp credentials 17 | const long gmtOffset_sec = 19800; // GMT + 5:30h 18 | const int daylightOffset_sec = 0; 19 | const char* ntpServer = "pool.ntp.org"; 20 | 21 | // function to setup the wifi with predefined credentials 22 | void setupWifi() { 23 | // set the wifi to station mode to connect to a access point 24 | WiFi.mode(WIFI_STA); 25 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 26 | 27 | Serial.println(); 28 | Serial.print("Connecting to " + String(WIFI_SSID)); 29 | 30 | // wait till chip is being connected to wifi (Blocking Mode) 31 | while (WiFi.status() != WL_CONNECTED) { 32 | Serial.print("."); 33 | delay(250); 34 | } 35 | 36 | // now it is connected to the access point just print the ip assigned to chip 37 | Serial.println(); 38 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 39 | Serial.println(WiFi.localIP()); 40 | } 41 | 42 | // function to sync time from ntp server with predefined credentials 43 | void syncTimeFromNtp() { 44 | // sync the time from ntp server 45 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 46 | 47 | struct tm timeinfo; 48 | 49 | // get the current time 50 | if(!getLocalTime(&timeinfo)) { 51 | Serial.println("Failed to obtain time"); 52 | return; 53 | } 54 | 55 | // log the time info to serial :) 56 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 57 | Serial.println(); 58 | } 59 | 60 | // function to get the esp touch value 61 | uint16_t getEspTouchValue() { 62 | return touchRead(TOUCH_GPIO_PIN); 63 | } 64 | 65 | // function to get the time 66 | unsigned long long getEpochMillis() { 67 | time_t now; 68 | struct tm timeinfo; 69 | 70 | // get the current time i.e make sure the device is in sync with the ntp server 71 | if (!getLocalTime(&timeinfo)) { 72 | Serial.println("failed to obtain time"); 73 | return 0; 74 | } 75 | 76 | // get the epoch time 77 | time(&now); 78 | 79 | // generate the epoch millis 80 | unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000); 81 | 82 | return timeMillis; 83 | } 84 | 85 | // function to publish esp touch value to esp touch stream 86 | bool publishEspTouchValues() { 87 | static int sequence = 0; 88 | unsigned long long milliseconds = 0; 89 | 90 | const char* payload = ""; 91 | String deviceShadowStr = ""; 92 | StaticJsonDocument<1024> doc; 93 | 94 | // get the current epoch millis 95 | milliseconds = getEpochMillis(); 96 | 97 | // make sure you got the millis 98 | if(milliseconds == 0) { 99 | Serial.println("failed to get epoch millis"); 100 | return false; 101 | } 102 | 103 | // increment the sequence counter 104 | sequence++; 105 | 106 | // get the connection status 107 | bool connectionStatus = Bytebeam.isConnected(); 108 | 109 | // get the esp touch value 110 | uint16_t touchValue = getEspTouchValue(); 111 | 112 | JsonArray deviceShadowJsonArray = doc.to(); 113 | JsonObject deviceShadowJsonObj_1 = deviceShadowJsonArray.createNestedObject(); 114 | 115 | deviceShadowJsonObj_1["timestamp"] = milliseconds; 116 | deviceShadowJsonObj_1["sequence"] = sequence; 117 | deviceShadowJsonObj_1["touch"] = touchValue; 118 | 119 | serializeJson(deviceShadowJsonArray, deviceShadowStr); 120 | payload = deviceShadowStr.c_str(); 121 | 122 | Serial.printf("publishing %s to %s\n", payload, espTouchStream); 123 | 124 | return Bytebeam.publishToStream(espTouchStream, payload); 125 | } 126 | 127 | void setup() { 128 | // put your setup code here, to run once: 129 | Serial.begin(115200); 130 | Serial.println(); 131 | 132 | setupWifi(); 133 | syncTimeFromNtp(); 134 | 135 | // setting up the device info i.e to be seen in the device shadow 136 | Bytebeam.status = "Device is Up!"; 137 | Bytebeam.softwareType = "esp-touch-ino"; 138 | Bytebeam.softwareVersion = "1.0.0"; 139 | Bytebeam.hardwareType = "ESP32 Dev Module"; 140 | Bytebeam.hardwareVersion = "rev1"; 141 | 142 | // begin the bytebeam client 143 | if(!Bytebeam.begin()) { 144 | Serial.println("Bytebeam Client Initialization Failed."); 145 | } else { 146 | Serial.println("Bytebeam Client is Initialized Successfully."); 147 | } 148 | } 149 | 150 | void loop() { 151 | // put your main code here, to run repeatedly: 152 | 153 | // bytebeam client loop 154 | Bytebeam.loop(); 155 | 156 | // publish device status to device shadow 157 | if(!publishEspTouchValues()) { 158 | Serial.println("Failed to publish esp touch value to esp touch stream"); 159 | } 160 | 161 | // hold on execution for some time 162 | delay(10000); 163 | } -------------------------------------------------------------------------------- /examples/ESP32/EspTouch/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Esp Touch Example 2 | ESP32 comes with capacitive touch GPIOs which can sense human touch. We will make use of these touch GPIO to send touch values to bytebeam cloud 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/EspTouch/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/HelloWokwi/HelloWokwi.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // on board led pin number 7 | #define BOARD_LED 2 8 | 9 | // led state variable 10 | int ledState = 0; 11 | 12 | // wifi credentials 13 | const char* WIFI_SSID = SECRET_SSID; 14 | const char* WIFI_PASSWORD = SECRET_PASS; 15 | 16 | // sntp credentials 17 | const long gmtOffset_sec = 19800; // GMT + 5:30h 18 | const int daylightOffset_sec = 0; 19 | const char* ntpServer = "pool.ntp.org"; 20 | 21 | // Replace this with your device config json in the same format 22 | char deviceConfigData[] = R"( 23 | { 24 | "project_id": "demo", 25 | "broker": "cloud.bytebeam.io", 26 | "port": 8883, 27 | "device_id": "1", 28 | "authentication": { 29 | "ca_certificate": "-----BEGIN CERTIFICATE-----\nMIIFrDCCA5SgAwIBAgICBMwDQYJAwdzEOMAwGA1UBhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYcmUxFzAVBgNV\nBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIxMDkwMjExMDYyM1oXDTMxMDkwMjExMDYyM1owdzEOMAwG\nA1UEBhMFSW5kaWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCYW5nYWxv\ncmUxFzAVBgNVBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDAS\nBgNVBAoTC0J5dGViZWFtLmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC\nAgEAr/bnOa/8AUGZmd/s+7rejuROgeLqqU9X15KKfKOBqcoMyXsSO65UEwpzadpw\nMl7GDCdHqFTymqdnAnbhgaT1PoIFhOG64y7UiNgiWmbh0XJj8G6oLrW9rQ1gug1Q\n/D7x2fUnza71aixiwEL+KsIFYIdDuzmoRD3rSer/bKOcGGs0WfB54KqIVVZ1DwsU\nk1wx5ExsKo7gAdXMAbdHRI2Szmn5MsZwGL6V0LfsKLE8ms2qlZe50oo2woLNN6XP\nRfRL4bwwkdsCqXWkkt4eUSNDq9hJsuINHdhO3GUieLsKLJGWJ0lq6si74t75rIKb\nvvsFEQ9mnAVS+iuUUsSjHPJIMnn/J64Nmgl/R/8FP5TUgUrHvHXKQkJ9h/a7+3tS\nlV2KMsFksXaFrGEByGIJ7yR4qu9hx5MXf8pf8EGEwOW/H3CdWcC2MvJ11PVpceUJ\neDVwE7B4gPM9Kx02RNwvUMH2FmYqkXX2DrrHQGQuq+6VRoN3rEdmGPqnONJEPeOw\nZzcGDVXKWZtd7UCbcZKdn0RYmVtI/OB5OW8IRoXFYgGB3IWP796dsXIwbJSqRb9m\nylICGOceQy3VR+8+BHkQLj5/ZKTe+AA3Ktk9UADvxRiWKGcejSA/LvyT8qzz0dqn\nGtcHYJuhJ/XpkHtB0PykB5WtxFjx3G/osbZfrNflcQZ9h1MCAwEAAaNCMEAwDgYD\nVR0PAQH/BAQDAgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKl/MTbLrZ0g\nurneOmAfBHO+LHz+MA0GCSqGSIb3DQEBCwUAA4ICAQAlus/uKic5sgo1d2hBJ0Ak\ns1XJsA2jz+OEdshQHmCCmzFir3IRSuVRmDBaBGlJDHCELqYxKn6dl/sKGwoqoAQ5\nOeR2sey3Nmdyw2k2JTDx58HnApZKAVir7BDxbIbbHmfhJk4ljeUBbertNXWbRHVr\ncs4XBNwXvX+noZjQzmXXK89YBsV2DCrGRAUeZ4hQEqV7XC0VKmlzEmfkr1nibDr5\nqwbI+7QWIAnkHggYi27lL2UTH7TvkwYC4TyDaoQ2ZRpG\nHY+mxXLdftoMv/ZvmyjOPYeTRQbfPqoRqcM6XOPXwSw9B6YddwmnkI7ohNOvAVfD\nwGptUc5OodgFQc3waRljX1q2lawZCTh58IUf32CRtOEL2RIz4VpUrNF/0E2vts1f\npO7V1vY2Qin998Nwqkxdsll0GLtEEE9hUyvk1F8U+fgjJ3Rjn4BxnCN4oCrdJOMa\nJCaysaHV7EEIMqrYP4jH6RzQzOXLd0m9NaL8A/Y9z2a96fwpZZU/fEEOH71t3Eo3\nV/CKlysiALMtsHfZDwHNpa6g0NQNGN5IRl/w1TS1izzjzgWhR6r8wX8OPLRzhNRz\n2HDbTXGYsem0ihC0B8uzujOhTHcBwsfxZUMpGjg8iycJlfpPDWBdw8qrGu8LeNux\na0cIevjvYAtVysoXInV0kg==\n-----END CERTIFICATE-----\n", 30 | "device_certificate": "-----BEGIN CERTIFICATE-----\nMIIEcjCCAlqgAwIBAgICB+MwhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIyMTEwMzA3NDcwMloXDTMyMTEKTEbMBkG\nA1UEChMSZXNwYnl0ZWJlYW1zZGt0ZXN0MQowCAYDVQQDEwExMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsm8CF8fKSzWFKZeO52RJRGER4z7sYrgTb9x\noIeljE8kmhR+EW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXa\nbI9manlqw0WqAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+s\nn6j5yEUnWKSIgoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY\n4X9UpdrjS5cRWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9\nplTq7I9/fDnkRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABo1YwVDAO\nBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0jBBgwFoAU\nqX8xNsutnSC6ud46YB8Ec74sfP4wDAYDVR0RBAUwA4IBMTANBgkqhkiG9w0BAQsF\nAAOCAgEAcj5Ytt47AdmsXBsv/K7YkUvkNwV64luBMQtqmTKRDWnIQLaFzPjdpieu\n81ktFKklKw6pReWdUPSBy6hKq3zzGvSsShBSghbOAJvlPkK6jpLy5TzZdIj8ug7g\nMCzZvqdmznekSg4elGHJIYUfHD6ZUJaEkkGD1yQpxOIVCnodhN2246SXJK23itmz\nB5y1AHU5zydN7Ys0oY1l8RCc5Iz24IcQAi//2pIPe9ORks3QBBi+qY9m+emHCqgb\n48hNe5v7X+yF4VITlWs3Mfk0gSgbDQ4OwVf/8/D7o0hQ8EU5bzXNvf49Kd2mWTii\nQdQDdNLxZsdgWNwYdqrQhA0qN02yJxkhNm5GXmP75zmg0bPe4I+pNwuy+B32wFZn\nNcZrh4HZzS1cAyyyr3E59zsPjqcohaUcBpe6oUoQ8z1V7K9FR31TnFfvjg9mbDnX\nv2+PXsp0m7f4e1QfepZxUwyjemxOe/b+IEc7PckIrkPy46JaIvi9ONrTR8Y5wDir\nbGuzpmiyMFlyzK4ULh7kt7MU/jU/ulnqDU8JvAnhhxK3kgV4vv8LSYJSEYYP9i1S\nj/EPPQBANdtr4B2pcV1ig13dinq7rir6Q/pnkKrAFOfZcvOWW2BvPOC2dcnCYJpB\n1R5QJGXqna8Uh+ZwThs0K/Nd9dml1w/Rug8hx0VHoIe6AjXEepQ=\n-----END CERTIFICATE-----\n", 31 | "device_private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAzsm8CF8fKSzWFKZeO52RJRmhR+\nEW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXabI9manlqw0Wq\nAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+sn6j5yEUnWKSI\ngoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY4X9UpdrjS5cR\nWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9plTq7I9/fDnk\nRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABAoIBAHv3A/ogzBVrA4ut\nkKA8fV6zeZFLOzfcAUuakQujReMvLsoPruPT2VUmuU1SRpNT7csmn7azmRW+4gny\nmO5meKDR382fz2DTIuKI0kByVvtNfmtBwAEdSiBpkzD7m3m1A8hg1wHw3sebolw6\njy3Zvxn5RASe3GKKsnKVLu8n5VXgyytn2I6sYOmKoLv3N9V3tziHL3Gl2AfWAd5P\nJHJdxZ50hhjzUnI0MmvUU6M9G26xagxNNibzOWv3BEuBRw5fuVpt/QoBouFhcKF7\nEdCFpiZ8LJFpux6FyLDOOAa7mj+Y6yK1qKsJbFGG8AnhPTO/bAc1m7yQcJygH9cl\nretVDcECgYEA4z+NkjqIPRiAvOsmJD6KfMeABkZc4JmART+KtrpoJmPWc2WDxu8M\ngP1eqmh/aGGORY8hcFyl+SIf5JvP13Dd/47tSK4vhyEGnnqRt+wjjuzci0rDvFdH\ntaUbjlb4kKStssQPTTmG726Zd1f32eKzBnCY8YqWdMMM1HXak20rPo8CgYEA6PN8\nYIcIrRkFzyvam8m5pCeoHylBgSNjN2j8dGC8b6SGMG6y4+rUiuxfhC/Oq7UtOvf+\njYQQgeMjB22dhcvJa6rjuuKXXpbcgNnzcemnySohUr7Nm1bXHwRfoqMAmeh3pkcL\nL+K4Mf6Gd1i2hiYd4Dd59m5/p3W+QUyKa4iaRP0CgYAf2/UZHyOijSDfW4hJZIs9\n2ypTtuGmi160Vqg33gJj/3M9UmobJcB3BQ6UjXnvRF4R2nMxsYuDVglqn32QEr7M\n6VjS67i2FSc8aKqtQmnpy8NPs/elHAdtq+wlFIRcovnHKj2K8hm8z6CsXqTc4y9+\nI6MNmgRl8kKGNs+iA5ggeQKBgBKLN25zsWQeJtE8G3XlVArWQVLhtN4z0/UYPWiC\nPt3gSfJXDZSJIAxDDsN2DsyqaoRUM4ZOagX878/qkOySsWEJxIEfAo+8EKeNMgzy\nXbHs0aRFnhZsjklgzsAim6ykzcmFxEU2lhUcvtWHUVhSdnRf1iyg1Taeb9vA3Q/8\nWtN9AoGBAN+rik+pvcdPAexngqmsUgoW8Abvv7dyBmt99KfnyRDfbt6EM68CZI90\naOlNE9P7XZyOyfQdzOlJWv8B78dwrbwMiwkhGtMjEzdW\nKFI0T+ZOXN99GcKLHeg5GfGqHcHlEhXP9BtRyTJVz914alvOIaiY\n-----END RSA PRIVATE KEY-----\n" 32 | } 33 | } 34 | )"; 35 | 36 | // function to setup the wifi with predefined credentials 37 | void setupWifi() { 38 | // set the wifi to station mode to connect to a access point 39 | WiFi.mode(WIFI_STA); 40 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 41 | 42 | Serial.println(); 43 | Serial.print("Connecting to " + String(WIFI_SSID)); 44 | 45 | // wait till chip is being connected to wifi (Blocking Mode) 46 | while (WiFi.status() != WL_CONNECTED) { 47 | Serial.print("."); 48 | delay(250); 49 | } 50 | 51 | // now it is connected to the access point just print the ip assigned to chip 52 | Serial.println(); 53 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 54 | Serial.println(WiFi.localIP()); 55 | } 56 | 57 | // function to sync time from ntp server with predefined credentials 58 | void syncTimeFromNtp() { 59 | // sync the time from ntp server 60 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 61 | 62 | struct tm timeinfo; 63 | 64 | // get the current time 65 | if(!getLocalTime(&timeinfo)) { 66 | Serial.println("Failed to obtain time"); 67 | return; 68 | } 69 | 70 | // log the time info to serial :) 71 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 72 | Serial.println(); 73 | } 74 | 75 | // function to setup the predefined led 76 | void setupLED() { 77 | pinMode(BOARD_LED, OUTPUT); 78 | digitalWrite(BOARD_LED, ledState); 79 | } 80 | 81 | // function to toggle the predefined led 82 | void toggleLED() { 83 | ledState = !ledState; 84 | digitalWrite(BOARD_LED, ledState); 85 | } 86 | 87 | // function to get the time 88 | unsigned long long getEpochMillis() { 89 | time_t now; 90 | struct tm timeinfo; 91 | 92 | // get the current time i.e make sure the device is in sync with the ntp server 93 | if (!getLocalTime(&timeinfo)) { 94 | Serial.println("failed to obtain time"); 95 | return 0; 96 | } 97 | 98 | // get the epoch time 99 | time(&now); 100 | 101 | // generate the epoch millis 102 | unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000); 103 | 104 | return timeMillis; 105 | } 106 | 107 | // function to publish payload to device shadow 108 | bool publishToDeviceShadow() { 109 | static int sequence = 0; 110 | unsigned long long milliseconds = 0; 111 | char ledStatus[200] = ""; 112 | char deviceShadowStream[] = "device_shadow"; 113 | 114 | const char* payload = ""; 115 | String deviceShadowStr = ""; 116 | StaticJsonDocument<1024> doc; 117 | 118 | // get the current epoch millis 119 | milliseconds = getEpochMillis(); 120 | 121 | // make sure you got the millis 122 | if(milliseconds == 0) { 123 | Serial.println("failed to get epoch millis"); 124 | return false; 125 | } 126 | 127 | // increment the sequence counter 128 | sequence++; 129 | 130 | // generate the led status message string 131 | sprintf(ledStatus, "LED is %s !", ledState == true? "ON" : "OFF"); 132 | 133 | JsonArray deviceShadowJsonArray = doc.to(); 134 | JsonObject deviceShadowJsonObj_1 = deviceShadowJsonArray.createNestedObject(); 135 | 136 | deviceShadowJsonObj_1["timestamp"] = milliseconds; 137 | deviceShadowJsonObj_1["sequence"] = sequence; 138 | deviceShadowJsonObj_1["Status"] = ledStatus; 139 | 140 | serializeJson(deviceShadowJsonArray, deviceShadowStr); 141 | payload = deviceShadowStr.c_str(); 142 | 143 | Serial.printf("publishing %s to %s\n", payload, deviceShadowStream); 144 | 145 | return Bytebeam.publishToStream(deviceShadowStream, payload); 146 | } 147 | 148 | // handler for ToggleLED action 149 | int ToggleLED_Hanlder(char* args, char* actionId) { 150 | Serial.println("ToggleLED Action Received !"); 151 | Serial.printf("<--- args : %s, actionId : %s --->\n", args, actionId); 152 | 153 | // toggle the led 154 | toggleLED(); 155 | 156 | // publish led state to device shadow 157 | if(!publishToDeviceShadow()) { 158 | // publish action failed status 159 | if(!Bytebeam.publishActionFailed(actionId, "Publish led state to device shadow Failed")) { 160 | Serial.println("Failed to publish action failed response for Toggle LED action"); 161 | } 162 | 163 | Serial.println("Failed to publish led state to device shadow"); 164 | return -1; 165 | } 166 | 167 | // publish action completed status 168 | if(!Bytebeam.publishActionCompleted(actionId)) { 169 | Serial.println("Failed to publish action completed response for Toggle LED action"); 170 | return -1; 171 | } 172 | 173 | return 0; 174 | } 175 | 176 | void setup() { 177 | // put your setup code here, to run once: 178 | Serial.begin(115200); 179 | Serial.println(); 180 | 181 | setupWifi(); 182 | syncTimeFromNtp(); 183 | 184 | // setup the gpio led 185 | setupLED(); 186 | 187 | // setting up the device info i.e to be seen in the device shadow 188 | Bytebeam.status = "Device is Up!"; 189 | Bytebeam.softwareType = "hello-wokwi-ino"; 190 | Bytebeam.softwareVersion = "1.0.0"; 191 | Bytebeam.hardwareType = "ESP32 Dev Module"; 192 | Bytebeam.hardwareVersion = "rev1"; 193 | 194 | // begin the bytebeam client 195 | if(!Bytebeam.begin(deviceConfigData, BytebeamLogger::LOG_INFO)) { 196 | Serial.println("Bytebeam Client Initialization Failed."); 197 | } else { 198 | Serial.println("Bytebeam Client is Initialized Successfully."); 199 | } 200 | 201 | // add the handler for toggle led action 202 | Bytebeam.addActionHandler(ToggleLED_Hanlder, "ToggleLED"); 203 | } 204 | 205 | void loop() { 206 | // put your main code here, to run repeatedly: 207 | 208 | // bytebeam client loop 209 | Bytebeam.loop(); 210 | 211 | // hold on the execution for some time 212 | delay(5000); 213 | } -------------------------------------------------------------------------------- /examples/ESP32/HelloWokwi/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Hello Wokwi Example 2 | This example demonnstrates how to integrate Wokwi with Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/HelloWokwi/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "Wokwi-GUEST" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/HelloWokwi/diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "Benny Meisels", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { "type": "wokwi-esp32-devkit-v1", "id": "esp", "top": 4.7, "left": -5, "attrs": {} }, 7 | { 8 | "type": "wokwi-led", 9 | "id": "led-red", 10 | "top": 6, 11 | "left": 129, 12 | "attrs": { "color": "red", "flip": "1", "label": "WiFi" } 13 | }, 14 | { 15 | "type": "wokwi-resistor", 16 | "id": "r1", 17 | "top": 86.2, 18 | "left": 104.4, 19 | "rotate": 90, 20 | "attrs": { "value": "1000" } 21 | } 22 | ], 23 | "connections": [ 24 | [ "esp:TX0", "$serialMonitor:RX", "", [] ], 25 | [ "esp:RX0", "$serialMonitor:TX", "", [] ], 26 | [ "esp:GND.1", "led-red:C", "black", [ "h66.9", "v-105.7" ] ], 27 | [ "led-red:A", "r1:1", "green", [ "h-9.6", "v19.2" ] ], 28 | [ "r1:2", "esp:D2", "green", [ "h0", "v8.4" ] ] 29 | ] 30 | } -------------------------------------------------------------------------------- /examples/ESP32/HelloWokwi/wokwi.toml: -------------------------------------------------------------------------------- 1 | [wokwi] 2 | version = 1 3 | elf = "build/esp32.esp32.esp32/HelloWokwi.ino.elf" 4 | firmware = "build/esp32.esp32.esp32/HelloWokwi.ino.bin" -------------------------------------------------------------------------------- /examples/ESP32/PublishChipTemperature/PublishChipTemperature.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // temperature stream name 7 | char tempStream[] = "chip_temperature"; 8 | 9 | // wifi credentials 10 | const char* WIFI_SSID = SECRET_SSID; 11 | const char* WIFI_PASSWORD = SECRET_PASS; 12 | 13 | // sntp credentials 14 | const long gmtOffset_sec = 19800; // GMT + 5:30h 15 | const int daylightOffset_sec = 0; 16 | const char* ntpServer = "pool.ntp.org"; 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | uint8_t temprature_sens_read(); 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | 28 | // function to setup the wifi with predefined credentials 29 | void setupWifi() { 30 | // set the wifi to station mode to connect to a access point 31 | WiFi.mode(WIFI_STA); 32 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 33 | 34 | Serial.println(); 35 | Serial.print("Connecting to " + String(WIFI_SSID)); 36 | 37 | // wait till chip is being connected to wifi (Blocking Mode) 38 | while (WiFi.status() != WL_CONNECTED) { 39 | Serial.print("."); 40 | delay(250); 41 | } 42 | 43 | // now it is connected to the access point just print the ip assigned to chip 44 | Serial.println(); 45 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 46 | Serial.println(WiFi.localIP()); 47 | } 48 | 49 | // function to sync time from ntp server with predefined credentials 50 | void syncTimeFromNtp() { 51 | // sync the time from ntp server 52 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 53 | 54 | struct tm timeinfo; 55 | 56 | // get the current time 57 | if(!getLocalTime(&timeinfo)) { 58 | Serial.println("Failed to obtain time"); 59 | return; 60 | } 61 | 62 | // log the time info to serial :) 63 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 64 | Serial.println(); 65 | } 66 | 67 | // function to get the time 68 | unsigned long long getEpochMillis() { 69 | time_t now; 70 | struct tm timeinfo; 71 | 72 | // get the current time i.e make sure the device is in sync with the ntp server 73 | if (!getLocalTime(&timeinfo)) { 74 | Serial.println("failed to obtain time"); 75 | return 0; 76 | } 77 | 78 | // get the epoch time 79 | time(&now); 80 | 81 | // generate the epoch millis 82 | unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000); 83 | 84 | return timeMillis; 85 | } 86 | 87 | // function to publish chip temperature to strem 88 | bool publishChipTemperature(char* stream) { 89 | static int sequence = 0; 90 | unsigned long long milliseconds = 0; 91 | uint8_t chipTemp = 0; 92 | 93 | const char* payload = ""; 94 | String chipTemperatureStr = ""; 95 | StaticJsonDocument<1024> doc; 96 | 97 | // get the current epoch millis 98 | milliseconds = getEpochMillis(); 99 | 100 | // make sure you got the millis 101 | if(milliseconds == 0) { 102 | Serial.println("failed to get epoch millis"); 103 | return false; 104 | } 105 | 106 | // increment the sequence counter 107 | sequence++; 108 | 109 | // get the chip temperature 110 | chipTemp = (temprature_sens_read() - 32) / 1.8; 111 | 112 | JsonArray chipTemperatureJsonArray = doc.to(); 113 | JsonObject chipTemperatureJsonObj_1 = chipTemperatureJsonArray.createNestedObject(); 114 | 115 | chipTemperatureJsonObj_1["timestamp"] = milliseconds; 116 | chipTemperatureJsonObj_1["sequence"] = sequence; 117 | chipTemperatureJsonObj_1["temperature"] = chipTemp; 118 | 119 | serializeJson(chipTemperatureJsonArray, chipTemperatureStr); 120 | payload = chipTemperatureStr.c_str(); 121 | 122 | Serial.printf("publishing %s to %s\n", payload, stream); 123 | 124 | return Bytebeam.publishToStream(stream, payload); 125 | } 126 | 127 | void setup() { 128 | // put your setup code here, to run once: 129 | Serial.begin(115200); 130 | Serial.println(); 131 | 132 | setupWifi(); 133 | syncTimeFromNtp(); 134 | 135 | // setting up the device info i.e to be seen in the device shadow 136 | Bytebeam.status = "Device is Up!"; 137 | Bytebeam.softwareType = "publish-chip-temp-ino"; 138 | Bytebeam.softwareVersion = "1.0.0"; 139 | Bytebeam.hardwareType = "ESP32 Dev Module"; 140 | Bytebeam.hardwareVersion = "rev1"; 141 | 142 | // begin the bytebeam client 143 | if(!Bytebeam.begin()) { 144 | Serial.println("Bytebeam Client Initialization Failed."); 145 | } else { 146 | Serial.println("Bytebeam Client is Initialized Successfully."); 147 | } 148 | } 149 | 150 | void loop() { 151 | // put your main code here, to run repeatedly: 152 | 153 | // bytebeam client loop 154 | Bytebeam.loop(); 155 | 156 | // publish chip temperature to temperature stream 157 | if(!publishChipTemperature(tempStream)) { 158 | Serial.printf("Failed to publish chip temperature to %s", tempStream); 159 | } 160 | 161 | // hold on execution for some time 162 | delay(10000); 163 | } -------------------------------------------------------------------------------- /examples/ESP32/PublishChipTemperature/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Publish Chip Temperature Example 2 | This example will show you how to publish chip temperature to Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/PublishChipTemperature/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/PushData/PushData.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // wifi credentials 7 | const char* WIFI_SSID = SECRET_SSID; 8 | const char* WIFI_PASSWORD = SECRET_PASS; 9 | 10 | // sntp credentials 11 | const long gmtOffset_sec = 19800; // GMT + 5:30h 12 | const int daylightOffset_sec = 0; 13 | const char* ntpServer = "pool.ntp.org"; 14 | 15 | // device status 16 | char deviceStatus[200] = ""; 17 | 18 | // function to setup the wifi with predefined credentials 19 | void setupWifi() { 20 | // set the wifi to station mode to connect to a access point 21 | WiFi.mode(WIFI_STA); 22 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 23 | 24 | Serial.println(); 25 | Serial.print("Connecting to " + String(WIFI_SSID)); 26 | 27 | // wait till chip is being connected to wifi (Blocking Mode) 28 | while (WiFi.status() != WL_CONNECTED) { 29 | Serial.print("."); 30 | delay(250); 31 | } 32 | 33 | // now it is connected to the access point just print the ip assigned to chip 34 | Serial.println(); 35 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 36 | Serial.println(WiFi.localIP()); 37 | } 38 | 39 | // function to sync time from ntp server with predefined credentials 40 | void syncTimeFromNtp() { 41 | // sync the time from ntp server 42 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 43 | 44 | struct tm timeinfo; 45 | 46 | // get the current time 47 | if(!getLocalTime(&timeinfo)) { 48 | Serial.println("Failed to obtain time"); 49 | return; 50 | } 51 | 52 | // log the time info to serial :) 53 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 54 | Serial.println(); 55 | } 56 | 57 | // function to get the time 58 | unsigned long long getEpochMillis() { 59 | time_t now; 60 | struct tm timeinfo; 61 | 62 | // get the current time i.e make sure the device is in sync with the ntp server 63 | if (!getLocalTime(&timeinfo)) { 64 | Serial.println("failed to obtain time"); 65 | return 0; 66 | } 67 | 68 | // get the epoch time 69 | time(&now); 70 | 71 | // generate the epoch millis 72 | unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000); 73 | 74 | return timeMillis; 75 | } 76 | 77 | // function to publish payload to device shadow 78 | bool publishToDeviceShadow() { 79 | static int sequence = 0; 80 | unsigned long long milliseconds = 0; 81 | char deviceShadowStream[] = "device_shadow"; 82 | 83 | const char* payload = ""; 84 | String deviceShadowStr = ""; 85 | StaticJsonDocument<1024> doc; 86 | 87 | // get the current epoch millis 88 | milliseconds = getEpochMillis(); 89 | 90 | // make sure you got the millis 91 | if(milliseconds == 0) { 92 | Serial.println("failed to get epoch millis"); 93 | return false; 94 | } 95 | 96 | // increment the sequence counter 97 | sequence++; 98 | 99 | // get the connection status 100 | bool connectionStatus = Bytebeam.isConnected(); 101 | 102 | // get the device status 103 | sprintf(deviceStatus, "Device Status : %s !", connectionStatus? "Connected" : "Disconnected"); 104 | 105 | JsonArray deviceShadowJsonArray = doc.to(); 106 | JsonObject deviceShadowJsonObj_1 = deviceShadowJsonArray.createNestedObject(); 107 | 108 | deviceShadowJsonObj_1["timestamp"] = milliseconds; 109 | deviceShadowJsonObj_1["sequence"] = sequence; 110 | deviceShadowJsonObj_1["Status"] = deviceStatus; 111 | 112 | serializeJson(deviceShadowJsonArray, deviceShadowStr); 113 | payload = deviceShadowStr.c_str(); 114 | 115 | Serial.printf("publishing %s to %s\n", payload, deviceShadowStream); 116 | 117 | return Bytebeam.publishToStream(deviceShadowStream, payload); 118 | } 119 | 120 | void setup() { 121 | // put your setup code here, to run once: 122 | Serial.begin(115200); 123 | Serial.println(); 124 | 125 | setupWifi(); 126 | syncTimeFromNtp(); 127 | 128 | // setting up the device info i.e to be seen in the device shadow 129 | Bytebeam.status = "Device is Up!"; 130 | Bytebeam.softwareType = "push-data-ino"; 131 | Bytebeam.softwareVersion = "1.0.0"; 132 | Bytebeam.hardwareType = "ESP32 Dev Module"; 133 | Bytebeam.hardwareVersion = "rev1"; 134 | 135 | // begin the bytebeam client 136 | if(!Bytebeam.begin()) { 137 | Serial.println("Bytebeam Client Initialization Failed."); 138 | } else { 139 | Serial.println("Bytebeam Client is Initialized Successfully."); 140 | } 141 | } 142 | 143 | void loop() { 144 | // put your main code here, to run repeatedly: 145 | 146 | // bytebeam client loop 147 | Bytebeam.loop(); 148 | 149 | // publish device status to device shadow 150 | if(!publishToDeviceShadow()) { 151 | Serial.println("Failed to publish device status to device shadow"); 152 | return; 153 | } 154 | 155 | // hold on execution for some time 156 | delay(10000); 157 | } -------------------------------------------------------------------------------- /examples/ESP32/PushData/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Push Data Example 2 | This example will show you how to push data to Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/PushData/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/README.md: -------------------------------------------------------------------------------- 1 | ## ESP32 Examples 2 | 3 | This section includes some basic skecthes to get you started with **BytebeamArduino** on ESP32. 4 | 5 | - SetupClient 6 | - SetupClient_GSM 7 | - ActionsHandling 8 | - ToggleLED 9 | - PushData 10 | - PublishChipTemperature 11 | - EspTouch 12 | - UpdateConfig 13 | - CloudLogging 14 | - BasicOTA 15 | - BasicOTA_GSM -------------------------------------------------------------------------------- /examples/ESP32/SetupClient/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Setup Client Example 2 | This example will show you how to setup the client for Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/SetupClient/SetupClient.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // 7 | // By including the above header you got the access to the gloabl object named Bytebeam 8 | // Use Bytebeam global object to perform the required operations 9 | // 10 | 11 | // wifi credentials 12 | const char* WIFI_SSID = SECRET_SSID; 13 | const char* WIFI_PASSWORD = SECRET_PASS; 14 | 15 | // sntp credentials 16 | const long gmtOffset_sec = 19800; // GMT + 5:30h 17 | const int daylightOffset_sec = 0; 18 | const char* ntpServer = "pool.ntp.org"; 19 | 20 | // function to setup the wifi with predefined credentials 21 | void setupWifi() { 22 | // set the wifi to station mode to connect to a access point 23 | WiFi.mode(WIFI_STA); 24 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 25 | 26 | Serial.println(); 27 | Serial.print("Connecting to " + String(WIFI_SSID)); 28 | 29 | // wait till chip is being connected to wifi (Blocking Mode) 30 | while (WiFi.status() != WL_CONNECTED) { 31 | Serial.print("."); 32 | delay(250); 33 | } 34 | 35 | // now it is connected to the access point just print the ip assigned to chip 36 | Serial.println(); 37 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 38 | Serial.println(WiFi.localIP()); 39 | } 40 | 41 | // function to sync time from ntp server with predefined credentials 42 | void syncTimeFromNtp() { 43 | // sync the time from ntp server 44 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 45 | 46 | struct tm timeinfo; 47 | 48 | // get the current time 49 | if(!getLocalTime(&timeinfo)) { 50 | Serial.println("Failed to obtain time"); 51 | return; 52 | } 53 | 54 | // log the time info to serial :) 55 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 56 | Serial.println(); 57 | } 58 | 59 | void setup() { 60 | // put your setup code here, to run once: 61 | Serial.begin(115200); 62 | Serial.println(); 63 | 64 | setupWifi(); 65 | syncTimeFromNtp(); 66 | 67 | // 68 | // Your other application setup stuff goes here 69 | // 70 | 71 | // setting up the device info i.e to be seen in the device shadow 72 | Bytebeam.status = "Device is Up!"; 73 | Bytebeam.softwareType = "setup-wifi-client-ino"; 74 | Bytebeam.softwareVersion = "1.0.0"; 75 | Bytebeam.hardwareType = "ESP32 Dev Module"; 76 | Bytebeam.hardwareVersion = "rev1"; 77 | 78 | // This method will initialize and start the bytebeam client 79 | // You can over-ride the default file system, file name and library logging options, if needed 80 | // eg. Bytebeam.begin(BytebeamArduino::LITTLEFS_FILE_SYSTEM, "/my_device_config.json", BytebeamLogger::LOG_INFO) 81 | if(!Bytebeam.begin()) { 82 | Serial.println("Bytebeam Client Initialization Failed."); 83 | } else { 84 | Serial.println("Bytebeam Client is Initialized Successfully."); 85 | } 86 | 87 | // 88 | // If above call is successfull then the bytebeam client is now configured for the use 89 | // You can always check for the logs in serial monitor for the status of the above call 90 | // 91 | 92 | // check if bytebeam client is connected or disconnected 93 | bool connectionStatus = Bytebeam.isConnected(); 94 | 95 | if(!connectionStatus) { 96 | Serial.println("Bytebeam Client is Disconnected."); 97 | } else { 98 | Serial.println("Bytebeam Client is Connected."); 99 | } 100 | 101 | // Call the end method to stop and de-initialize the bytebeam client at any point of time in the code 102 | // Bytebeam.end(); 103 | } 104 | 105 | void loop() { 106 | // put your main code here, to run repeatedly: 107 | 108 | // 109 | // Your application regular stuff goes here 110 | // 111 | 112 | // This method will let you maintain the connection with the bytebeam cloud, In case 113 | // the connection is lost, it will attempt to reconnect to the bytebeam cloud 114 | Bytebeam.loop(); 115 | 116 | // software delay, you can customize it as per your application needs 117 | delay(5000); 118 | } -------------------------------------------------------------------------------- /examples/ESP32/SetupClient/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/SetupClient_GSM/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Setup GSM Client Example 2 | This example will show you how to setup the GSM client for Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. [TTGO T-SIM7600E](https://www.lilygo.cc/products/t-sim7600) 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library 9 | 2. [TinyGSM Library](https://github.com/vshymanskyy/TinyGSM) 10 | 3. [ArduinoHttpClient Library](https://github.com/arduino-libraries/ArduinoHttpClient) 11 | 4. [SSLClient Library](https://github.com/govorox/SSLClient.git) -------------------------------------------------------------------------------- /examples/ESP32/SetupClient_GSM/SetupClient_GSM.ino: -------------------------------------------------------------------------------- 1 | #define TINY_GSM_MODEM_SIM7600 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // 7 | // By including the above header you got the access to the gloabl object named Bytebeam 8 | // Use Bytebeam global object to perform the required operations 9 | // 10 | 11 | #define LED_PIN 12 12 | #define MODEM_PWRKEY 4 13 | #define MODEM_FLIGHT 25 14 | #define MODEM_TX 27 15 | #define MODEM_RX 26 16 | 17 | // set GSM PIN, if any 18 | #define GSM_PIN SECRET_PIN 19 | 20 | #define SerialMon Serial 21 | #define SerialAT Serial1 22 | 23 | // Your GPRS credentials, if any 24 | const char apn[] = SECRET_APN; 25 | const char gprsUser[] = SECRET_USER; 26 | const char gprsPass[] = SECRET_PASS; 27 | 28 | TinyGsm modem(SerialAT); 29 | 30 | // function to setup the modem with predefined credentials 31 | void setupModem() { 32 | // configure your reset, enable pins here if needed 33 | pinMode(LED_PIN, OUTPUT); 34 | pinMode(MODEM_PWRKEY, OUTPUT); 35 | pinMode(MODEM_FLIGHT, OUTPUT); 36 | 37 | // set the status led pin low to indicate the start process 38 | digitalWrite(LED_PIN, LOW); 39 | 40 | // pull up power pin (IO:4) Modulator power key, need to powered up the modem 41 | // this pin must be held high for more than 1 second according to manual requirements 42 | digitalWrite(MODEM_PWRKEY, LOW); 43 | delay(100); 44 | digitalWrite(MODEM_PWRKEY, HIGH); 45 | delay(1000); 46 | digitalWrite(MODEM_PWRKEY, LOW); 47 | 48 | // pull up the power pin (IO:25) Modulator flight mode control, need to enable modulator 49 | // this pin must be set to high 50 | digitalWrite(MODEM_FLIGHT, HIGH); 51 | 52 | SerialMon.println("Modem Powered ON"); 53 | 54 | // start the serial communication b/w esp32 and modem 55 | SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX); 56 | delay(6000); 57 | 58 | // Restart takes quite some time 59 | // To skip it, call init() instead of restart() 60 | modem.restart(); 61 | // modem.init(); 62 | 63 | // set the network mode (2 : Automatic) 64 | modem.setNetworkMode(2); 65 | 66 | String modemName = modem.getModemName(); 67 | SerialMon.printf("Modem Name : "); 68 | SerialMon.println(modemName); 69 | 70 | String modemInfo = modem.getModemInfo(); 71 | SerialMon.print("Modem Info : "); 72 | SerialMon.println(modemInfo); 73 | 74 | // Unlock your SIM card with a PIN if needed 75 | if(GSM_PIN && modem.getSimStatus() != 3) { 76 | modem.simUnlock(GSM_PIN); 77 | } 78 | 79 | SimStatus simStatus = modem.getSimStatus(); 80 | 81 | if(simStatus != SIM_READY) { 82 | SerialMon.println("Couldn't Ready the SIM."); 83 | return; 84 | } 85 | SerialMon.println("SIM is Ready."); 86 | 87 | // high indicates the modem is initialized successfully 88 | digitalWrite(LED_PIN, HIGH); 89 | SerialMon.println("Modem Initialized Successfully !"); 90 | 91 | SerialMon.println("Waiting for network..."); 92 | if(!modem.waitForNetwork()) { 93 | SerialMon.println(" fail"); 94 | delay(10000); 95 | return; 96 | } 97 | SerialMon.println(" success"); 98 | 99 | if(modem.isNetworkConnected()) { 100 | SerialMon.println("Network connected"); 101 | } 102 | 103 | // GPRS connection parameters are usually set after network registration 104 | SerialMon.print("Connecting to apn : "); 105 | SerialMon.println(apn); 106 | 107 | if (!modem.gprsConnect(apn)) { 108 | SerialMon.println(" fail"); 109 | delay(10000); 110 | return; 111 | } 112 | SerialMon.println(" success"); 113 | 114 | if(modem.isGprsConnected()) { 115 | SerialMon.println("GPRS connected"); 116 | } 117 | } 118 | 119 | // function to sync time from ntp server with predefined credentials 120 | void syncTimeFromNtp() { 121 | String dateTime = modem.getGSMDateTime(DATE_FULL); 122 | 123 | SerialMon.print("Current Time : "); 124 | SerialMon.println(dateTime); 125 | SerialMon.println(); 126 | } 127 | 128 | void setup() { 129 | // put your setup code here, to run once: 130 | SerialMon.begin(115200); 131 | SerialMon.println(); 132 | 133 | setupModem(); 134 | syncTimeFromNtp(); 135 | 136 | // 137 | // Your other application setup stuff goes here 138 | // 139 | 140 | // setting up the device info i.e to be seen in the device shadow 141 | Bytebeam.status = "Device is Up!"; 142 | Bytebeam.softwareType = "setup-gsm-client-ino"; 143 | Bytebeam.softwareVersion = "1.0.0"; 144 | Bytebeam.hardwareType = "ESP32 Dev Module"; 145 | Bytebeam.hardwareVersion = "rev1"; 146 | 147 | // This method will initialize and start the bytebeam client 148 | // You can over-ride the default file system, file name and library logging options, if needed 149 | // eg. Bytebeam.begin(BytebeamArduino::LITTLEFS_FILE_SYSTEM, "/my_device_config.json", BytebeamLogger::LOG_INFO) 150 | if(!Bytebeam.begin(&modem)) { 151 | Serial.println("Bytebeam Client Initialization Failed."); 152 | } else { 153 | Serial.println("Bytebeam Client is Initialized Successfully."); 154 | } 155 | 156 | // 157 | // If above call is successfull then the bytebeam client is now configured for the use 158 | // You can always check for the logs in serial monitor for the status of the above call 159 | // 160 | 161 | // check if bytebeam client is connected or disconnected 162 | bool connectionStatus = Bytebeam.isConnected(); 163 | 164 | if(!connectionStatus) { 165 | SerialMon.println("Bytebeam Client is Disconnected."); 166 | } else { 167 | SerialMon.println("Bytebeam Client is Connected."); 168 | } 169 | 170 | // Call the end method to stop and de-initialize the bytebeam client at any point of time in the code 171 | // Bytebeam.end(); 172 | } 173 | 174 | void loop() { 175 | // put your main code here, to run repeatedly: 176 | 177 | // 178 | // Your application regular stuff goes here 179 | // 180 | 181 | // This method will let you maintain the connection with the bytebeam cloud, In case 182 | // the connection is lost, it will attempt to reconnect to the bytebeam cloud 183 | Bytebeam.loop(); 184 | 185 | // software delay, you can customize it as per your application needs 186 | delay(5000); 187 | } -------------------------------------------------------------------------------- /examples/ESP32/SetupClient_GSM/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_PIN "" 6 | #define SECRET_APN "" 7 | #define SECRET_USER "" 8 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/ToggleLED/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Toggle LED Example 2 | This example will show you how to toggle the led with Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/ToggleLED/ToggleLED.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // on board led pin number 7 | #define BOARD_LED 2 8 | 9 | // led state variable 10 | int ledState = 0; 11 | 12 | // wifi credentials 13 | const char* WIFI_SSID = SECRET_SSID; 14 | const char* WIFI_PASSWORD = SECRET_PASS; 15 | 16 | // sntp credentials 17 | const long gmtOffset_sec = 19800; // GMT + 5:30h 18 | const int daylightOffset_sec = 0; 19 | const char* ntpServer = "pool.ntp.org"; 20 | 21 | // function to setup the wifi with predefined credentials 22 | void setupWifi() { 23 | // set the wifi to station mode to connect to a access point 24 | WiFi.mode(WIFI_STA); 25 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 26 | 27 | Serial.println(); 28 | Serial.print("Connecting to " + String(WIFI_SSID)); 29 | 30 | // wait till chip is being connected to wifi (Blocking Mode) 31 | while (WiFi.status() != WL_CONNECTED) { 32 | Serial.print("."); 33 | delay(250); 34 | } 35 | 36 | // now it is connected to the access point just print the ip assigned to chip 37 | Serial.println(); 38 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 39 | Serial.println(WiFi.localIP()); 40 | } 41 | 42 | // function to sync time from ntp server with predefined credentials 43 | void syncTimeFromNtp() { 44 | // sync the time from ntp server 45 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 46 | 47 | struct tm timeinfo; 48 | 49 | // get the current time 50 | if(!getLocalTime(&timeinfo)) { 51 | Serial.println("Failed to obtain time"); 52 | return; 53 | } 54 | 55 | // log the time info to serial :) 56 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 57 | Serial.println(); 58 | } 59 | 60 | // function to setup the predefined led 61 | void setupLED() { 62 | pinMode(BOARD_LED, OUTPUT); 63 | digitalWrite(BOARD_LED, ledState); 64 | } 65 | 66 | // function to toggle the predefined led 67 | void toggleLED() { 68 | ledState = !ledState; 69 | digitalWrite(BOARD_LED, ledState); 70 | } 71 | 72 | // function to get the time 73 | unsigned long long getEpochMillis() { 74 | time_t now; 75 | struct tm timeinfo; 76 | 77 | // get the current time i.e make sure the device is in sync with the ntp server 78 | if (!getLocalTime(&timeinfo)) { 79 | Serial.println("failed to obtain time"); 80 | return 0; 81 | } 82 | 83 | // get the epoch time 84 | time(&now); 85 | 86 | // generate the epoch millis 87 | unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000); 88 | 89 | return timeMillis; 90 | } 91 | 92 | // function to publish payload to device shadow 93 | bool publishToDeviceShadow() { 94 | static int sequence = 0; 95 | unsigned long long milliseconds = 0; 96 | char ledStatus[200] = ""; 97 | char deviceShadowStream[] = "device_shadow"; 98 | 99 | const char* payload = ""; 100 | String deviceShadowStr = ""; 101 | StaticJsonDocument<1024> doc; 102 | 103 | // get the current epoch millis 104 | milliseconds = getEpochMillis(); 105 | 106 | // make sure you got the millis 107 | if(milliseconds == 0) { 108 | Serial.println("failed to get epoch millis"); 109 | return false; 110 | } 111 | 112 | // increment the sequence counter 113 | sequence++; 114 | 115 | // generate the led status message string 116 | sprintf(ledStatus, "LED is %s !", ledState == true? "ON" : "OFF"); 117 | 118 | JsonArray deviceShadowJsonArray = doc.to(); 119 | JsonObject deviceShadowJsonObj_1 = deviceShadowJsonArray.createNestedObject(); 120 | 121 | deviceShadowJsonObj_1["timestamp"] = milliseconds; 122 | deviceShadowJsonObj_1["sequence"] = sequence; 123 | deviceShadowJsonObj_1["Status"] = ledStatus; 124 | 125 | serializeJson(deviceShadowJsonArray, deviceShadowStr); 126 | payload = deviceShadowStr.c_str(); 127 | 128 | Serial.printf("publishing %s to %s\n", payload, deviceShadowStream); 129 | 130 | return Bytebeam.publishToStream(deviceShadowStream, payload); 131 | } 132 | 133 | // handler for ToggleLED action 134 | int ToggleLED_Hanlder(char* args, char* actionId) { 135 | Serial.println("ToggleLED Action Received !"); 136 | Serial.printf("<--- args : %s, actionId : %s --->\n", args, actionId); 137 | 138 | // toggle the led 139 | toggleLED(); 140 | 141 | // publish led state to device shadow 142 | if(!publishToDeviceShadow()) { 143 | // publish action failed status 144 | if(!Bytebeam.publishActionFailed(actionId, "Publish led state to device shadow Failed")) { 145 | Serial.println("Failed to publish action failed response for Toggle LED action"); 146 | } 147 | 148 | Serial.println("Failed to publish led state to device shadow"); 149 | return -1; 150 | } 151 | 152 | // publish action completed status 153 | if(!Bytebeam.publishActionCompleted(actionId)) { 154 | Serial.println("Failed to publish action completed response for Toggle LED action"); 155 | return -1; 156 | } 157 | 158 | return 0; 159 | } 160 | 161 | void setup() { 162 | // put your setup code here, to run once: 163 | Serial.begin(115200); 164 | Serial.println(); 165 | 166 | setupWifi(); 167 | syncTimeFromNtp(); 168 | 169 | // setup the gpio led 170 | setupLED(); 171 | 172 | // setting up the device info i.e to be seen in the device shadow 173 | Bytebeam.status = "Device is Up!"; 174 | Bytebeam.softwareType = "toggle-led-ino"; 175 | Bytebeam.softwareVersion = "1.0.0"; 176 | Bytebeam.hardwareType = "ESP32 Dev Module"; 177 | Bytebeam.hardwareVersion = "rev1"; 178 | 179 | // begin the bytebeam client 180 | if(!Bytebeam.begin()) { 181 | Serial.println("Bytebeam Client Initialization Failed."); 182 | } else { 183 | Serial.println("Bytebeam Client is Initialized Successfully."); 184 | } 185 | 186 | // add the handler for toggle led action 187 | Bytebeam.addActionHandler(ToggleLED_Hanlder, "ToggleLED"); 188 | } 189 | 190 | void loop() { 191 | // put your main code here, to run repeatedly: 192 | 193 | // bytebeam client loop 194 | Bytebeam.loop(); 195 | 196 | // hold on the execution for some time 197 | delay(5000); 198 | } -------------------------------------------------------------------------------- /examples/ESP32/ToggleLED/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP32/UpdateConfig/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Update Config Example 2 | This example will show you how to update the device configuration with Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP32/UpdateConfig/UpdateConfig.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // on board led pin number 7 | #define BOARD_LED 2 8 | 9 | // duty cycle for the led 10 | int ledDutyCycle = 0; 11 | 12 | // wifi credentials 13 | const char* WIFI_SSID = SECRET_SSID; 14 | const char* WIFI_PASSWORD = SECRET_PASS; 15 | 16 | // sntp credentials 17 | const long gmtOffset_sec = 19800; // GMT + 5:30h 18 | const int daylightOffset_sec = 0; 19 | const char* ntpServer = "pool.ntp.org"; 20 | 21 | // function to setup the wifi with predefined credentials 22 | void setupWifi() { 23 | // set the wifi to station mode to connect to a access point 24 | WiFi.mode(WIFI_STA); 25 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 26 | 27 | Serial.println(); 28 | Serial.print("Connecting to " + String(WIFI_SSID)); 29 | 30 | // wait till chip is being connected to wifi (Blocking Mode) 31 | while (WiFi.status() != WL_CONNECTED) { 32 | Serial.print("."); 33 | delay(250); 34 | } 35 | 36 | // now it is connected to the access point just print the ip assigned to chip 37 | Serial.println(); 38 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 39 | Serial.println(WiFi.localIP()); 40 | } 41 | 42 | // function to sync time from ntp server with predefined credentials 43 | void syncTimeFromNtp() { 44 | // sync the time from ntp server 45 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 46 | 47 | struct tm timeinfo; 48 | 49 | // get the current time 50 | if(!getLocalTime(&timeinfo)) { 51 | Serial.println("Failed to obtain time"); 52 | return; 53 | } 54 | 55 | // log the time info to serial :) 56 | Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); 57 | Serial.println(); 58 | } 59 | 60 | // function to get the time 61 | unsigned long long getEpochMillis() { 62 | time_t now; 63 | struct tm timeinfo; 64 | 65 | // get the current time i.e make sure the device is in sync with the ntp server 66 | if (!getLocalTime(&timeinfo)) { 67 | Serial.println("failed to obtain time"); 68 | return 0; 69 | } 70 | 71 | // get the epoch time 72 | time(&now); 73 | 74 | // generate the epoch millis 75 | unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000); 76 | 77 | return timeMillis; 78 | } 79 | 80 | // function to publish payload to device shadow 81 | bool publishToDeviceShadow() { 82 | static int sequence = 0; 83 | unsigned long long milliseconds = 0; 84 | char ledStatus[200] = ""; 85 | char deviceShadowStream[] = "device_shadow"; 86 | 87 | const char* payload = ""; 88 | String deviceShadowStr = ""; 89 | StaticJsonDocument<1024> doc; 90 | 91 | // get the current epoch millis 92 | milliseconds = getEpochMillis(); 93 | 94 | // make sure you got the millis 95 | if(milliseconds == 0) { 96 | Serial.println("failed to get epoch millis"); 97 | return false; 98 | } 99 | 100 | // increment the sequence counter 101 | sequence++; 102 | 103 | // generate the led status message string 104 | float brightness = (ledDutyCycle/255.0) * 100; 105 | sprintf(ledStatus, "LED Brighntness is %.2f%% !", brightness); 106 | 107 | JsonArray deviceShadowJsonArray = doc.to(); 108 | JsonObject deviceShadowJsonObj_1 = deviceShadowJsonArray.createNestedObject(); 109 | 110 | deviceShadowJsonObj_1["timestamp"] = milliseconds; 111 | deviceShadowJsonObj_1["sequence"] = sequence; 112 | deviceShadowJsonObj_1["Status"] = ledStatus; 113 | 114 | serializeJson(deviceShadowJsonArray, deviceShadowStr); 115 | payload = deviceShadowStr.c_str(); 116 | 117 | Serial.printf("publishing %s to %s\n", payload, deviceShadowStream); 118 | 119 | return Bytebeam.publishToStream(deviceShadowStream, payload); 120 | } 121 | 122 | // handler for update_config action 123 | int UpdateConfig_Hanlder(char* args, char* actionId) { 124 | Serial.println("UpdateConfig Action Received !"); 125 | Serial.printf("<--- args : %s, actionId : %s --->\n", args, actionId); 126 | 127 | StaticJsonDocument<1024> doc; 128 | DeserializationError err = deserializeJson(doc, args); 129 | 130 | if(err) { 131 | Serial.printf("deserializeJson() failed : %s\n", err.c_str()); 132 | 133 | // publish action failed status 134 | if(!Bytebeam.publishActionFailed(actionId, "Json Deserialization Failed")) { 135 | Serial.println("Failed to publish action failed response for Update Config action"); 136 | } 137 | 138 | return -1; 139 | } 140 | 141 | const char* name = doc["name"]; 142 | 143 | if(name == NULL) { 144 | Serial.println("Error parsing update config name"); 145 | 146 | // publish action failed status 147 | if(!Bytebeam.publishActionFailed(actionId, "Error parsing update config name")) { 148 | Serial.println("Failed to publish action failed response for Update Config action"); 149 | } 150 | 151 | return -1; 152 | } 153 | 154 | const char* version = doc["version"]; 155 | 156 | if(version == NULL) { 157 | Serial.println("Error parsing update config version"); 158 | 159 | // publish action failed status 160 | if(!Bytebeam.publishActionFailed(actionId, "Error parsing update config version")) { 161 | Serial.println("Failed to publish action failed response for Update Config action"); 162 | } 163 | 164 | return -1; 165 | } 166 | 167 | if(doc.containsKey("step_value")) { 168 | // get the led duty cycle 169 | ledDutyCycle = doc["step_value"]; 170 | } else { 171 | Serial.println("Error parsing update config step value"); 172 | 173 | // publish action failed status 174 | if(!Bytebeam.publishActionFailed(actionId, "Error parsing update config step value")) { 175 | Serial.println("Failed to publish action failed response for Update Config action"); 176 | } 177 | 178 | return -1; 179 | } 180 | 181 | // generate the pwm signal 182 | analogWrite(BOARD_LED, ledDutyCycle); 183 | 184 | // publish led brightness to device shadow 185 | if(!publishToDeviceShadow()) { 186 | // publish action failed status 187 | if(!Bytebeam.publishActionFailed(actionId, "Publish led brightness to device shadow Failed")) { 188 | Serial.println("Failed to publish action failed response for Update Config action"); 189 | } 190 | 191 | Serial.println("Failed to publish led brightness to device shadow"); 192 | return -1; 193 | } 194 | 195 | // publish action completed status 196 | if(!Bytebeam.publishActionCompleted(actionId)) { 197 | Serial.println("Failed to publish action completed response for Update Config action"); 198 | return -1; 199 | } 200 | 201 | return 0; 202 | } 203 | 204 | void setup() { 205 | // put your setup code here, to run once: 206 | Serial.begin(115200); 207 | Serial.println(); 208 | 209 | setupWifi(); 210 | syncTimeFromNtp(); 211 | 212 | // setting up the device info i.e to be seen in the device shadow 213 | Bytebeam.status = "Device is Up!"; 214 | Bytebeam.softwareType = "update-config-ino"; 215 | Bytebeam.softwareVersion = "1.0.0"; 216 | Bytebeam.hardwareType = "ESP32 Dev Module"; 217 | Bytebeam.hardwareVersion = "rev1"; 218 | 219 | // begin the bytebeam client 220 | if(!Bytebeam.begin()) { 221 | Serial.println("Bytebeam Client Initialization Failed."); 222 | } else { 223 | Serial.println("Bytebeam Client is Initialized Successfully."); 224 | } 225 | 226 | // add the handler for update config action 227 | Bytebeam.addActionHandler(UpdateConfig_Hanlder, "update_config"); 228 | } 229 | 230 | void loop() { 231 | // put your main code here, to run repeatedly: 232 | 233 | // bytebeam client loop 234 | Bytebeam.loop(); 235 | 236 | // hold on the execution for some time 237 | delay(5000); 238 | } -------------------------------------------------------------------------------- /examples/ESP32/UpdateConfig/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/ESP8266/README.md: -------------------------------------------------------------------------------- 1 | ## ESP8266 Examples 2 | 3 | This section includes the sample sketch showing how you can quickly start off with **BytebeamArduino** on ESP8266. 4 | 5 | - ToggleLED 6 | 7 | You can notice the change lies before the bytebeam begin part in setting up WiFi and SNTP. As long as the library supports the required functionality in ESP8266, you can still work on ESP32 samples by doing these minor modifications. -------------------------------------------------------------------------------- /examples/ESP8266/ToggleLED/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam Toggle LED Example 2 | This example will show you how to toggle the led with Bytebeam IoT Platform. 3 | 4 | ## Hardware specification 5 | 1. ESP8266 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/ESP8266/ToggleLED/ToggleLED.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "arduino_secrets.h" 5 | 6 | // on board led pin number 7 | #define BOARD_LED 2 8 | 9 | // led state variable 10 | int ledState = 0; 11 | 12 | // wifi credentials 13 | const char* WIFI_SSID = SECRET_SSID; 14 | const char* WIFI_PASSWORD = SECRET_SSID; 15 | 16 | // sntp credentials 17 | const long gmtOffset_sec = 19800; // GMT + 5:30h 18 | const int daylightOffset_sec = 0; 19 | const char* ntpServer = "pool.ntp.org"; 20 | 21 | // function to setup the wifi with predefined credentials 22 | void setupWifi() { 23 | // set the wifi to station mode to connect to a access point 24 | WiFi.mode(WIFI_STA); 25 | WiFi.begin(WIFI_SSID , WIFI_PASSWORD); 26 | 27 | Serial.println(); 28 | Serial.print("Connecting to " + String(WIFI_SSID)); 29 | 30 | // wait till chip is being connected to wifi (Blocking Mode) 31 | while (WiFi.status() != WL_CONNECTED) { 32 | Serial.print("."); 33 | delay(250); 34 | } 35 | 36 | // now it is connected to the access point just print the ip assigned to chip 37 | Serial.println(); 38 | Serial.print("Connected to " + String(WIFI_SSID) + ", Got IP address : "); 39 | Serial.println(WiFi.localIP()); 40 | } 41 | 42 | // function to sync time from ntp server with predefined credentials 43 | void syncTimeFromNtp() { 44 | // sync the time from ntp server 45 | configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); 46 | 47 | struct tm timeinfo; 48 | 49 | // get the current time 50 | if(!getLocalTime(&timeinfo)) { 51 | Serial.println("Failed to obtain time"); 52 | return; 53 | } 54 | 55 | // log the time info to serial :) 56 | Serial.print("Current time: "); 57 | Serial.println(asctime(&timeinfo)); 58 | } 59 | 60 | // function to setup the predefined led 61 | void setupLED() { 62 | pinMode(BOARD_LED, OUTPUT); 63 | digitalWrite(BOARD_LED, ledState); 64 | } 65 | 66 | // function to toggle the predefined led 67 | void toggleLED() { 68 | ledState = !ledState; 69 | digitalWrite(BOARD_LED, ledState); 70 | } 71 | 72 | // function to get the time 73 | unsigned long long getEpochMillis() { 74 | time_t now; 75 | struct tm timeinfo; 76 | 77 | // get the current time i.e make sure the device is in sync with the ntp server 78 | if (!getLocalTime(&timeinfo)) { 79 | Serial.println("failed to obtain time"); 80 | return 0; 81 | } 82 | 83 | // get the epoch time 84 | time(&now); 85 | 86 | // generate the epoch millis 87 | unsigned long long timeMillis = ((unsigned long long)now * 1000) + (millis() % 1000); 88 | 89 | return timeMillis; 90 | } 91 | 92 | // function to publish payload to device shadow 93 | bool publishToDeviceShadow() { 94 | static int sequence = 0; 95 | unsigned long long milliseconds = 0; 96 | char ledStatus[200] = ""; 97 | char deviceShadowStream[] = "device_shadow"; 98 | 99 | const char* payload = ""; 100 | String deviceShadowStr = ""; 101 | StaticJsonDocument<1024> doc; 102 | 103 | // get the current epoch millis 104 | milliseconds = getEpochMillis(); 105 | 106 | // make sure you got the millis 107 | if(milliseconds == 0) { 108 | Serial.println("failed to get epoch millis"); 109 | return false; 110 | } 111 | 112 | // increment the sequence counter 113 | sequence++; 114 | 115 | // generate the led status message string 116 | sprintf(ledStatus, "LED is %s !", ledState == true? "ON" : "OFF"); 117 | 118 | JsonArray deviceShadowJsonArray = doc.to(); 119 | JsonObject deviceShadowJsonObj_1 = deviceShadowJsonArray.createNestedObject(); 120 | 121 | deviceShadowJsonObj_1["timestamp"] = milliseconds; 122 | deviceShadowJsonObj_1["sequence"] = sequence; 123 | deviceShadowJsonObj_1["Status"] = ledStatus; 124 | 125 | serializeJson(deviceShadowJsonArray, deviceShadowStr); 126 | payload = deviceShadowStr.c_str(); 127 | 128 | Serial.printf("publishing %s to %s\n", payload, deviceShadowStream); 129 | 130 | return Bytebeam.publishToStream(deviceShadowStream, payload); 131 | } 132 | 133 | // handler for ToggleLED action 134 | int ToggleLED_Hanlder(char* args, char* actionId) { 135 | Serial.println("ToggleLED Action Received !"); 136 | Serial.printf("<--- args : %s, actionId : %s --->\n", args, actionId); 137 | 138 | // toggle the led 139 | toggleLED(); 140 | 141 | // publish led state to device shadow 142 | if(!publishToDeviceShadow()) { 143 | // publish action failed status 144 | if(!Bytebeam.publishActionFailed(actionId, "Publish led state to device shadow Failed")) { 145 | Serial.println("Failed to publish action failed response for Toggle LED action"); 146 | } 147 | 148 | Serial.println("Failed to publish led state to device shadow"); 149 | return -1; 150 | } 151 | 152 | // publish action completed status 153 | if(!Bytebeam.publishActionCompleted(actionId)) { 154 | Serial.println("Failed to publish action completed response for Toggle LED action"); 155 | return -1; 156 | } 157 | 158 | return 0; 159 | } 160 | 161 | void setup() { 162 | // put your setup code here, to run once: 163 | Serial.begin(115200); 164 | Serial.println(); 165 | 166 | setupWifi(); 167 | syncTimeFromNtp(); 168 | 169 | // setup the gpio led 170 | setupLED(); 171 | 172 | // setting up the device info i.e to be seen in the device shadow 173 | Bytebeam.status = "Device is Up!"; 174 | Bytebeam.softwareType = "toggle-led-ino"; 175 | Bytebeam.softwareVersion = "1.0.0"; 176 | Bytebeam.hardwareType = "NodeMCU 1.0 (ESP-12E Module)"; 177 | Bytebeam.hardwareVersion = "rev1"; 178 | 179 | // begin the bytebeam client 180 | if(!Bytebeam.begin()) { 181 | Serial.println("Bytebeam Client Initialization Failed."); 182 | } else { 183 | Serial.println("Bytebeam Client is Initialized Successfully."); 184 | } 185 | 186 | // add the handler for toggle led action 187 | Bytebeam.addActionHandler(ToggleLED_Hanlder, "ToggleLED"); 188 | } 189 | 190 | void loop() { 191 | // put your main code here, to run repeatedly: 192 | 193 | // bytebeam client loop 194 | Bytebeam.loop(); 195 | 196 | // hold on the execution for some time 197 | delay(5000); 198 | } -------------------------------------------------------------------------------- /examples/ESP8266/ToggleLED/arduino_secrets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Place all the sensitive data here 3 | // 4 | 5 | #define SECRET_SSID "" 6 | #define SECRET_PASS "" -------------------------------------------------------------------------------- /examples/Provisioning/FATFSProvisioning/FATFSProvisioning.ino: -------------------------------------------------------------------------------- 1 | #include "FS.h" 2 | #include "FFat.h" 3 | 4 | /* This macro is used to specify the base path of the fatfs partiiton */ 5 | #define FATFS_BASE_PATH "/ffat" 6 | 7 | /* This macro is used to format the fatfs if in case the fatfs initialization fails i.e reset if not required */ 8 | #define FORMAT_FATFS_IF_FAILED true 9 | 10 | /* This macro is used to format the fatfs in the beginnig i.e reset if not required */ 11 | #define FORMAT_FATFS_IN_BEGINNING true 12 | 13 | /* This macro is used to specify the name of the device config file */ 14 | #define DEVICE_CONFIG_FILE_NAME "/device_config.json" 15 | 16 | /* This macro is used to specify the maximum size of device config json in bytes that need to be handled for particular device */ 17 | #define DEVICE_CONFIG_STR_LENGTH 8192 18 | 19 | /* This macro is used to print the device config read/write buffers to serial monitor i.e set to debug any issue */ 20 | #define PRINT_BUFFERS_TO_SERIAL false 21 | 22 | char deviceConfigReadStr[DEVICE_CONFIG_STR_LENGTH] = ""; 23 | 24 | // Replace this with your device config json in the same format 25 | char deviceConfigWriteStr[DEVICE_CONFIG_STR_LENGTH] = R"( 26 | { 27 | "project_id": "demo", 28 | "broker": "cloud.bytebeam.io", 29 | "port": 8883, 30 | "device_id": "1", 31 | "authentication": { 32 | "ca_certificate": "-----BEGIN CERTIFICATE-----\nMIIFrDCCA5SgAwIBAgICBMwDQYJAwdzEOMAwGA1UBhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYcmUxFzAVBgNV\nBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIxMDkwMjExMDYyM1oXDTMxMDkwMjExMDYyM1owdzEOMAwG\nA1UEBhMFSW5kaWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCYW5nYWxv\ncmUxFzAVBgNVBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDAS\nBgNVBAoTC0J5dGViZWFtLmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC\nAgEAr/bnOa/8AUGZmd/s+7rejuROgeLqqU9X15KKfKOBqcoMyXsSO65UEwpzadpw\nMl7GDCdHqFTymqdnAnbhgaT1PoIFhOG64y7UiNgiWmbh0XJj8G6oLrW9rQ1gug1Q\n/D7x2fUnza71aixiwEL+KsIFYIdDuzmoRD3rSer/bKOcGGs0WfB54KqIVVZ1DwsU\nk1wx5ExsKo7gAdXMAbdHRI2Szmn5MsZwGL6V0LfsKLE8ms2qlZe50oo2woLNN6XP\nRfRL4bwwkdsCqXWkkt4eUSNDq9hJsuINHdhO3GUieLsKLJGWJ0lq6si74t75rIKb\nvvsFEQ9mnAVS+iuUUsSjHPJIMnn/J64Nmgl/R/8FP5TUgUrHvHXKQkJ9h/a7+3tS\nlV2KMsFksXaFrGEByGIJ7yR4qu9hx5MXf8pf8EGEwOW/H3CdWcC2MvJ11PVpceUJ\neDVwE7B4gPM9Kx02RNwvUMH2FmYqkXX2DrrHQGQuq+6VRoN3rEdmGPqnONJEPeOw\nZzcGDVXKWZtd7UCbcZKdn0RYmVtI/OB5OW8IRoXFYgGB3IWP796dsXIwbJSqRb9m\nylICGOceQy3VR+8+BHkQLj5/ZKTe+AA3Ktk9UADvxRiWKGcejSA/LvyT8qzz0dqn\nGtcHYJuhJ/XpkHtB0PykB5WtxFjx3G/osbZfrNflcQZ9h1MCAwEAAaNCMEAwDgYD\nVR0PAQH/BAQDAgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKl/MTbLrZ0g\nurneOmAfBHO+LHz+MA0GCSqGSIb3DQEBCwUAA4ICAQAlus/uKic5sgo1d2hBJ0Ak\ns1XJsA2jz+OEdshQHmCCmzFir3IRSuVRmDBaBGlJDHCELqYxKn6dl/sKGwoqoAQ5\nOeR2sey3Nmdyw2k2JTDx58HnApZKAVir7BDxbIbbHmfhJk4ljeUBbertNXWbRHVr\ncs4XBNwXvX+noZjQzmXXK89YBsV2DCrGRAUeZ4hQEqV7XC0VKmlzEmfkr1nibDr5\nqwbI+7QWIAnkHggYi27lL2UTH7TvkwYC4TyDaoQ2ZRpG\nHY+mxXLdftoMv/ZvmyjOPYeTRQbfPqoRqcM6XOPXwSw9B6YddwmnkI7ohNOvAVfD\nwGptUc5OodgFQc3waRljX1q2lawZCTh58IUf32CRtOEL2RIz4VpUrNF/0E2vts1f\npO7V1vY2Qin998Nwqkxdsll0GLtEEE9hUyvk1F8U+fgjJ3Rjn4BxnCN4oCrdJOMa\nJCaysaHV7EEIMqrYP4jH6RzQzOXLd0m9NaL8A/Y9z2a96fwpZZU/fEEOH71t3Eo3\nV/CKlysiALMtsHfZDwHNpa6g0NQNGN5IRl/w1TS1izzjzgWhR6r8wX8OPLRzhNRz\n2HDbTXGYsem0ihC0B8uzujOhTHcBwsfxZUMpGjg8iycJlfpPDWBdw8qrGu8LeNux\na0cIevjvYAtVysoXInV0kg==\n-----END CERTIFICATE-----\n", 33 | "device_certificate": "-----BEGIN CERTIFICATE-----\nMIIEcjCCAlqgAwIBAgICB+MwhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIyMTEwMzA3NDcwMloXDTMyMTEKTEbMBkG\nA1UEChMSZXNwYnl0ZWJlYW1zZGt0ZXN0MQowCAYDVQQDEwExMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsm8CF8fKSzWFKZeO52RJRGER4z7sYrgTb9x\noIeljE8kmhR+EW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXa\nbI9manlqw0WqAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+s\nn6j5yEUnWKSIgoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY\n4X9UpdrjS5cRWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9\nplTq7I9/fDnkRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABo1YwVDAO\nBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0jBBgwFoAU\nqX8xNsutnSC6ud46YB8Ec74sfP4wDAYDVR0RBAUwA4IBMTANBgkqhkiG9w0BAQsF\nAAOCAgEAcj5Ytt47AdmsXBsv/K7YkUvkNwV64luBMQtqmTKRDWnIQLaFzPjdpieu\n81ktFKklKw6pReWdUPSBy6hKq3zzGvSsShBSghbOAJvlPkK6jpLy5TzZdIj8ug7g\nMCzZvqdmznekSg4elGHJIYUfHD6ZUJaEkkGD1yQpxOIVCnodhN2246SXJK23itmz\nB5y1AHU5zydN7Ys0oY1l8RCc5Iz24IcQAi//2pIPe9ORks3QBBi+qY9m+emHCqgb\n48hNe5v7X+yF4VITlWs3Mfk0gSgbDQ4OwVf/8/D7o0hQ8EU5bzXNvf49Kd2mWTii\nQdQDdNLxZsdgWNwYdqrQhA0qN02yJxkhNm5GXmP75zmg0bPe4I+pNwuy+B32wFZn\nNcZrh4HZzS1cAyyyr3E59zsPjqcohaUcBpe6oUoQ8z1V7K9FR31TnFfvjg9mbDnX\nv2+PXsp0m7f4e1QfepZxUwyjemxOe/b+IEc7PckIrkPy46JaIvi9ONrTR8Y5wDir\nbGuzpmiyMFlyzK4ULh7kt7MU/jU/ulnqDU8JvAnhhxK3kgV4vv8LSYJSEYYP9i1S\nj/EPPQBANdtr4B2pcV1ig13dinq7rir6Q/pnkKrAFOfZcvOWW2BvPOC2dcnCYJpB\n1R5QJGXqna8Uh+ZwThs0K/Nd9dml1w/Rug8hx0VHoIe6AjXEepQ=\n-----END CERTIFICATE-----\n", 34 | "device_private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAzsm8CF8fKSzWFKZeO52RJRmhR+\nEW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXabI9manlqw0Wq\nAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+sn6j5yEUnWKSI\ngoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY4X9UpdrjS5cR\nWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9plTq7I9/fDnk\nRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABAoIBAHv3A/ogzBVrA4ut\nkKA8fV6zeZFLOzfcAUuakQujReMvLsoPruPT2VUmuU1SRpNT7csmn7azmRW+4gny\nmO5meKDR382fz2DTIuKI0kByVvtNfmtBwAEdSiBpkzD7m3m1A8hg1wHw3sebolw6\njy3Zvxn5RASe3GKKsnKVLu8n5VXgyytn2I6sYOmKoLv3N9V3tziHL3Gl2AfWAd5P\nJHJdxZ50hhjzUnI0MmvUU6M9G26xagxNNibzOWv3BEuBRw5fuVpt/QoBouFhcKF7\nEdCFpiZ8LJFpux6FyLDOOAa7mj+Y6yK1qKsJbFGG8AnhPTO/bAc1m7yQcJygH9cl\nretVDcECgYEA4z+NkjqIPRiAvOsmJD6KfMeABkZc4JmART+KtrpoJmPWc2WDxu8M\ngP1eqmh/aGGORY8hcFyl+SIf5JvP13Dd/47tSK4vhyEGnnqRt+wjjuzci0rDvFdH\ntaUbjlb4kKStssQPTTmG726Zd1f32eKzBnCY8YqWdMMM1HXak20rPo8CgYEA6PN8\nYIcIrRkFzyvam8m5pCeoHylBgSNjN2j8dGC8b6SGMG6y4+rUiuxfhC/Oq7UtOvf+\njYQQgeMjB22dhcvJa6rjuuKXXpbcgNnzcemnySohUr7Nm1bXHwRfoqMAmeh3pkcL\nL+K4Mf6Gd1i2hiYd4Dd59m5/p3W+QUyKa4iaRP0CgYAf2/UZHyOijSDfW4hJZIs9\n2ypTtuGmi160Vqg33gJj/3M9UmobJcB3BQ6UjXnvRF4R2nMxsYuDVglqn32QEr7M\n6VjS67i2FSc8aKqtQmnpy8NPs/elHAdtq+wlFIRcovnHKj2K8hm8z6CsXqTc4y9+\nI6MNmgRl8kKGNs+iA5ggeQKBgBKLN25zsWQeJtE8G3XlVArWQVLhtN4z0/UYPWiC\nPt3gSfJXDZSJIAxDDsN2DsyqaoRUM4ZOagX878/qkOySsWEJxIEfAo+8EKeNMgzy\nXbHs0aRFnhZsjklgzsAim6ykzcmFxEU2lhUcvtWHUVhSdnRf1iyg1Taeb9vA3Q/8\nWtN9AoGBAN+rik+pvcdPAexngqmsUgoW8Abvv7dyBmt99KfnyRDfbt6EM68CZI90\naOlNE9P7XZyOyfQdzOlJWv8B78dwrbwMiwkhGtMjEzdW\nKFI0T+ZOXN99GcKLHeg5GfGqHcHlEhXP9BtRyTJVz914alvOIaiY\n-----END RSA PRIVATE KEY-----\n" 35 | } 36 | } 37 | )"; 38 | 39 | void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { 40 | Serial.printf("Listing directory : %s\r\n", dirname); 41 | 42 | File root = fs.open(dirname); 43 | if (!root) { 44 | Serial.println("- failed to open directory"); 45 | return; 46 | } 47 | if (!root.isDirectory()) { 48 | Serial.println(" - not a directory"); 49 | return; 50 | } 51 | 52 | File file = root.openNextFile(); 53 | while (file) { 54 | if (file.isDirectory()) { 55 | Serial.print(" - DIR : "); 56 | Serial.println(file.name()); 57 | if (levels) { 58 | listDir(fs, file.name(), levels - 1); 59 | } 60 | } else { 61 | Serial.print(" - FILE: "); 62 | Serial.print(file.name()); 63 | Serial.print("\tSIZE: "); 64 | Serial.println(file.size()); 65 | } 66 | file = root.openNextFile(); 67 | } 68 | } 69 | 70 | void readFile(fs::FS &fs, const char *path, char *message) { 71 | Serial.printf("Reading file : %s\r\n", path); 72 | 73 | File file = fs.open(path, FILE_READ); 74 | if (!file || file.isDirectory()) { 75 | Serial.println("- failed to open file for reading"); 76 | return; 77 | } 78 | 79 | char chr = ' '; 80 | int strIndex = 0; 81 | 82 | Serial.println("- read from file"); 83 | while (file.available()) { 84 | chr = file.read(); 85 | message[strIndex++] = chr; 86 | } 87 | file.close(); 88 | } 89 | 90 | void writeFile(fs::FS &fs, const char *path, const char *message) { 91 | Serial.printf("Writing file : %s\r\n", path); 92 | 93 | File file = fs.open(path, FILE_WRITE); 94 | if (!file) { 95 | Serial.println("- failed to open file for writing"); 96 | return; 97 | } 98 | if (file.print(message)) { 99 | Serial.println("- file written"); 100 | } else { 101 | Serial.println("- write failed"); 102 | } 103 | file.close(); 104 | } 105 | 106 | void setup() { 107 | // put your setup code here, to run once: 108 | Serial.begin(115200); 109 | Serial.println(); 110 | 111 | #if FORMAT_FATFS_IN_BEGINNING 112 | if (!FFat.format()) { 113 | Serial.println("fatfs format failed"); 114 | return; 115 | } else { 116 | Serial.println("fatfs format success"); 117 | } 118 | #endif 119 | 120 | // initalize the fatfs file system 121 | if (!FFat.begin(FORMAT_FATFS_IF_FAILED, FATFS_BASE_PATH)) { 122 | Serial.println("fatfs mount failed"); 123 | return; 124 | } else { 125 | Serial.println("fatfs mount success"); 126 | } 127 | 128 | listDir(FFat, "/", 0); // list the directories in the fatfs 129 | writeFile(FFat, DEVICE_CONFIG_FILE_NAME, deviceConfigWriteStr); // write the device configuration string to fatfs 130 | readFile(FFat, DEVICE_CONFIG_FILE_NAME, deviceConfigReadStr); // read the device configuration string from fatfs 131 | 132 | // de-initalize the fatfs file system 133 | FFat.end(); 134 | 135 | #if PRINT_BUFFERS_TO_SERIAL 136 | Serial.println(); 137 | Serial.println("deviceConfigWriteStr : "); 138 | Serial.println(deviceConfigWriteStr); 139 | Serial.println("deviceConfigReadStr : "); 140 | Serial.println(deviceConfigReadStr); 141 | #endif 142 | 143 | // verify the write process and log the result 144 | if (!memcmp(deviceConfigReadStr, deviceConfigWriteStr, DEVICE_CONFIG_STR_LENGTH)) { 145 | Serial.println("device provisioning success !"); 146 | } else { 147 | Serial.println("device provisioning failed !"); 148 | } 149 | } 150 | 151 | void loop() { 152 | // put your main code here, to run repeatedly: 153 | 154 | // nothing to do here 155 | } -------------------------------------------------------------------------------- /examples/Provisioning/FATFSProvisioning/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam FATFS Provisioning Example 2 | This example will show you how to provison your device with FATFS file system. 3 | 4 | ## Hardware specification 5 | 1. ESP32 Dev Board 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/Provisioning/LITTLEFSProvisioning/LITTLEFSProvisioning.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* This macro is used to specify the base path of the littlefs partiiton */ 4 | #define LITTLEFS_BASE_PATH "/littlefs" 5 | 6 | /* This macro is used to format the littlefs if in case the littlefs initialization fails i.e reset if not required */ 7 | #define FORMAT_LITTLEFS_IF_FAILED true 8 | 9 | /* This macro is used to format the littlefs in the beginnig i.e reset if not required */ 10 | #define FORMAT_LITTLEFS_IN_BEGINNING true 11 | 12 | /* This macro is used to specify the name of the device config file */ 13 | #define DEVICE_CONFIG_FILE_NAME "/device_config.json" 14 | 15 | /* This macro is used to specify the maximum size of device config json in bytes that need to be handled for particular device */ 16 | #define DEVICE_CONFIG_STR_LENGTH 8192 17 | 18 | /* This macro is used to print the device config read/write buffers to serial monitor i.e set to debug any issue */ 19 | #define PRINT_BUFFERS_TO_SERIAL false 20 | 21 | char deviceConfigReadStr[DEVICE_CONFIG_STR_LENGTH] = ""; 22 | 23 | // Replace this with your device config json in the same format 24 | char deviceConfigWriteStr[DEVICE_CONFIG_STR_LENGTH] = R"( 25 | { 26 | "project_id": "demo", 27 | "broker": "cloud.bytebeam.io", 28 | "port": 8883, 29 | "device_id": "1", 30 | "authentication": { 31 | "ca_certificate": "-----BEGIN CERTIFICATE-----\nMIIFrDCCA5SgAwIBAgICBMwDQYJAwdzEOMAwGA1UBhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYcmUxFzAVBgNV\nBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIxMDkwMjExMDYyM1oXDTMxMDkwMjExMDYyM1owdzEOMAwG\nA1UEBhMFSW5kaWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCYW5nYWxv\ncmUxFzAVBgNVBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDAS\nBgNVBAoTC0J5dGViZWFtLmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC\nAgEAr/bnOa/8AUGZmd/s+7rejuROgeLqqU9X15KKfKOBqcoMyXsSO65UEwpzadpw\nMl7GDCdHqFTymqdnAnbhgaT1PoIFhOG64y7UiNgiWmbh0XJj8G6oLrW9rQ1gug1Q\n/D7x2fUnza71aixiwEL+KsIFYIdDuzmoRD3rSer/bKOcGGs0WfB54KqIVVZ1DwsU\nk1wx5ExsKo7gAdXMAbdHRI2Szmn5MsZwGL6V0LfsKLE8ms2qlZe50oo2woLNN6XP\nRfRL4bwwkdsCqXWkkt4eUSNDq9hJsuINHdhO3GUieLsKLJGWJ0lq6si74t75rIKb\nvvsFEQ9mnAVS+iuUUsSjHPJIMnn/J64Nmgl/R/8FP5TUgUrHvHXKQkJ9h/a7+3tS\nlV2KMsFksXaFrGEByGIJ7yR4qu9hx5MXf8pf8EGEwOW/H3CdWcC2MvJ11PVpceUJ\neDVwE7B4gPM9Kx02RNwvUMH2FmYqkXX2DrrHQGQuq+6VRoN3rEdmGPqnONJEPeOw\nZzcGDVXKWZtd7UCbcZKdn0RYmVtI/OB5OW8IRoXFYgGB3IWP796dsXIwbJSqRb9m\nylICGOceQy3VR+8+BHkQLj5/ZKTe+AA3Ktk9UADvxRiWKGcejSA/LvyT8qzz0dqn\nGtcHYJuhJ/XpkHtB0PykB5WtxFjx3G/osbZfrNflcQZ9h1MCAwEAAaNCMEAwDgYD\nVR0PAQH/BAQDAgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKl/MTbLrZ0g\nurneOmAfBHO+LHz+MA0GCSqGSIb3DQEBCwUAA4ICAQAlus/uKic5sgo1d2hBJ0Ak\ns1XJsA2jz+OEdshQHmCCmzFir3IRSuVRmDBaBGlJDHCELqYxKn6dl/sKGwoqoAQ5\nOeR2sey3Nmdyw2k2JTDx58HnApZKAVir7BDxbIbbHmfhJk4ljeUBbertNXWbRHVr\ncs4XBNwXvX+noZjQzmXXK89YBsV2DCrGRAUeZ4hQEqV7XC0VKmlzEmfkr1nibDr5\nqwbI+7QWIAnkHggYi27lL2UTH7TvkwYC4TyDaoQ2ZRpG\nHY+mxXLdftoMv/ZvmyjOPYeTRQbfPqoRqcM6XOPXwSw9B6YddwmnkI7ohNOvAVfD\nwGptUc5OodgFQc3waRljX1q2lawZCTh58IUf32CRtOEL2RIz4VpUrNF/0E2vts1f\npO7V1vY2Qin998Nwqkxdsll0GLtEEE9hUyvk1F8U+fgjJ3Rjn4BxnCN4oCrdJOMa\nJCaysaHV7EEIMqrYP4jH6RzQzOXLd0m9NaL8A/Y9z2a96fwpZZU/fEEOH71t3Eo3\nV/CKlysiALMtsHfZDwHNpa6g0NQNGN5IRl/w1TS1izzjzgWhR6r8wX8OPLRzhNRz\n2HDbTXGYsem0ihC0B8uzujOhTHcBwsfxZUMpGjg8iycJlfpPDWBdw8qrGu8LeNux\na0cIevjvYAtVysoXInV0kg==\n-----END CERTIFICATE-----\n", 32 | "device_certificate": "-----BEGIN CERTIFICATE-----\nMIIEcjCCAlqgAwIBAgICB+MwhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIyMTEwMzA3NDcwMloXDTMyMTEKTEbMBkG\nA1UEChMSZXNwYnl0ZWJlYW1zZGt0ZXN0MQowCAYDVQQDEwExMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsm8CF8fKSzWFKZeO52RJRGER4z7sYrgTb9x\noIeljE8kmhR+EW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXa\nbI9manlqw0WqAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+s\nn6j5yEUnWKSIgoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY\n4X9UpdrjS5cRWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9\nplTq7I9/fDnkRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABo1YwVDAO\nBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0jBBgwFoAU\nqX8xNsutnSC6ud46YB8Ec74sfP4wDAYDVR0RBAUwA4IBMTANBgkqhkiG9w0BAQsF\nAAOCAgEAcj5Ytt47AdmsXBsv/K7YkUvkNwV64luBMQtqmTKRDWnIQLaFzPjdpieu\n81ktFKklKw6pReWdUPSBy6hKq3zzGvSsShBSghbOAJvlPkK6jpLy5TzZdIj8ug7g\nMCzZvqdmznekSg4elGHJIYUfHD6ZUJaEkkGD1yQpxOIVCnodhN2246SXJK23itmz\nB5y1AHU5zydN7Ys0oY1l8RCc5Iz24IcQAi//2pIPe9ORks3QBBi+qY9m+emHCqgb\n48hNe5v7X+yF4VITlWs3Mfk0gSgbDQ4OwVf/8/D7o0hQ8EU5bzXNvf49Kd2mWTii\nQdQDdNLxZsdgWNwYdqrQhA0qN02yJxkhNm5GXmP75zmg0bPe4I+pNwuy+B32wFZn\nNcZrh4HZzS1cAyyyr3E59zsPjqcohaUcBpe6oUoQ8z1V7K9FR31TnFfvjg9mbDnX\nv2+PXsp0m7f4e1QfepZxUwyjemxOe/b+IEc7PckIrkPy46JaIvi9ONrTR8Y5wDir\nbGuzpmiyMFlyzK4ULh7kt7MU/jU/ulnqDU8JvAnhhxK3kgV4vv8LSYJSEYYP9i1S\nj/EPPQBANdtr4B2pcV1ig13dinq7rir6Q/pnkKrAFOfZcvOWW2BvPOC2dcnCYJpB\n1R5QJGXqna8Uh+ZwThs0K/Nd9dml1w/Rug8hx0VHoIe6AjXEepQ=\n-----END CERTIFICATE-----\n", 33 | "device_private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAzsm8CF8fKSzWFKZeO52RJRmhR+\nEW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXabI9manlqw0Wq\nAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+sn6j5yEUnWKSI\ngoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY4X9UpdrjS5cR\nWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9plTq7I9/fDnk\nRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABAoIBAHv3A/ogzBVrA4ut\nkKA8fV6zeZFLOzfcAUuakQujReMvLsoPruPT2VUmuU1SRpNT7csmn7azmRW+4gny\nmO5meKDR382fz2DTIuKI0kByVvtNfmtBwAEdSiBpkzD7m3m1A8hg1wHw3sebolw6\njy3Zvxn5RASe3GKKsnKVLu8n5VXgyytn2I6sYOmKoLv3N9V3tziHL3Gl2AfWAd5P\nJHJdxZ50hhjzUnI0MmvUU6M9G26xagxNNibzOWv3BEuBRw5fuVpt/QoBouFhcKF7\nEdCFpiZ8LJFpux6FyLDOOAa7mj+Y6yK1qKsJbFGG8AnhPTO/bAc1m7yQcJygH9cl\nretVDcECgYEA4z+NkjqIPRiAvOsmJD6KfMeABkZc4JmART+KtrpoJmPWc2WDxu8M\ngP1eqmh/aGGORY8hcFyl+SIf5JvP13Dd/47tSK4vhyEGnnqRt+wjjuzci0rDvFdH\ntaUbjlb4kKStssQPTTmG726Zd1f32eKzBnCY8YqWdMMM1HXak20rPo8CgYEA6PN8\nYIcIrRkFzyvam8m5pCeoHylBgSNjN2j8dGC8b6SGMG6y4+rUiuxfhC/Oq7UtOvf+\njYQQgeMjB22dhcvJa6rjuuKXXpbcgNnzcemnySohUr7Nm1bXHwRfoqMAmeh3pkcL\nL+K4Mf6Gd1i2hiYd4Dd59m5/p3W+QUyKa4iaRP0CgYAf2/UZHyOijSDfW4hJZIs9\n2ypTtuGmi160Vqg33gJj/3M9UmobJcB3BQ6UjXnvRF4R2nMxsYuDVglqn32QEr7M\n6VjS67i2FSc8aKqtQmnpy8NPs/elHAdtq+wlFIRcovnHKj2K8hm8z6CsXqTc4y9+\nI6MNmgRl8kKGNs+iA5ggeQKBgBKLN25zsWQeJtE8G3XlVArWQVLhtN4z0/UYPWiC\nPt3gSfJXDZSJIAxDDsN2DsyqaoRUM4ZOagX878/qkOySsWEJxIEfAo+8EKeNMgzy\nXbHs0aRFnhZsjklgzsAim6ykzcmFxEU2lhUcvtWHUVhSdnRf1iyg1Taeb9vA3Q/8\nWtN9AoGBAN+rik+pvcdPAexngqmsUgoW8Abvv7dyBmt99KfnyRDfbt6EM68CZI90\naOlNE9P7XZyOyfQdzOlJWv8B78dwrbwMiwkhGtMjEzdW\nKFI0T+ZOXN99GcKLHeg5GfGqHcHlEhXP9BtRyTJVz914alvOIaiY\n-----END RSA PRIVATE KEY-----\n" 34 | } 35 | } 36 | )"; 37 | 38 | #if defined(BYTEBEAM_ARDUINO_ARCH_ESP32) 39 | void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { 40 | Serial.printf("Listing directory : %s\r\n", dirname); 41 | 42 | File root = fs.open(dirname); 43 | if (!root) { 44 | Serial.println("- failed to open directory"); 45 | return; 46 | } 47 | if (!root.isDirectory()) { 48 | Serial.println(" - not a directory"); 49 | return; 50 | } 51 | 52 | File file = root.openNextFile(); 53 | while (file) { 54 | if (file.isDirectory()) { 55 | Serial.print(" - DIR : "); 56 | Serial.println(file.name()); 57 | if (levels) { 58 | listDir(fs, file.name(), levels - 1); 59 | } 60 | } else { 61 | Serial.print(" - FILE: "); 62 | Serial.print(file.name()); 63 | Serial.print("\tSIZE: "); 64 | Serial.println(file.size()); 65 | } 66 | file = root.openNextFile(); 67 | } 68 | } 69 | #elif defined(BYTEBEAM_ARDUINO_ARCH_ESP8266) 70 | void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { 71 | Serial.printf("Listing directory: %s\n", dirname); 72 | 73 | Dir root = fs.openDir(dirname); 74 | 75 | while (root.next()) { 76 | File file = root.openFile("r"); 77 | Serial.print(" - FILE: "); 78 | Serial.print(root.fileName()); 79 | Serial.print("\tSIZE: "); 80 | Serial.println(file.size()); 81 | file.close(); 82 | } 83 | } 84 | #endif 85 | 86 | void readFile(fs::FS &fs, const char *path, char *message) { 87 | Serial.printf("Reading file : %s\r\n", path); 88 | 89 | File file = fs.open(path, FILE_READ); 90 | if (!file || file.isDirectory()) { 91 | Serial.println("- failed to open file for reading"); 92 | return; 93 | } 94 | 95 | char chr = ' '; 96 | int strIndex = 0; 97 | 98 | Serial.println("- read from file"); 99 | while (file.available()) { 100 | chr = file.read(); 101 | message[strIndex++] = chr; 102 | } 103 | file.close(); 104 | } 105 | 106 | void writeFile(fs::FS &fs, const char *path, const char *message) { 107 | // spiffs like write file operation 108 | if(!fs.exists(path)) { 109 | if (strchr(path, '/')) { 110 | Serial.printf("Create missing folders of : %s\r\n", path); 111 | 112 | char *pathStr = strdup(path); 113 | if (pathStr) { 114 | char *ptr = strchr(pathStr, '/'); 115 | while (ptr) { 116 | *ptr = 0; 117 | fs.mkdir(pathStr); 118 | *ptr = '/'; 119 | ptr = strchr(ptr+1, '/'); 120 | } 121 | } 122 | free(pathStr); 123 | } 124 | } 125 | 126 | Serial.printf("Writing file : %s\r\n", path); 127 | 128 | File file = fs.open(path, FILE_WRITE); 129 | if (!file) { 130 | Serial.println("- failed to open file for writing"); 131 | return; 132 | } 133 | if (file.print(message)) { 134 | Serial.println("- file written"); 135 | } else { 136 | Serial.println("- write failed"); 137 | } 138 | file.close(); 139 | } 140 | 141 | void setup() { 142 | // put your setup code here, to run once: 143 | Serial.begin(115200); 144 | Serial.println(); 145 | 146 | bool beginStatus = false; 147 | 148 | // initalize the spiffs file system 149 | #if defined(BYTEBEAM_ARDUINO_ARCH_ESP32) 150 | beginStatus = LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED, LITTLEFS_BASE_PATH); 151 | #elif defined(BYTEBEAM_ARDUINO_ARCH_ESP8266) 152 | beginStatus = LittleFS.begin(); 153 | #endif 154 | 155 | if (!beginStatus) { 156 | Serial.println("littlefs mount failed"); 157 | return; 158 | } else { 159 | Serial.println("littlefs mount success"); 160 | } 161 | 162 | #if FORMAT_LITTLEFS_IN_BEGINNING 163 | if (!LittleFS.format()) { 164 | Serial.println("littlefs format failed"); 165 | return; 166 | } else { 167 | Serial.println("littlefs format success"); 168 | } 169 | #endif 170 | 171 | listDir(LittleFS, "/", 0); // list the directories in the littlefs 172 | writeFile(LittleFS, DEVICE_CONFIG_FILE_NAME, deviceConfigWriteStr); // write the device configuration string to littlefs 173 | readFile(LittleFS, DEVICE_CONFIG_FILE_NAME, deviceConfigReadStr); // read the device configuration string from littlefs 174 | 175 | // de-initalize the littlefs file system 176 | LittleFS.end(); 177 | 178 | #if PRINT_BUFFERS_TO_SERIAL 179 | Serial.println(); 180 | Serial.println("deviceConfigWriteStr : "); 181 | Serial.println(deviceConfigWriteStr); 182 | Serial.println("deviceConfigReadStr : "); 183 | Serial.println(deviceConfigReadStr); 184 | #endif 185 | 186 | // verify the write process and log the result 187 | if (!memcmp(deviceConfigReadStr, deviceConfigWriteStr, DEVICE_CONFIG_STR_LENGTH)) { 188 | Serial.println("device provisioning success !"); 189 | } else { 190 | Serial.println("device provisioning failed !"); 191 | } 192 | } 193 | 194 | void loop() { 195 | // put your main code here, to run repeatedly: 196 | 197 | // nothing to do here 198 | } -------------------------------------------------------------------------------- /examples/Provisioning/LITTLEFSProvisioning/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam LITTLEFS Provisioning Example 2 | This example will show you how to provison your device with LITTLEFS file system. 3 | 4 | ## Hardware specification 5 | 1. Dev Board (ESP32 or ESP8266) 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/Provisioning/README.md: -------------------------------------------------------------------------------- 1 | ## Provisioning 2 | 3 | Before you get started with the **BytebeamArduino** you need to provision your device. Each device have it's own config file which needs to be flased into it's file system. As long as the file system is supported by the device, you can pick any of the following file systems for device provisioning. 4 | 5 | - SPIFFSProvisioning 6 | - LITTLEFSProvisioning 7 | - FATFSProvisioning 8 | 9 | Default Configuration, 10 | 11 | | Arch | File Sytem | File Name | 12 | | ------------- |:-------------:| -------------------:| 13 | | ESP32 | SPIFFS | /device_config.json | 14 | | ESP8266 | LITTLEFS | /device_config.json | 15 | 16 | You can always override the default configurations and here are steps to do so, 17 | - Provision your device with the required configurations 18 | - Specify the same configurations in your sketch via `begin` method. 19 | 20 | See [Advance SDK Configurations](https://docs.bytebeam.io/docs/advance-sdk-configurations) for the implementation details. -------------------------------------------------------------------------------- /examples/Provisioning/SPIFFSProvisioning/README.md: -------------------------------------------------------------------------------- 1 | # Bytebeam SPIFFS Provisioning Example 2 | This example will show you how to provison your device with SPIFFS file system. 3 | 4 | ## Hardware specification 5 | 1. Dev Board (ESP32 or ESP8266) 6 | 7 | ## Software Specification 8 | 1. Bytebeam Arduino Library -------------------------------------------------------------------------------- /examples/Provisioning/SPIFFSProvisioning/SPIFFSProvisioning.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* This macro is used to specify the base path of the spiffs partiiton */ 4 | #define SPIFFS_BASE_PATH "/spiffs" 5 | 6 | /* This macro is used to format the spiffs if in case the spiffs initialization fails i.e reset if not required */ 7 | #define FORMAT_SPIFFS_IF_FAILED true 8 | 9 | /* This macro is used to format the spiffs in the beginnig i.e reset if not required */ 10 | #define FORMAT_SPIFSS_IN_BEGINNING true 11 | 12 | /* This macro is used to specify the name of the device config file */ 13 | #define DEVICE_CONFIG_FILE_NAME "/device_config.json" 14 | 15 | /* This macro is used to specify the maximum size of device config json in bytes that need to be handled for particular device */ 16 | #define DEVICE_CONFIG_STR_LENGTH 8192 17 | 18 | /* This macro is used to print the device config read/write buffers to serial monitor i.e set to debug any issue */ 19 | #define PRINT_BUFFERS_TO_SERIAL false 20 | 21 | char deviceConfigReadStr[DEVICE_CONFIG_STR_LENGTH] = ""; 22 | 23 | // Replace this with your device config json in the same format 24 | char deviceConfigWriteStr[DEVICE_CONFIG_STR_LENGTH] = R"( 25 | { 26 | "project_id": "demo", 27 | "broker": "cloud.bytebeam.io", 28 | "port": 8883, 29 | "device_id": "1", 30 | "authentication": { 31 | "ca_certificate": "-----BEGIN CERTIFICATE-----\nMIIFrDCCA5SgAwIBAgICBMwDQYJAwdzEOMAwGA1UBhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYcmUxFzAVBgNV\nBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIxMDkwMjExMDYyM1oXDTMxMDkwMjExMDYyM1owdzEOMAwG\nA1UEBhMFSW5kaWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCYW5nYWxv\ncmUxFzAVBgNVBAkTDlN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDAS\nBgNVBAoTC0J5dGViZWFtLmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC\nAgEAr/bnOa/8AUGZmd/s+7rejuROgeLqqU9X15KKfKOBqcoMyXsSO65UEwpzadpw\nMl7GDCdHqFTymqdnAnbhgaT1PoIFhOG64y7UiNgiWmbh0XJj8G6oLrW9rQ1gug1Q\n/D7x2fUnza71aixiwEL+KsIFYIdDuzmoRD3rSer/bKOcGGs0WfB54KqIVVZ1DwsU\nk1wx5ExsKo7gAdXMAbdHRI2Szmn5MsZwGL6V0LfsKLE8ms2qlZe50oo2woLNN6XP\nRfRL4bwwkdsCqXWkkt4eUSNDq9hJsuINHdhO3GUieLsKLJGWJ0lq6si74t75rIKb\nvvsFEQ9mnAVS+iuUUsSjHPJIMnn/J64Nmgl/R/8FP5TUgUrHvHXKQkJ9h/a7+3tS\nlV2KMsFksXaFrGEByGIJ7yR4qu9hx5MXf8pf8EGEwOW/H3CdWcC2MvJ11PVpceUJ\neDVwE7B4gPM9Kx02RNwvUMH2FmYqkXX2DrrHQGQuq+6VRoN3rEdmGPqnONJEPeOw\nZzcGDVXKWZtd7UCbcZKdn0RYmVtI/OB5OW8IRoXFYgGB3IWP796dsXIwbJSqRb9m\nylICGOceQy3VR+8+BHkQLj5/ZKTe+AA3Ktk9UADvxRiWKGcejSA/LvyT8qzz0dqn\nGtcHYJuhJ/XpkHtB0PykB5WtxFjx3G/osbZfrNflcQZ9h1MCAwEAAaNCMEAwDgYD\nVR0PAQH/BAQDAgKEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKl/MTbLrZ0g\nurneOmAfBHO+LHz+MA0GCSqGSIb3DQEBCwUAA4ICAQAlus/uKic5sgo1d2hBJ0Ak\ns1XJsA2jz+OEdshQHmCCmzFir3IRSuVRmDBaBGlJDHCELqYxKn6dl/sKGwoqoAQ5\nOeR2sey3Nmdyw2k2JTDx58HnApZKAVir7BDxbIbbHmfhJk4ljeUBbertNXWbRHVr\ncs4XBNwXvX+noZjQzmXXK89YBsV2DCrGRAUeZ4hQEqV7XC0VKmlzEmfkr1nibDr5\nqwbI+7QWIAnkHggYi27lL2UTH7TvkwYC4TyDaoQ2ZRpG\nHY+mxXLdftoMv/ZvmyjOPYeTRQbfPqoRqcM6XOPXwSw9B6YddwmnkI7ohNOvAVfD\nwGptUc5OodgFQc3waRljX1q2lawZCTh58IUf32CRtOEL2RIz4VpUrNF/0E2vts1f\npO7V1vY2Qin998Nwqkxdsll0GLtEEE9hUyvk1F8U+fgjJ3Rjn4BxnCN4oCrdJOMa\nJCaysaHV7EEIMqrYP4jH6RzQzOXLd0m9NaL8A/Y9z2a96fwpZZU/fEEOH71t3Eo3\nV/CKlysiALMtsHfZDwHNpa6g0NQNGN5IRl/w1TS1izzjzgWhR6r8wX8OPLRzhNRz\n2HDbTXGYsem0ihC0B8uzujOhTHcBwsfxZUMpGjg8iycJlfpPDWBdw8qrGu8LeNux\na0cIevjvYAtVysoXInV0kg==\n-----END CERTIFICATE-----\n", 32 | "device_certificate": "-----BEGIN CERTIFICATE-----\nMIIEcjCCAlqgAwIBAgICB+MwhMFSW5k\naWExETAPBgNVBAgTCEthcm5hdGFrMRIwEAYDVQQHEwlCN1YmJpYWggR2FyZGVuMQ8wDQYDVQQREwY1NjAwMTExFDASBgNVBAoTC0J5\ndGViZWFtLmlvMB4XDTIyMTEwMzA3NDcwMloXDTMyMTEKTEbMBkG\nA1UEChMSZXNwYnl0ZWJlYW1zZGt0ZXN0MQowCAYDVQQDEwExMIIBIjANBgkqhkiG\n9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsm8CF8fKSzWFKZeO52RJRGER4z7sYrgTb9x\noIeljE8kmhR+EW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXa\nbI9manlqw0WqAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+s\nn6j5yEUnWKSIgoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY\n4X9UpdrjS5cRWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9\nplTq7I9/fDnkRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABo1YwVDAO\nBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwHwYDVR0jBBgwFoAU\nqX8xNsutnSC6ud46YB8Ec74sfP4wDAYDVR0RBAUwA4IBMTANBgkqhkiG9w0BAQsF\nAAOCAgEAcj5Ytt47AdmsXBsv/K7YkUvkNwV64luBMQtqmTKRDWnIQLaFzPjdpieu\n81ktFKklKw6pReWdUPSBy6hKq3zzGvSsShBSghbOAJvlPkK6jpLy5TzZdIj8ug7g\nMCzZvqdmznekSg4elGHJIYUfHD6ZUJaEkkGD1yQpxOIVCnodhN2246SXJK23itmz\nB5y1AHU5zydN7Ys0oY1l8RCc5Iz24IcQAi//2pIPe9ORks3QBBi+qY9m+emHCqgb\n48hNe5v7X+yF4VITlWs3Mfk0gSgbDQ4OwVf/8/D7o0hQ8EU5bzXNvf49Kd2mWTii\nQdQDdNLxZsdgWNwYdqrQhA0qN02yJxkhNm5GXmP75zmg0bPe4I+pNwuy+B32wFZn\nNcZrh4HZzS1cAyyyr3E59zsPjqcohaUcBpe6oUoQ8z1V7K9FR31TnFfvjg9mbDnX\nv2+PXsp0m7f4e1QfepZxUwyjemxOe/b+IEc7PckIrkPy46JaIvi9ONrTR8Y5wDir\nbGuzpmiyMFlyzK4ULh7kt7MU/jU/ulnqDU8JvAnhhxK3kgV4vv8LSYJSEYYP9i1S\nj/EPPQBANdtr4B2pcV1ig13dinq7rir6Q/pnkKrAFOfZcvOWW2BvPOC2dcnCYJpB\n1R5QJGXqna8Uh+ZwThs0K/Nd9dml1w/Rug8hx0VHoIe6AjXEepQ=\n-----END CERTIFICATE-----\n", 33 | "device_private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAzsm8CF8fKSzWFKZeO52RJRmhR+\nEW217sxUyUn+rmJSCxRz6jtspKv37POPaQilmwtriVq8L46YCrXabI9manlqw0Wq\nAfaWAlFXzM13CuXeGZKhuAK3INs15jqP0s+oWFvww8+hww540I+sn6j5yEUnWKSI\ngoYEc82cwvj0qOvaxYxjUTXgV2IDLSXdFJbZq4k9LDbzPZdDe0aY4X9UpdrjS5cR\nWT3Ok4VwWpMRwOT654CTwE8WUja/pHTRFbMYkqd1jrD2Joqtm+u9plTq7I9/fDnk\nRqPjueDQ04LKTbUC2UsRKw1VmHPndw22+mDPUwIDAQABAoIBAHv3A/ogzBVrA4ut\nkKA8fV6zeZFLOzfcAUuakQujReMvLsoPruPT2VUmuU1SRpNT7csmn7azmRW+4gny\nmO5meKDR382fz2DTIuKI0kByVvtNfmtBwAEdSiBpkzD7m3m1A8hg1wHw3sebolw6\njy3Zvxn5RASe3GKKsnKVLu8n5VXgyytn2I6sYOmKoLv3N9V3tziHL3Gl2AfWAd5P\nJHJdxZ50hhjzUnI0MmvUU6M9G26xagxNNibzOWv3BEuBRw5fuVpt/QoBouFhcKF7\nEdCFpiZ8LJFpux6FyLDOOAa7mj+Y6yK1qKsJbFGG8AnhPTO/bAc1m7yQcJygH9cl\nretVDcECgYEA4z+NkjqIPRiAvOsmJD6KfMeABkZc4JmART+KtrpoJmPWc2WDxu8M\ngP1eqmh/aGGORY8hcFyl+SIf5JvP13Dd/47tSK4vhyEGnnqRt+wjjuzci0rDvFdH\ntaUbjlb4kKStssQPTTmG726Zd1f32eKzBnCY8YqWdMMM1HXak20rPo8CgYEA6PN8\nYIcIrRkFzyvam8m5pCeoHylBgSNjN2j8dGC8b6SGMG6y4+rUiuxfhC/Oq7UtOvf+\njYQQgeMjB22dhcvJa6rjuuKXXpbcgNnzcemnySohUr7Nm1bXHwRfoqMAmeh3pkcL\nL+K4Mf6Gd1i2hiYd4Dd59m5/p3W+QUyKa4iaRP0CgYAf2/UZHyOijSDfW4hJZIs9\n2ypTtuGmi160Vqg33gJj/3M9UmobJcB3BQ6UjXnvRF4R2nMxsYuDVglqn32QEr7M\n6VjS67i2FSc8aKqtQmnpy8NPs/elHAdtq+wlFIRcovnHKj2K8hm8z6CsXqTc4y9+\nI6MNmgRl8kKGNs+iA5ggeQKBgBKLN25zsWQeJtE8G3XlVArWQVLhtN4z0/UYPWiC\nPt3gSfJXDZSJIAxDDsN2DsyqaoRUM4ZOagX878/qkOySsWEJxIEfAo+8EKeNMgzy\nXbHs0aRFnhZsjklgzsAim6ykzcmFxEU2lhUcvtWHUVhSdnRf1iyg1Taeb9vA3Q/8\nWtN9AoGBAN+rik+pvcdPAexngqmsUgoW8Abvv7dyBmt99KfnyRDfbt6EM68CZI90\naOlNE9P7XZyOyfQdzOlJWv8B78dwrbwMiwkhGtMjEzdW\nKFI0T+ZOXN99GcKLHeg5GfGqHcHlEhXP9BtRyTJVz914alvOIaiY\n-----END RSA PRIVATE KEY-----\n" 34 | } 35 | } 36 | )"; 37 | 38 | #if defined(BYTEBEAM_ARDUINO_ARCH_ESP32) 39 | void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { 40 | Serial.printf("Listing directory : %s\r\n", dirname); 41 | 42 | File root = fs.open(dirname); 43 | if (!root) { 44 | Serial.println("- failed to open directory"); 45 | return; 46 | } 47 | if (!root.isDirectory()) { 48 | Serial.println(" - not a directory"); 49 | return; 50 | } 51 | 52 | File file = root.openNextFile(); 53 | while (file) { 54 | if (file.isDirectory()) { 55 | Serial.print(" - DIR : "); 56 | Serial.println(file.name()); 57 | if (levels) { 58 | listDir(fs, file.name(), levels - 1); 59 | } 60 | } else { 61 | Serial.print(" - FILE: "); 62 | Serial.print(file.name()); 63 | Serial.print("\tSIZE: "); 64 | Serial.println(file.size()); 65 | } 66 | file = root.openNextFile(); 67 | } 68 | } 69 | #elif defined(BYTEBEAM_ARDUINO_ARCH_ESP8266) 70 | void listDir(fs::FS &fs, const char *dirname, uint8_t levels) { 71 | Serial.printf("Listing directory: %s\n", dirname); 72 | 73 | Dir root = fs.openDir(dirname); 74 | 75 | while (root.next()) { 76 | File file = root.openFile("r"); 77 | Serial.print(" - FILE: "); 78 | Serial.print(root.fileName()); 79 | Serial.print("\tSIZE: "); 80 | Serial.println(file.size()); 81 | file.close(); 82 | } 83 | } 84 | #endif 85 | 86 | void readFile(fs::FS &fs, const char *path, char *message) { 87 | Serial.printf("Reading file : %s\r\n", path); 88 | 89 | File file = fs.open(path, FILE_READ); 90 | if (!file || file.isDirectory()) { 91 | Serial.println("- failed to open file for reading"); 92 | return; 93 | } 94 | 95 | char chr = ' '; 96 | int strIndex = 0; 97 | 98 | Serial.println("- read from file"); 99 | while (file.available()) { 100 | chr = file.read(); 101 | message[strIndex++] = chr; 102 | } 103 | file.close(); 104 | } 105 | 106 | void writeFile(fs::FS &fs, const char *path, const char *message) { 107 | Serial.printf("Writing file : %s\r\n", path); 108 | 109 | File file = fs.open(path, FILE_WRITE); 110 | if (!file) { 111 | Serial.println("- failed to open file for writing"); 112 | return; 113 | } 114 | if (file.print(message)) { 115 | Serial.println("- file written"); 116 | } else { 117 | Serial.println("- write failed"); 118 | } 119 | file.close(); 120 | } 121 | 122 | void setup() { 123 | // put your setup code here, to run once: 124 | Serial.begin(115200); 125 | Serial.println(); 126 | 127 | #if FORMAT_SPIFSS_IN_BEGINNING 128 | if (!SPIFFS.format()) { 129 | Serial.println("spiffs format failed"); 130 | return; 131 | } else { 132 | Serial.println("spiffs format success"); 133 | } 134 | #endif 135 | 136 | bool beginStatus = false; 137 | 138 | // initalize the spiffs file system 139 | #if defined(BYTEBEAM_ARDUINO_ARCH_ESP32) 140 | beginStatus = SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED, SPIFFS_BASE_PATH); 141 | #elif defined(BYTEBEAM_ARDUINO_ARCH_ESP8266) 142 | beginStatus = SPIFFS.begin(); 143 | #endif 144 | 145 | if (!beginStatus) { 146 | Serial.println("spiffs mount failed"); 147 | return; 148 | } else { 149 | Serial.println("spiffs mount success"); 150 | } 151 | 152 | listDir(SPIFFS, "/", 0); // list the directories in the spiffs 153 | writeFile(SPIFFS, DEVICE_CONFIG_FILE_NAME, deviceConfigWriteStr); // write the device configuration string to spiffs 154 | readFile(SPIFFS, DEVICE_CONFIG_FILE_NAME, deviceConfigReadStr); // read the device configuration string from spiffs 155 | 156 | // de-initalize the spiffs file system 157 | SPIFFS.end(); 158 | 159 | #if PRINT_BUFFERS_TO_SERIAL 160 | Serial.println(); 161 | Serial.println("deviceConfigWriteStr : "); 162 | Serial.println(deviceConfigWriteStr); 163 | Serial.println("deviceConfigReadStr : "); 164 | Serial.println(deviceConfigReadStr); 165 | #endif 166 | 167 | // verify the write process and log the result 168 | if (!memcmp(deviceConfigReadStr, deviceConfigWriteStr, DEVICE_CONFIG_STR_LENGTH)) { 169 | Serial.println("device provisioning success !"); 170 | } else { 171 | Serial.println("device provisioning failed !"); 172 | } 173 | } 174 | 175 | void loop() { 176 | // put your main code here, to run repeatedly: 177 | 178 | // nothing to do here 179 | } -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | ## BytebeamArduino Examples 2 | 3 | Let's get started with the **BytebeamArduino** 4 | 5 | - Provisioning 6 | - ESP32 7 | - ESP8266 -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BytebeamArduino", 3 | "version": "1.1.0", 4 | "description": "A small Arduino Library for Bytebeam Cloud that just works. This library simplifies the process of communicating with Bytebeam cloud backend.", 5 | "keywords": "mqtt, http, gsm, iot, arduino, espressif32, espressif8266, bytebeam, device-management, ota-firmware-updates, cloud-logging", 6 | "license": "Apache-2.0", 7 | "authors": [ 8 | { 9 | "name": "Mayank Narang", 10 | "url": "https://github.com/narangmayank", 11 | "maintainer": true 12 | } 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/bytebeamio/bytebeam-arduino-sdk" 17 | }, 18 | "homepage": "https://bytebeam.io/docs/arduino", 19 | "frameworks": "arduino", 20 | "platforms": [ 21 | "espressif8266", 22 | "espressif32" 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=BytebeamArduino 2 | version=1.1.0 3 | author=Mayank Narang 4 | maintainer=Mayank Narang 5 | sentence=A small Arduino Library for Bytebeam Cloud that just works. 6 | paragraph=This library simplifies the process of communicating with Bytebeam cloud backend. 7 | category=Communication 8 | url=https://bytebeam.io/docs/arduino 9 | architectures=esp32,esp8266 10 | repository=https://github.com/bytebeamio/bytebeam-arduino-sdk.git -------------------------------------------------------------------------------- /src/BytebeamArduino.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEBEAM_ARDUINO_H 2 | #define BYTEBEAM_ARDUINO_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "BytebeamLog.h" 8 | #include "BytebeamTime.h" 9 | #include "BytebeamOTA.h" 10 | #include "BytebeamLogger.h" 11 | #include "BytebeamArduinoDefines.h" 12 | 13 | #ifndef FILE_READ 14 | #define FILE_READ "r" 15 | #endif 16 | 17 | #ifndef FILE_WRITE 18 | #define FILE_WRITE "w" 19 | #endif 20 | 21 | /* This macro is used to specify the maximum length of bytebeam mqtt topic string */ 22 | #define BYTEBEAM_MQTT_TOPIC_STR_LEN 200 23 | 24 | /* This macro is used to specify the maximum length of bytebeam action id string */ 25 | #define BYTEBEAM_ACTION_ID_STR_LEN 20 26 | 27 | /* This macro is used to specify the maximum number of actions that need to be handled for particular device */ 28 | #define BYTEBEAM_NUMBER_OF_ACTIONS 10 29 | 30 | /* This macro is used to specify the file system used for provisioning the device */ 31 | #if defined(BYTEBEAM_ARDUINO_ARCH_ESP32) 32 | // defaults to spiffs for esp32 arch (usual filesystem) 33 | #define DEVICE_CONFIG_FILE_SYSTEM SPIFFS_FILE_SYSTEM 34 | #elif defined(BYTEBEAM_ARDUINO_ARCH_ESP8266) 35 | // defaults to littlefs for esp8266 arch (community recommended) 36 | #define DEVICE_CONFIG_FILE_SYSTEM LITTLEFS_FILE_SYSTEM 37 | #endif 38 | 39 | /* This macro is used to specify the name of the device config file */ 40 | #define DEVICE_CONFIG_FILE_NAME "/device_config.json" 41 | 42 | /* This macro is used to specify the maximum number of attempts we will perform to reconnect to the server in case the client got disconnect */ 43 | #define BYTEBEAM_CONNECT_MAX_RETRIES 5 44 | 45 | /* This macro is used to enable the OTA i.e disable this flag to completely remove OTA from compilation phase thereby saving flash size too */ 46 | #define BYTEBEAM_OTA_ENABLE true 47 | 48 | class BytebeamArduino : private PubSubClient, 49 | public BytebeamLog { 50 | public: 51 | /** 52 | * @enum deviceConfigFileSystem 53 | * This sturct contains the available file systems that can be used for provisioning the device 54 | * @var deviceConfigFileSystem::FATFS_FILE_SYSTEM 55 | * Use FATFS file system for provisioning the device 56 | * @var deviceConfigFileSystem::SPIFFS_FILE_SYSTEM 57 | * Use SPIFFS file system for provisioning the device 58 | * @var deviceConfigFileSystem::LITTLEFS_FILE_SYSTEM 59 | * Use LITTLEFS file system for provisioning the device 60 | * @var deviceConfigFileSystem::SD_FILE_SYSTEM 61 | * Use SD file system for provisioning the device 62 | */ 63 | typedef enum { 64 | FATFS_FILE_SYSTEM, 65 | SPIFFS_FILE_SYSTEM, 66 | LITTLEFS_FILE_SYSTEM, 67 | SD_FILE_SYSTEM 68 | } deviceConfigFileSystem; 69 | 70 | /** 71 | * @struct actionFunctionsHandler 72 | * This sturct contains name and function pointer for particular action 73 | * @var actionFunctionsHandler::name 74 | * Name of particular action 75 | * @var actionFunctionsHandler::func 76 | * Pointer to action handler function for particular action 77 | */ 78 | typedef struct { 79 | const char* name; 80 | int (*func)(char* args, char* actionId); 81 | } actionFunctionsHandler; 82 | 83 | // contructor 84 | BytebeamArduino(); 85 | 86 | // destructor 87 | ~BytebeamArduino(); 88 | 89 | // public functions 90 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 91 | bool begin( const deviceConfigFileSystem fileSystem = DEVICE_CONFIG_FILE_SYSTEM, 92 | const char* fileName = DEVICE_CONFIG_FILE_NAME, 93 | BytebeamLogger::DebugLevel level = BytebeamLogger::LOG_WARN); 94 | 95 | bool begin( char* deviceConfigData, 96 | BytebeamLogger::DebugLevel level = BytebeamLogger::LOG_WARN); 97 | #endif 98 | 99 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 100 | bool begin( TinyGsm* modem, 101 | const deviceConfigFileSystem fileSystem = DEVICE_CONFIG_FILE_SYSTEM, 102 | const char* fileName = DEVICE_CONFIG_FILE_NAME, 103 | BytebeamLogger::DebugLevel level = BytebeamLogger::LOG_WARN); 104 | 105 | bool begin( TinyGsm* modem, 106 | char* deviceConfigData, 107 | BytebeamLogger::DebugLevel level = BytebeamLogger::LOG_WARN); 108 | #endif 109 | 110 | bool loop(); 111 | bool isConnected(); 112 | bool handleActions(char* actionReceivedStr); 113 | bool addActionHandler(int (*funcPtr)(char* args, char* actionId), char* actionName); 114 | bool removeActionHandler(char* actionName); 115 | bool updateActionHandler(int (*newFuncPtr)(char* args, char* actionId), char* actionName); 116 | bool isActionHandlerThere(char* actionName); 117 | bool printActionHandlerArray(); 118 | bool resetActionHandlerArray(); 119 | bool publishActionCompleted(char* actionId); 120 | bool publishActionFailed(char* actionId, char* error = "Action Failed"); 121 | bool publishActionProgress(char* actionId, int progressPercentage, char* status = "Progress"); 122 | bool publishToStream(char* streamName, const char* payload); 123 | 124 | #if BYTEBEAM_OTA_ENABLE 125 | bool enableOTA(); 126 | bool isOTAEnabled(); 127 | bool disableOTA(); 128 | #endif 129 | 130 | bool end(); 131 | 132 | // public variables 133 | const char* status; 134 | const char* softwareType; 135 | const char* softwareVersion; 136 | const char* hardwareType; 137 | const char* hardwareVersion; 138 | 139 | private: 140 | // private functions 141 | void printArchitectureInfo(); 142 | void initActionHandlerArray(); 143 | bool subscribe(const char* topic, uint8_t qos); 144 | bool unsubscribe(const char* topic); 145 | bool publish(const char* topic, const char* payload); 146 | bool subscribeToActions(); 147 | bool unsubscribeToActions(); 148 | bool publishActionStatus(char* actionId, int progressPercentage, char* status, char* error); 149 | bool readDeviceConfigFile(); 150 | bool parseDeviceConfigFile(); 151 | bool setupBytebeamClient(); 152 | void clearBytebeamClient(); 153 | bool initSDK(); 154 | bool isInitialized(); 155 | bool publishDeviceHeartbeat(); 156 | 157 | // private variables 158 | int mqttPort; 159 | const char* mqttBrokerUrl; 160 | const char* deviceId; 161 | const char* projectId; 162 | const char* caCertPem; 163 | const char* clientCertPem; 164 | const char* clientKeyPem; 165 | const char* clientId; 166 | int actionFuncsHandlerIdx; 167 | actionFunctionsHandler actionFuncs[BYTEBEAM_NUMBER_OF_ACTIONS]; 168 | deviceConfigFileSystem fileSystem; 169 | const char* fileName; 170 | char* deviceConfigStr; 171 | bool isClientActive; 172 | bool isOTAEnable; 173 | char lastKnownActionId[BYTEBEAM_ACTION_ID_STR_LEN]; 174 | 175 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 176 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 177 | WiFiClientSecure secureClient; 178 | #endif 179 | 180 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 181 | TinyGsmClient gsmClient; 182 | SSLClient secureClient; 183 | #endif 184 | #endif 185 | 186 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP8266 187 | const BearSSL::X509List* rootCA = NULL; 188 | const BearSSL::X509List* clientCert = NULL; 189 | const BearSSL::PrivateKey* clientKey = NULL; 190 | BearSSL::WiFiClientSecure secureClient; 191 | #endif 192 | }; 193 | 194 | extern BytebeamArduino Bytebeam; 195 | 196 | #endif /* BYTEBEAM_ARDUINO_H */ -------------------------------------------------------------------------------- /src/BytebeamArduinoDefines.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEBEAM_ARDUINO_DEFINES_H 2 | #define BYTEBEAM_ARDUINO_DEFINES_H 3 | 4 | // 5 | // Enable the define as per your connectivity interface 6 | // Make sure you enable only one interface at a time 7 | // 8 | 9 | // defines for using the wifi interface 10 | #define BYTEBEAM_ARDUINO_USE_WIFI 11 | 12 | // defines for using the modem interface 13 | // #define TINY_GSM_MODEM_SIM7600 14 | // #define BYTEBEAM_ARDUINO_USE_MODEM 15 | 16 | #if defined(ESP32) || defined(ARDUINO_ARCH_ESP32) 17 | // ESP32 architecture dependent defines 18 | #define BYTEBEAM_ARDUINO_ARCH_ESP32 19 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_FS 20 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_FATFS 21 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_SPIFFS 22 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_LITTLEFS 23 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_SD 24 | 25 | // ESP32 architecture dependent includes 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #endif 39 | 40 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 41 | #include 42 | #include 43 | #include 44 | #include "BytebeamHTTPUpdate.h" 45 | #endif 46 | #elif defined(ESP8266) || defined(ARDUINO_ARCH_ESP8266) 47 | // ESP8266 architecture dependent defines 48 | #define BYTEBEAM_ARDUINO_ARCH_ESP8266 49 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_FS 50 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_SPIFFS 51 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_LITTLEFS 52 | #define BYTEBEAM_ARDUINO_ARCH_SUPPORTS_SD 53 | 54 | // ESP8266 architecture dependent includes 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include 63 | #endif 64 | 65 | #endif /* BYTEBEAM_ARDUINO_DEFINES_H */ -------------------------------------------------------------------------------- /src/BytebeamHTTPUpdate.cpp: -------------------------------------------------------------------------------- 1 | #include "BytebeamHTTPUpdate.h" 2 | #include "BytebeamLogger.h" 3 | 4 | #if defined(BYTEBEAM_ARDUINO_ARCH_ESP32) && defined(BYTEBEAM_ARDUINO_USE_MODEM) 5 | 6 | bool BytebeamHTTPUpdate::runUpdate(Stream& in, uint32_t size) { 7 | StreamString error; 8 | 9 | if(_cbProgress) { 10 | Update.onProgress(_cbProgress); 11 | } 12 | 13 | if(!Update.begin(size, U_FLASH, _ledPin, _ledOn)) { 14 | _lastError = Update.getError(); 15 | Update.printError(error); 16 | error.trim(); // remove line ending 17 | BytebeamLogger::Error(__FILE__, __func__, "Update.begin failed! (%s)", error.c_str()); 18 | return false; 19 | } 20 | 21 | if(_cbProgress) { 22 | _cbProgress(0, size); 23 | } 24 | 25 | // To do: the MD5 could be checked if the server sends it 26 | // To do: the SHA256 could be checked if the server sends it 27 | 28 | if(Update.writeStream(in) != size) { 29 | _lastError = Update.getError(); 30 | Update.printError(error); 31 | error.trim(); // remove line ending 32 | BytebeamLogger::Error(__FILE__, __func__, "Update.writeStream failed! (%s)", error.c_str()); 33 | return false; 34 | } 35 | 36 | if(_cbProgress) { 37 | _cbProgress(size, size); 38 | } 39 | 40 | if(!Update.end()) { 41 | _lastError = Update.getError(); 42 | Update.printError(error); 43 | error.trim(); // remove line ending 44 | BytebeamLogger::Error(__FILE__, __func__, "Update.end failed! (%s)", error.c_str()); 45 | return false; 46 | } 47 | 48 | return true; 49 | } 50 | 51 | BytebeamHTTPUpdate::BytebeamHTTPUpdate() { 52 | // 53 | // Initailizing all the variables with default values here 54 | // 55 | 56 | this->_rebootOnUpdate = true; 57 | this->_ledPin = -1; 58 | this->_ledOn = HIGH; 59 | } 60 | 61 | BytebeamHTTPUpdate::~BytebeamHTTPUpdate() { 62 | // 63 | // Nothing much to do here, just print the log to serial :) 64 | // 65 | 66 | BytebeamLogger::Info(__FILE__, __func__, "I am BytebeamHTTPUpdate::~BytebeamHTTPUpdate()"); 67 | } 68 | 69 | int BytebeamHTTPUpdate::getLastError(void) { 70 | return _lastError; 71 | } 72 | 73 | String BytebeamHTTPUpdate::getLastErrorString(void) { 74 | if(_lastError == 0) { 75 | return String(); // no error 76 | } 77 | 78 | // error from Update class 79 | if(_lastError > 0) { 80 | StreamString error; 81 | Update.printError(error); 82 | error.trim(); // remove line ending 83 | return String("Update error: ") + error; 84 | } 85 | 86 | switch(_lastError) { 87 | case HTTP_UE_TOO_LESS_SPACE: 88 | return "Not Enough space"; 89 | case HTTP_UE_SERVER_NOT_REPORT_SIZE: 90 | return "Server Did Not Report Size"; 91 | case HTTP_UE_BIN_VERIFY_HEADER_FAILED: 92 | return "Verify Bin Header Failed"; 93 | case HTTP_UE_NO_PARTITION: 94 | return "Partition Could Not be Found"; 95 | } 96 | 97 | return String("HTTP Error"); 98 | } 99 | 100 | t_httpUpdate_return BytebeamHTTPUpdate::update(Client& client, const String& url, const String& currentVersion) { 101 | // url will come in this format "https://firmware.cloud.bytebeam.io/api/v1/firmwares/{version}/artifact\" 102 | const uint16_t port = 443; 103 | const String server = url.substring(8, 34); 104 | const String resource = url.substring(34, url.length()); 105 | BytebeamHTTPUpdateResult ret = HTTP_UPDATE_FAILED; 106 | 107 | HttpClient http(client, server, port); 108 | 109 | BytebeamLogger::Info(__FILE__, __func__, "ESP32 info ::"); 110 | BytebeamLogger::Info(__FILE__, __func__, " - free Space: %d", ESP.getFreeSketchSpace()); 111 | BytebeamLogger::Info(__FILE__, __func__, " - current Sketch Size: %d", ESP.getSketchSize()); 112 | 113 | int statusCode = 0; 114 | 115 | if(http.get(resource) == 0) { 116 | // read status code 117 | statusCode = http.responseStatusCode(); 118 | BytebeamLogger::Info(__FILE__, __func__, "HTTPS Status code : %d", statusCode); 119 | 120 | // read headers 121 | while(http.headerAvailable()) { 122 | BytebeamLogger::Info(__FILE__, __func__, "%s : %s", http.readHeaderName().c_str(), http.readHeaderValue().c_str()); 123 | } 124 | } else { 125 | BytebeamLogger::Error(__FILE__, __func__, "Unable to connect to HTTPS Server"); 126 | return HTTP_UPDATE_FAILED; 127 | } 128 | 129 | // image size 130 | size_t len = 0; 131 | 132 | // read content length 133 | len = http.contentLength(); 134 | BytebeamLogger::Info(__FILE__, __func__, "Content Length : %d", len); 135 | 136 | ///< OK (Start Update) 137 | if(statusCode == 200) { 138 | if(len > 0) { 139 | bool startUpdate = true; 140 | 141 | // check if space is available 142 | int sketchFreeSpace = ESP.getFreeSketchSpace(); 143 | if(!sketchFreeSpace){ 144 | _lastError = HTTP_UE_NO_PARTITION; 145 | BytebeamLogger::Error(__FILE__, __func__, "No FreeSketchSpace"); 146 | return HTTP_UPDATE_FAILED; 147 | } 148 | 149 | // make sure we have enough space available 150 | if(len > sketchFreeSpace) { 151 | BytebeamLogger::Error(__FILE__, __func__, "FreeSketchSpace to low (%d) needed: %d", sketchFreeSpace, len); 152 | startUpdate = false; 153 | } 154 | 155 | if(!startUpdate) { 156 | _lastError = HTTP_UE_TOO_LESS_SPACE; 157 | ret = HTTP_UPDATE_FAILED; 158 | } else { 159 | // Warn main app we're starting up... 160 | if (_cbStart) { 161 | _cbStart(); 162 | } 163 | 164 | if(http.peek() != 0xE9) { 165 | BytebeamLogger::Error(__FILE__, __func__, "Magic header does not start with 0xE9"); 166 | _lastError = HTTP_UE_BIN_VERIFY_HEADER_FAILED; 167 | http.stop(); 168 | return HTTP_UPDATE_FAILED; 169 | } 170 | 171 | if(runUpdate(http, len)) { 172 | ret = HTTP_UPDATE_OK; 173 | BytebeamLogger::Debug(__FILE__, __func__, "Update ok"); 174 | http.stop(); 175 | 176 | // Warn main app we're all done 177 | if (_cbEnd) { 178 | _cbEnd(); 179 | } 180 | 181 | if(_rebootOnUpdate) { 182 | BytebeamLogger::Info(__FILE__, __func__, "Rebooting..."); 183 | ESP.restart(); 184 | } 185 | } else { 186 | ret = HTTP_UPDATE_FAILED; 187 | BytebeamLogger::Debug(__FILE__, __func__, "Update failed"); 188 | } 189 | } 190 | } else { 191 | _lastError = HTTP_UE_SERVER_NOT_REPORT_SIZE; 192 | ret = HTTP_UPDATE_FAILED; 193 | BytebeamLogger::Error(__FILE__, __func__, "Content-Length was 0 or wasn't set by Server?!"); 194 | } 195 | } else { 196 | _lastError = statusCode; 197 | ret = HTTP_UPDATE_FAILED; 198 | BytebeamLogger::Debug(__FILE__, __func__, "HTTPS Code is (%d)", statusCode); 199 | } 200 | 201 | http.stop(); 202 | return ret; 203 | } 204 | 205 | BytebeamHTTPUpdate BytebeamhttpUpdate; 206 | 207 | #endif /* #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 BYTEBEAM_ARDUINO_USE_MODEM */ -------------------------------------------------------------------------------- /src/BytebeamHTTPUpdate.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEBEAM_HTTP_UPDATE_H 2 | #define BYTEBEAM_HTTP_UPDATE_H 3 | 4 | #include "BytebeamArduinoDefines.h" 5 | 6 | #if defined(BYTEBEAM_ARDUINO_ARCH_ESP32) && defined(BYTEBEAM_ARDUINO_USE_MODEM) 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | /// note we use HTTP client errors too so we start at 100 13 | #define HTTP_UE_TOO_LESS_SPACE (-100) 14 | #define HTTP_UE_SERVER_NOT_REPORT_SIZE (-101) 15 | #define HTTP_UE_SERVER_FILE_NOT_FOUND (-102) 16 | #define HTTP_UE_SERVER_FORBIDDEN (-103) 17 | #define HTTP_UE_SERVER_WRONG_HTTP_CODE (-104) 18 | #define HTTP_UE_SERVER_FAULTY_MD5 (-105) 19 | #define HTTP_UE_BIN_VERIFY_HEADER_FAILED (-106) 20 | #define HTTP_UE_BIN_FOR_WRONG_FLASH (-107) 21 | #define HTTP_UE_NO_PARTITION (-108) 22 | 23 | enum BytebeamHTTPUpdateResult { 24 | HTTP_UPDATE_FAILED, 25 | HTTP_UPDATE_NO_UPDATES, 26 | HTTP_UPDATE_OK 27 | }; 28 | 29 | typedef BytebeamHTTPUpdateResult t_httpUpdate_return; // backward compatibility 30 | 31 | using BytebeamHTTPUpdateStartCB = std::function; 32 | using BytebeamHTTPUpdateEndCB = std::function; 33 | using BytebeamHTTPUpdateErrorCB = std::function; 34 | using BytebeamHTTPUpdateProgressCB = std::function; 35 | 36 | class BytebeamHTTPUpdate { 37 | public: 38 | // constructor 39 | BytebeamHTTPUpdate(); 40 | 41 | // destructor 42 | ~BytebeamHTTPUpdate(); 43 | 44 | // set reboot on update flag 45 | void rebootOnUpdate(bool reboot) { _rebootOnUpdate = reboot; } 46 | 47 | // set status led pin 48 | void setLedPin(int ledPin = -1, uint8_t ledOn = HIGH) { _ledPin = ledPin; _ledOn = ledOn; } 49 | 50 | // Notification callbacks 51 | void onStart(BytebeamHTTPUpdateStartCB cbOnStart) { _cbStart = cbOnStart; } 52 | void onEnd(BytebeamHTTPUpdateEndCB cbOnEnd) { _cbEnd = cbOnEnd; } 53 | void onError(BytebeamHTTPUpdateErrorCB cbOnError) { _cbError = cbOnError; } 54 | void onProgress(BytebeamHTTPUpdateProgressCB cbOnProgress) { _cbProgress = cbOnProgress; } 55 | 56 | // Error infos 57 | int getLastError(void); 58 | String getLastErrorString(void); 59 | 60 | // update the new image 61 | t_httpUpdate_return update(Client& client, const String& url, const String& currentVersion = ""); 62 | 63 | private: 64 | // mark the update 65 | bool runUpdate(Stream& in, uint32_t size); 66 | 67 | // last error 68 | int _lastError; 69 | 70 | // reboot on update flag 71 | bool _rebootOnUpdate; 72 | 73 | // status led pin 74 | int _ledPin; 75 | uint8_t _ledOn; 76 | 77 | // Callbacks 78 | BytebeamHTTPUpdateStartCB _cbStart; 79 | BytebeamHTTPUpdateEndCB _cbEnd; 80 | BytebeamHTTPUpdateErrorCB _cbError; 81 | BytebeamHTTPUpdateProgressCB _cbProgress; 82 | }; 83 | 84 | extern BytebeamHTTPUpdate BytebeamhttpUpdate; 85 | 86 | #endif /* BYTEBEAM_ARDUINO_ARCH_ESP32 && BYTEBEAM_ARDUINO_USE_MODEM */ 87 | 88 | #endif /* BYTEBEAM_HTTP_UPDATE_H */ -------------------------------------------------------------------------------- /src/BytebeamLog.cpp: -------------------------------------------------------------------------------- 1 | #include "BytebeamLog.h" 2 | #include "BytebeamArduino.h" 3 | #include "BytebeamLogger.h" 4 | 5 | void BytebeamLog::log(const char* level, const char* tag, const char* message) { 6 | // 7 | // this function will print the log in the following format 8 | // format : { level (millis) tag : message } i.e this format is adopted from the esp idf logging library 9 | // 10 | 11 | Serial.print(level[0]); 12 | Serial.print(" ("); 13 | Serial.print(millis()); 14 | Serial.print(") "); 15 | Serial.print(tag); 16 | Serial.print(" : "); 17 | Serial.print(message); 18 | } 19 | 20 | void BytebeamLog::logPrint(bytebeamLogLevel_t level, const char* tag, const char* message) { 21 | // 22 | // this function represents high level wrapper for the cloud logging 23 | // 24 | 25 | // before going ahead make sure log level is valid 26 | if(level > this->logLevel || !Serial) { 27 | return; 28 | } 29 | 30 | // get the level string 31 | const char* levelStr = bytebeamLogLevelStr[level]; 32 | 33 | // if cloud logging is disabled, print the log to serial and return :) 34 | if(!this->isCloudLoggingEnable) { 35 | log(levelStr, tag, message); 36 | return; 37 | } 38 | 39 | // if publish to cloud succedded, print the log to serial else print error log :) 40 | if(!logPublish(levelStr, tag, message)) { 41 | BytebeamLogger::Error(__FILE__, __func__, "failed to publish bytebeam log."); 42 | return; 43 | } 44 | 45 | log(levelStr, tag, message); 46 | } 47 | 48 | void BytebeamLog::logPrintln(bytebeamLogLevel_t level, const char* tag, const char* message) { 49 | // 50 | // Just call the logPrint function and give the new line to serial at the end 51 | // 52 | 53 | logPrint(level, tag, message); 54 | Serial.println(); 55 | } 56 | 57 | void BytebeamLog::logPrintf(bytebeamLogLevel_t level, const char* tag, const char* fmt, va_list args) { 58 | // 59 | // Generate the log message from the varibale arguments and call the logPrint function 60 | // 61 | 62 | int strSize = 0; 63 | int tempVar = 0; 64 | 65 | strSize = vsnprintf(NULL, 0, fmt, args) + 1; 66 | 67 | if(strSize <= 1) { 68 | BytebeamLogger::Error(__FILE__, __func__, "failed to get log message size"); 69 | return; 70 | } 71 | 72 | char* msgStr = (char*) malloc(strSize); 73 | 74 | // if memory allocation fails just log the failure to serial and return :) 75 | if(msgStr == NULL) { 76 | BytebeamLogger::Error(__FILE__, __func__, "failed to allocate the memory for log message"); 77 | return; 78 | } 79 | 80 | tempVar = vsnprintf(msgStr, strSize, fmt, args); 81 | 82 | if(tempVar >= strSize) { 83 | BytebeamLogger::Error(__FILE__, __func__, "failed to get log message"); 84 | return; 85 | } 86 | 87 | logPrint(level, tag, msgStr); 88 | } 89 | 90 | bool BytebeamLog::logPublish(const char* level, const char* tag, const char* message) { 91 | // 92 | // Publish the log info to cloud :) 93 | // 94 | 95 | static int sequence = 0; 96 | const char* payload = ""; 97 | String logMessageStr = ""; 98 | StaticJsonDocument<1024> doc; 99 | 100 | // get the current epoch millis 101 | if(!Time->getEpochMillis()) { 102 | BytebeamLogger::Error(__FILE__, __func__, "failed to get epoch millis"); 103 | return false; 104 | } 105 | 106 | sequence++; 107 | unsigned long long milliseconds = Time->nowMillis; 108 | 109 | JsonArray logMessageJsonArray = doc.to(); 110 | JsonObject logMessageJsonObj_1 = logMessageJsonArray.createNestedObject(); 111 | 112 | logMessageJsonObj_1["timestamp"] = milliseconds; 113 | logMessageJsonObj_1["sequence"] = sequence; 114 | logMessageJsonObj_1["level"] = level; 115 | logMessageJsonObj_1["tag"] = tag; 116 | logMessageJsonObj_1["message"] = message; 117 | 118 | serializeJson(logMessageJsonArray, logMessageStr); 119 | payload = logMessageStr.c_str(); 120 | 121 | return Bytebeam.publishToStream(this->logStream, payload); 122 | } 123 | 124 | BytebeamLog::BytebeamLog() { 125 | // 126 | // Initailizing all the variables with default values here 127 | // 128 | 129 | strcpy(this->logStream, "logs"); 130 | this->logLevel = BYTEBEAM_LOG_LEVEL_INFO; 131 | this->isCloudLoggingEnable = true; 132 | } 133 | 134 | BytebeamLog::~BytebeamLog() { 135 | // 136 | // Nothing much to do here, just print the log :) 137 | // 138 | 139 | BytebeamLogger::Info(__FILE__, __func__, "I am BytebeamLog::~BytebeamLog()"); 140 | } 141 | 142 | void BytebeamLog::setTimeInstance(BytebeamTime* Time) { 143 | this->Time = Time; 144 | } 145 | 146 | void BytebeamLog::enableCloudLogging() { 147 | this->isCloudLoggingEnable = true; 148 | } 149 | 150 | bool BytebeamLog::isCloudLoggingEnabled() { 151 | return this->isCloudLoggingEnable; 152 | } 153 | 154 | void BytebeamLog::disableCloudLogging() { 155 | this->isCloudLoggingEnable = false; 156 | } 157 | 158 | void BytebeamLog::setLogStream(char* stream) { 159 | int tempVar = snprintf(this->logStream, BYTEBEAM_LOG_STREAM_STR_LEN, "%s", stream); 160 | 161 | if(tempVar >= BYTEBEAM_LOG_STREAM_STR_LEN) { 162 | BytebeamLogger::Error(__FILE__, __func__, "log stream size exceeded buffer size"); 163 | return; 164 | } 165 | } 166 | 167 | char* BytebeamLog::getLogStream() { 168 | return this->logStream; 169 | } 170 | 171 | void BytebeamLog::setLogLevel(bytebeamLogLevel_t level) { 172 | this->logLevel = level; 173 | } 174 | 175 | bytebeamLogLevel_t BytebeamLog::getLogLevel() { 176 | return this->logLevel; 177 | } 178 | 179 | void BytebeamLog::logError(const char* tag, const char* message) { 180 | logPrint(BYTEBEAM_LOG_LEVEL_ERROR, tag, message); 181 | } 182 | 183 | void BytebeamLog::logErrorln(const char* tag, const char* message) { 184 | logPrintln(BYTEBEAM_LOG_LEVEL_ERROR, tag, message); 185 | } 186 | 187 | void BytebeamLog::logErrorf(const char* tag, const char* fmt, ...) { 188 | va_list args; 189 | va_start(args, fmt); 190 | logPrintf(BYTEBEAM_LOG_LEVEL_ERROR, tag, fmt, args); 191 | va_end(args); 192 | } 193 | 194 | void BytebeamLog::logWarn(const char* tag, const char* message) { 195 | logPrint(BYTEBEAM_LOG_LEVEL_WARN, tag, message); 196 | } 197 | 198 | void BytebeamLog::logWarnln(const char* tag, const char* message) { 199 | logPrintln(BYTEBEAM_LOG_LEVEL_WARN, tag, message); 200 | } 201 | 202 | void BytebeamLog::logWarnf(const char* tag, const char* fmt, ...) { 203 | va_list args; 204 | va_start(args, fmt); 205 | logPrintf(BYTEBEAM_LOG_LEVEL_WARN, tag, fmt, args); 206 | va_end(args); 207 | } 208 | 209 | void BytebeamLog::logInfo(const char* tag, const char* message) { 210 | logPrint(BYTEBEAM_LOG_LEVEL_INFO, tag, message); 211 | } 212 | 213 | void BytebeamLog::logInfoln(const char* tag, const char* message) { 214 | logPrintln(BYTEBEAM_LOG_LEVEL_INFO, tag, message); 215 | } 216 | 217 | void BytebeamLog::logInfof(const char* tag, const char* fmt, ...) { 218 | va_list args; 219 | va_start(args, fmt); 220 | logPrintf(BYTEBEAM_LOG_LEVEL_INFO, tag, fmt, args); 221 | va_end(args); 222 | } 223 | 224 | void BytebeamLog::logDebug(const char* tag, const char* message) { 225 | logPrint(BYTEBEAM_LOG_LEVEL_DEBUG, tag, message); 226 | } 227 | 228 | void BytebeamLog::logDebugln(const char* tag, const char* message) { 229 | logPrintln(BYTEBEAM_LOG_LEVEL_DEBUG, tag, message); 230 | } 231 | 232 | void BytebeamLog::logDebugf(const char* tag, const char* fmt, ...) { 233 | va_list args; 234 | va_start(args, fmt); 235 | logPrintf(BYTEBEAM_LOG_LEVEL_DEBUG, tag, fmt, args); 236 | va_end(args); 237 | } 238 | 239 | void BytebeamLog::logVerbose(const char* tag, const char* message) { 240 | logPrint(BYTEBEAM_LOG_LEVEL_VERBOSE, tag, message); 241 | } 242 | 243 | void BytebeamLog::logVerboseln(const char* tag, const char* message) { 244 | logPrintln(BYTEBEAM_LOG_LEVEL_VERBOSE, tag, message); 245 | } 246 | 247 | void BytebeamLog::logVerbosef(const char* tag, const char* fmt, ...) { 248 | va_list args; 249 | va_start(args, fmt); 250 | logPrintf(BYTEBEAM_LOG_LEVEL_VERBOSE, tag, fmt, args); 251 | va_end(args); 252 | } -------------------------------------------------------------------------------- /src/BytebeamLog.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEBEAM_LOG_H 2 | #define BYTEBEAM_LOG_H 3 | 4 | #include 5 | #include 6 | #include "BytebeamTime.h" 7 | 8 | /* This macro is used to specify the maximum length of bytebeam log stream string */ 9 | #define BYTEBEAM_LOG_STREAM_STR_LEN 20 10 | 11 | typedef enum { 12 | BYTEBEAM_LOG_LEVEL_NONE, 13 | BYTEBEAM_LOG_LEVEL_ERROR, 14 | BYTEBEAM_LOG_LEVEL_WARN, 15 | BYTEBEAM_LOG_LEVEL_INFO, 16 | BYTEBEAM_LOG_LEVEL_DEBUG, 17 | BYTEBEAM_LOG_LEVEL_VERBOSE, 18 | }bytebeamLogLevel_t; 19 | 20 | static const char* bytebeamLogLevelStr[6] = { 21 | [BYTEBEAM_LOG_LEVEL_NONE] = "None", 22 | [BYTEBEAM_LOG_LEVEL_ERROR] = "Error", 23 | [BYTEBEAM_LOG_LEVEL_WARN] = "Warn", 24 | [BYTEBEAM_LOG_LEVEL_INFO] = "Info", 25 | [BYTEBEAM_LOG_LEVEL_DEBUG] = "Debug", 26 | [BYTEBEAM_LOG_LEVEL_VERBOSE] = "Verbose" 27 | }; 28 | 29 | class BytebeamLog { 30 | public: 31 | // contructor 32 | BytebeamLog(); 33 | 34 | // destructor 35 | ~BytebeamLog(); 36 | 37 | // public functions 38 | void enableCloudLogging(); 39 | bool isCloudLoggingEnabled(); 40 | void disableCloudLogging(); 41 | 42 | void setLogStream(char* stream); 43 | char* getLogStream(); 44 | 45 | void setLogLevel(bytebeamLogLevel_t level); 46 | bytebeamLogLevel_t getLogLevel(); 47 | 48 | void logError(const char* tag, const char* message); 49 | void logErrorln(const char* tag, const char* message); 50 | void logErrorf(const char* tag, const char* fmt, ...); 51 | 52 | void logWarn(const char* tag, const char* message); 53 | void logWarnln(const char* tag, const char* message); 54 | void logWarnf(const char* tag, const char* fmt, ...); 55 | 56 | void logInfo(const char* tag, const char* message); 57 | void logInfoln(const char* tag, const char* message); 58 | void logInfof(const char* tag, const char* fmt, ...); 59 | 60 | void logDebug(const char* tag, const char* message); 61 | void logDebugln(const char* tag, const char* message); 62 | void logDebugf(const char* tag, const char* fmt, ...); 63 | 64 | void logVerbose(const char* tag, const char* message); 65 | void logVerboseln(const char* tag, const char* message); 66 | void logVerbosef(const char* tag, const char* fmt, ...); 67 | 68 | protected : 69 | void setTimeInstance(BytebeamTime* Time); 70 | 71 | private: 72 | // private functions 73 | void log(const char* level, const char* tag, const char* message); 74 | void logPrint(bytebeamLogLevel_t level, const char* tag, const char* message); 75 | void logPrintln(bytebeamLogLevel_t level, const char* tag, const char* message); 76 | void logPrintf(bytebeamLogLevel_t level, const char* tag, const char* fmt, va_list args); 77 | bool logPublish(const char* level, const char* tag, const char* message); 78 | 79 | // private variables 80 | BytebeamTime* Time; 81 | char logStream[BYTEBEAM_LOG_STREAM_STR_LEN]; 82 | bytebeamLogLevel_t logLevel; 83 | bool isCloudLoggingEnable; 84 | }; 85 | 86 | #endif /* BYTEBEAM_LOG_H */ -------------------------------------------------------------------------------- /src/BytebeamLogger.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEBEAM_LOGGER_H 2 | #define BYTEBEAM_LOGGER_H 3 | 4 | #include 5 | 6 | class BytebeamLogger { 7 | public: 8 | enum DebugLevel{ 9 | LOG_NONE, 10 | LOG_ERROR, 11 | LOG_WARN, 12 | LOG_INFO, 13 | LOG_DEBUG, 14 | LOG_TRACE 15 | }; 16 | 17 | // constructor 18 | BytebeamLogger() { /* nothing to do here*/ } 19 | 20 | // destructor 21 | ~BytebeamLogger() { /* nothing to do here */ } 22 | 23 | // public functions 24 | 25 | static void setLogLevel(DebugLevel level) { 26 | logLevel = level; 27 | } 28 | 29 | template 30 | static void None(const char* module, const char* func, const char* message, Args... args) { 31 | print(LOG_NONE, module, func, message, args...); 32 | } 33 | 34 | template 35 | static void Error(const char* module, const char* func, const char* message, Args... args) { 36 | print(LOG_ERROR, module, func, message, args...); 37 | } 38 | 39 | template 40 | static void Warn(const char* module, const char* func, const char* message, Args... args) { 41 | print(LOG_WARN, module, func, message, args...); 42 | } 43 | 44 | template 45 | static void Info(const char* module, const char* func, const char* message, Args... args) { 46 | print(LOG_INFO, module, func, message, args...); 47 | } 48 | 49 | template 50 | static void Debug(const char* module, const char* func, const char* message, Args... args) { 51 | print(LOG_DEBUG, module, func, message, args...); 52 | } 53 | 54 | template 55 | static void Trace(const char* module, const char* func, const char* message, Args... args) { 56 | print(LOG_TRACE, module, func, message, args...); 57 | } 58 | 59 | private: 60 | // private variables 61 | static DebugLevel logLevel; 62 | 63 | // private functions 64 | static void printPrefix(DebugLevel level, const char* module, const char* func) { 65 | // print the bytebeam logger prefix 66 | Serial.print("BytebeamLogger::"); 67 | 68 | // print the debug level 69 | switch (level) { 70 | case LOG_NONE : Serial.print("LOG_NONE"); break; 71 | case LOG_ERROR : Serial.print("LOG_ERROR"); break; 72 | case LOG_WARN : Serial.print("LOG_WARN"); break; 73 | case LOG_INFO : Serial.print("LOG_INFO"); break; 74 | case LOG_DEBUG : Serial.print("LOG_DEBUG"); break; 75 | case LOG_TRACE : Serial.print("LOG_TRACE"); break; 76 | 77 | default: Serial.print("UnKnown Log Level"); 78 | } 79 | 80 | // get the module string 81 | String moduleObj = String(module); 82 | 83 | int startIdx = moduleObj.lastIndexOf('\\'); 84 | 85 | //fix for linux 86 | if (startIdx == -1){ 87 | startIdx = moduleObj.lastIndexOf('/'); 88 | } 89 | 90 | startIdx += 1; 91 | 92 | int endIdx = moduleObj.lastIndexOf('.'); 93 | 94 | moduleObj = moduleObj.substring(startIdx, endIdx); 95 | 96 | const char* moduleStr = moduleObj.c_str(); 97 | 98 | // print the module name 99 | Serial.print(" ("); 100 | Serial.print(moduleStr); 101 | Serial.print(") "); 102 | 103 | // print the function name 104 | Serial.print(func); 105 | Serial.print(" : "); 106 | } 107 | 108 | template 109 | static void print(DebugLevel level, const char* module, const char* func, const char* message, Args... args) { 110 | // check the current log level and serial status 111 | if(level > logLevel || !Serial) { 112 | return; 113 | } 114 | 115 | // print prefix 116 | printPrefix(level, module, func); 117 | 118 | // print the actual message 119 | Serial.printf(message, args...); 120 | Serial.println(); 121 | } 122 | }; 123 | 124 | #endif /* BYTEBEAM_LOGGER_H */ -------------------------------------------------------------------------------- /src/BytebeamOTA.cpp: -------------------------------------------------------------------------------- 1 | #include "BytebeamOTA.h" 2 | #include "BytebeamLogger.h" 3 | 4 | #if BYTEBEAM_OTA_ENABLE 5 | 6 | static char tempOtaActionId[BYTEBEAM_OTA_ACTION_ID_STR_LEN] = ""; 7 | 8 | void BytebeamUpdateStarted() { 9 | BytebeamLogger::Warn(__FILE__, __func__, "CALLBACK: HTTP update process started"); 10 | } 11 | 12 | void BytebeamUpdateFinished() { 13 | BytebeamLogger::Warn(__FILE__, __func__, "CALLBACK: HTTP update process finished"); 14 | } 15 | 16 | void BytebeamUpdateProgress(int cur, int total) { 17 | static int loopVar = 0; 18 | static int percentOffset = 10; 19 | static int progressPercent = 0; 20 | static char* progressStatus = "Downloading"; 21 | 22 | BytebeamLogger::Warn(__FILE__, __func__, "CALLBACK: HTTP update process at %d of %d bytes", cur, total); 23 | progressPercent = (((float)cur / (float)total) * 100.00); 24 | 25 | if(progressPercent == loopVar) { 26 | BytebeamLogger::Debug(__FILE__, __func__, "progressPercent : %d", progressPercent); 27 | BytebeamLogger::Debug(__FILE__, __func__, "tempOtaActionId : %s", tempOtaActionId); 28 | 29 | // If we are done, change the status to downloaded 30 | if(progressPercent == 100) { 31 | progressStatus = "Downloaded"; 32 | } 33 | 34 | // publish the OTA progress status 35 | if(!Bytebeam.publishActionProgress(tempOtaActionId, progressPercent, progressStatus)) { 36 | BytebeamLogger::Error(__FILE__, __func__, "Failed to publish OTA progress status."); 37 | } 38 | 39 | if(loopVar == 100) { 40 | // reset the variables 41 | loopVar = 0; 42 | progressPercent = 0; 43 | } else { 44 | // mark the next progress stamp 45 | loopVar = loopVar + percentOffset; 46 | } 47 | } 48 | } 49 | 50 | void BytebeamUpdateError(int err) { 51 | BytebeamLogger::Warn(__FILE__, __func__, "CALLBACK: HTTP update fatal error code %d", err); 52 | } 53 | 54 | bool BytebeamOTA::parseOTAJson(char* otaPayloadStr, char* urlStringReturn) { 55 | StaticJsonDocument<1024> otaPayloadJson; 56 | DeserializationError err = deserializeJson(otaPayloadJson, otaPayloadStr); 57 | 58 | if(err) { 59 | BytebeamLogger::Error(__FILE__, __func__, "deserializeJson() failed : %s", err.c_str()); 60 | return false; 61 | } else { 62 | BytebeamLogger::Info(__FILE__, __func__, "deserializeJson() success"); 63 | } 64 | 65 | BytebeamLogger::Info(__FILE__, __func__, "Obtaining ota variables"); 66 | 67 | uint32_t length = otaPayloadJson["content-length"]; 68 | bool status = otaPayloadJson["status"]; 69 | const char* url = otaPayloadJson["url"]; 70 | const char* version = otaPayloadJson["version"]; 71 | 72 | const char* argsName[] = {"url", "version"}; 73 | const char* argsStr[] = {url, version}; 74 | int numArg = sizeof(argsStr)/sizeof(argsStr[0]); 75 | 76 | int argIterator = 0; 77 | for(argIterator = 0; argIterator < numArg; argIterator++) { 78 | if(argsStr[argIterator] == NULL) { 79 | BytebeamLogger::Error(__FILE__, __func__, "- failed to obtain %s", argsName[argIterator]); 80 | return false; 81 | } 82 | } 83 | BytebeamLogger::Info(__FILE__, __func__, "- obtain ota variables"); 84 | 85 | BytebeamLogger::Debug(__FILE__, __func__, "length : %d", length); 86 | BytebeamLogger::Debug(__FILE__, __func__, "status : %d", status); 87 | BytebeamLogger::Debug(__FILE__, __func__, "url : %s", url); 88 | BytebeamLogger::Debug(__FILE__, __func__, "version : %s", version); 89 | 90 | int maxLen = BYTEBEAM_OTA_URL_STR_LEN; 91 | int tempVar = snprintf(urlStringReturn, maxLen, "%s", url); 92 | 93 | if(tempVar >= maxLen) { 94 | BytebeamLogger::Error(__FILE__, __func__, "Firmware upgrade url size exceeded buffer size"); 95 | return false; 96 | } 97 | 98 | BytebeamLogger::Info(__FILE__, __func__, "Constructed url is %s", urlStringReturn); 99 | 100 | return true; 101 | } 102 | 103 | bool BytebeamOTA::performOTA(char* actionId, char* otaUrl) { 104 | int maxLen, tempVar; 105 | BytebeamLogger::Warn(__FILE__, __func__, "Performing OTA..."); 106 | 107 | // save the OTA information in RAM 108 | this->otaUpdateFlag = true; 109 | strcpy(this->otaActionId, actionId); 110 | strcpy(tempOtaActionId, this->otaActionId); 111 | 112 | // disable the auto reboot, we will manually reboot after saving some information 113 | this->BytebeamUpdate.rebootOnUpdate(false); 114 | 115 | // set the status led pin 116 | this->BytebeamUpdate.setLedPin(BYTEBEAM_OTA_BUILT_IN_LED, LOW); 117 | 118 | // set the update callbacks 119 | this->BytebeamUpdate.onStart(BytebeamUpdateStarted); 120 | this->BytebeamUpdate.onEnd(BytebeamUpdateFinished); 121 | this->BytebeamUpdate.onProgress(BytebeamUpdateProgress); 122 | this->BytebeamUpdate.onError(BytebeamUpdateError); 123 | 124 | // start the update process 125 | t_httpUpdate_return ret = this->BytebeamUpdate.update(this->secureOTAClient, otaUrl); 126 | 127 | switch (ret) { 128 | case HTTP_UPDATE_FAILED: 129 | maxLen = BYTEBEAM_OTA_ERROR_STR_LEN; 130 | tempVar = snprintf(this->otaError, maxLen, "Error (%d): %s", this->BytebeamUpdate.getLastError(), this->BytebeamUpdate.getLastErrorString().c_str()); 131 | 132 | if(tempVar >= maxLen) { 133 | BytebeamLogger::Error(__FILE__, __func__, "OTA error size exceeded buffer size"); 134 | } 135 | 136 | BytebeamLogger::Info(__FILE__, __func__, "HTTP_UPDATE_FAILED %s", this->otaError); 137 | break; 138 | 139 | case HTTP_UPDATE_NO_UPDATES: 140 | BytebeamLogger::Info(__FILE__, __func__, "HTTP_UPDATE_NO_UPDATES"); 141 | break; 142 | 143 | case HTTP_UPDATE_OK: 144 | BytebeamLogger::Info(__FILE__, __func__, "HTTP_UPDATE_OK"); 145 | break; 146 | } 147 | 148 | if(ret != HTTP_UPDATE_OK) { 149 | return false; 150 | } else { 151 | return true; 152 | } 153 | } 154 | 155 | BytebeamOTA::BytebeamOTA() 156 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 157 | : secureOTAClient(&gsmOTAClient) 158 | #endif 159 | { 160 | // 161 | // Initailizing all the variables with default values here 162 | // 163 | 164 | this->otaUpdateFlag = false; 165 | memset(this->otaActionId, 0x00, BYTEBEAM_OTA_ACTION_ID_STR_LEN); 166 | memset(this->otaError, 0x00, BYTEBEAM_OTA_ERROR_STR_LEN); 167 | } 168 | 169 | BytebeamOTA::~BytebeamOTA() { 170 | // 171 | // Nothing much to do here, just print the log to serial :) 172 | // 173 | 174 | BytebeamLogger::Info(__FILE__, __func__, "I am BytebeamOTA::~BytebeamOTA()"); 175 | } 176 | 177 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 178 | void BytebeamOTA::setupGsmClient(TinyGsm* modem) { 179 | // initiaize the gsm client with the modem instance 180 | this->gsmOTAClient.init(modem, 1); 181 | } 182 | #endif 183 | 184 | void BytebeamOTA::saveOTAInfo() { 185 | 186 | /* Non Volatile Storage are architecture specific, so we need to provide the implementation for storing 187 | * the OTA information to storage here based on the arcitecture. 188 | */ 189 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 190 | Preferences preferences; 191 | 192 | preferences.begin("OTAInfo"); 193 | preferences.putBool("OTAUpdateFlag", this->otaUpdateFlag); 194 | preferences.putString("OTAActionId", this->otaActionId); 195 | preferences.end(); 196 | #endif 197 | 198 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP8266 199 | int add = 0; 200 | int size = 512; 201 | uint8_t value = 0; 202 | 203 | EEPROM.begin(size); 204 | 205 | value = this->otaUpdateFlag; 206 | EEPROM.write(add, value); 207 | 208 | add++; 209 | 210 | for(int i=0; iotaActionId[i]; 212 | EEPROM.write(add, value); 213 | add++; 214 | } 215 | 216 | // save the changes made to the EEPROM 217 | EEPROM.commit(); 218 | 219 | EEPROM.end(); 220 | #endif 221 | 222 | BytebeamLogger::Info(__FILE__, __func__, "NVS: Saving OTA Information"); 223 | } 224 | 225 | void BytebeamOTA::retrieveOTAInfo() { 226 | 227 | /* Non Volatile Storage are architecture specific, so we need to provide the implementation for retrieving 228 | * the OTA information from storage here based on the arcitecture. 229 | */ 230 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 231 | Preferences preferences; 232 | 233 | preferences.begin("OTAInfo"); 234 | this->otaUpdateFlag = preferences.getBool("OTAUpdateFlag"); 235 | preferences.getString("OTAActionId", this->otaActionId, BYTEBEAM_OTA_ACTION_ID_STR_LEN); 236 | preferences.end(); 237 | #endif 238 | 239 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP8266 240 | int add = 0; 241 | int size = 512; 242 | uint8_t value = 0; 243 | 244 | EEPROM.begin(size); 245 | 246 | value = EEPROM.read(add); 247 | this->otaUpdateFlag = value; 248 | 249 | add++; 250 | 251 | for(int i=0; iotaActionId[i] = value; 254 | add++; 255 | } 256 | 257 | EEPROM.end(); 258 | #endif 259 | 260 | BytebeamLogger::Info(__FILE__, __func__, "NVS: Retrieving OTA Information"); 261 | } 262 | 263 | void BytebeamOTA::clearOTAInfoFromFlash() { 264 | 265 | /* Non Volatile Storage are architecture specific, so we need to provide the implementation for clearing 266 | * the OTA information from storage here based on the arcitecture. 267 | */ 268 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 269 | Preferences preferences; 270 | 271 | preferences.begin("OTAInfo"); 272 | preferences.clear(); 273 | preferences.end(); 274 | #endif 275 | 276 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP8266 277 | int add = 0; 278 | int size = 512; 279 | uint8_t value = 0; 280 | 281 | EEPROM.begin(size); 282 | 283 | for(int i=0; iotaUpdateFlag = false; 303 | memset(this->otaActionId, 0x00, BYTEBEAM_OTA_ACTION_ID_STR_LEN); 304 | memset(this->otaError, 0x00, BYTEBEAM_OTA_ERROR_STR_LEN); 305 | 306 | BytebeamLogger::Info(__FILE__, __func__, "NVS: Clearing OTA Information From RAM"); 307 | } 308 | 309 | void BytebeamOTA::setupSecureOTAClient(const void* caCert, const void* clientCert, const void* clientKey) { 310 | // 311 | // Setting up the secure OTA client 312 | // 313 | 314 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 315 | this->secureOTAClient.setCACert((const char*)caCert); 316 | this->secureOTAClient.setCertificate((const char*)clientCert); 317 | this->secureOTAClient.setPrivateKey((const char*)clientKey); 318 | #endif 319 | 320 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP8266 321 | this->secureOTAClient.setBufferSizes(2048, 2048); 322 | this->secureOTAClient.setTrustAnchors((const BearSSL::X509List*)caCert); 323 | this->secureOTAClient.setClientRSACert((const BearSSL::X509List*)clientCert, (const BearSSL::PrivateKey*)clientKey); 324 | #endif 325 | } 326 | 327 | void BytebeamOTA::clearSecureOTAClient() { 328 | // 329 | // Clearing up the secure OTA client 330 | // 331 | 332 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 333 | this->secureOTAClient.setCACert(NULL); 334 | this->secureOTAClient.setCertificate(NULL); 335 | this->secureOTAClient.setPrivateKey(NULL); 336 | #endif 337 | 338 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP8266 339 | this->secureOTAClient.setBufferSizes(0, 0); 340 | this->secureOTAClient.setTrustAnchors(NULL); 341 | this->secureOTAClient.setClientRSACert(NULL, NULL); 342 | #endif 343 | } 344 | 345 | bool BytebeamOTA::updateFirmware(char* otaPayloadStr, char* actionId) { 346 | char constructedUrl[BYTEBEAM_OTA_URL_STR_LEN] = { 0 }; 347 | 348 | if(!parseOTAJson(otaPayloadStr, constructedUrl)) { 349 | BytebeamLogger::Error(__FILE__, __func__, "OTA failed, error while parsing the OTA json"); 350 | return false; 351 | } 352 | 353 | if(!performOTA(actionId, constructedUrl)) { 354 | BytebeamLogger::Error(__FILE__, __func__, "OTA failed, error while performing HTTPS OTA"); 355 | return false; 356 | } 357 | 358 | return true; 359 | } 360 | 361 | #endif /* BYTEBEAM_OTA_ENABLE */ -------------------------------------------------------------------------------- /src/BytebeamOTA.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEBEAM_OTA_H 2 | #define BYTEBEAM_OTA_H 3 | 4 | #include 5 | #include 6 | #include "BytebeamArduino.h" 7 | #include "BytebeamArduinoDefines.h" 8 | 9 | /* This macro is used to specify the maximum length of bytebeam OTA url string */ 10 | #define BYTEBEAM_OTA_URL_STR_LEN 200 11 | 12 | /* This macro is used to specify the maximum length of bytebeam OTA action id string */ 13 | #define BYTEBEAM_OTA_ACTION_ID_STR_LEN 20 14 | 15 | /* This macro is used to specify the maximum length of the bytebeam OTA error string */ 16 | #define BYTEBEAM_OTA_ERROR_STR_LEN 200 17 | 18 | /* This macro is used to define the on-board led, we will be using this while HTTP OTA to show the process */ 19 | #define BYTEBEAM_OTA_BUILT_IN_LED 2 20 | 21 | class BytebeamOTA { 22 | public: 23 | // constructor 24 | BytebeamOTA(); 25 | 26 | // destructor 27 | ~BytebeamOTA(); 28 | 29 | // public functions 30 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 31 | void setupGsmClient(TinyGsm* modem); 32 | #endif 33 | 34 | void saveOTAInfo(); 35 | void retrieveOTAInfo(); 36 | void clearOTAInfoFromFlash(); 37 | void clearOTAInfoFromRAM(); 38 | void setupSecureOTAClient(const void* caCert, const void* clientCert, const void* clientKey); 39 | void clearSecureOTAClient(); 40 | bool updateFirmware(char* otaPayloadStr, char* actionId); 41 | 42 | // public variables 43 | bool otaUpdateFlag; 44 | char otaActionId[BYTEBEAM_OTA_ACTION_ID_STR_LEN]; 45 | char otaError[BYTEBEAM_OTA_ERROR_STR_LEN]; 46 | private: 47 | // private functions 48 | bool parseOTAJson(char* otaPayloadStr, char* urlStringReturn); 49 | bool performOTA(char* actionId, char* otaUrl); 50 | 51 | // private variables 52 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP32 53 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 54 | WiFiClientSecure secureOTAClient; 55 | HTTPUpdate& BytebeamUpdate = httpUpdate; 56 | #endif 57 | 58 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 59 | TinyGsmClient gsmOTAClient; 60 | SSLClient secureOTAClient; 61 | BytebeamHTTPUpdate& BytebeamUpdate = BytebeamhttpUpdate; 62 | #endif 63 | #endif 64 | 65 | #ifdef BYTEBEAM_ARDUINO_ARCH_ESP8266 66 | BearSSL::WiFiClientSecure secureOTAClient; 67 | ESP8266HTTPUpdate& BytebeamUpdate = ESPhttpUpdate; 68 | #endif 69 | }; 70 | 71 | #endif /* BYTEBEAM_OTA_H */ -------------------------------------------------------------------------------- /src/BytebeamTime.cpp: -------------------------------------------------------------------------------- 1 | #include "BytebeamTime.h" 2 | #include "BytebeamLogger.h" 3 | 4 | BytebeamTime::BytebeamTime() 5 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 6 | : timeClient(udpClient) 7 | #endif 8 | { 9 | // 10 | // Initailizing all the variables with default values here 11 | // 12 | 13 | this->beginMillis = 0; 14 | this->prevMillis = 0; 15 | this->nowMillis = 0; 16 | this->endMillis = 0; 17 | this->durationMillis = 0; 18 | } 19 | 20 | BytebeamTime::~BytebeamTime() { 21 | // 22 | // Nothing much to do here, just print the log :) 23 | // 24 | 25 | BytebeamLogger::Info(__FILE__, __func__, "I am BytebeamTime::~BytebeamTime()"); 26 | } 27 | 28 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 29 | void BytebeamTime::setModemInstance(TinyGsm* modem) { 30 | this->modem = modem; 31 | } 32 | #endif 33 | 34 | bool BytebeamTime::begin() { 35 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 36 | // begin the time client 37 | timeClient.begin(); 38 | 39 | // set the gmt time offset ( +5:30h = 19800s ) 40 | // fix : commenting as of now as we are getting the correct time stamp 41 | // timeClient.setTimeOffset(19800); 42 | 43 | // set the ntp server update interval to 30s 44 | timeClient.setUpdateInterval(30); 45 | #endif 46 | 47 | // get the epoch millis 48 | if(!getEpochMillis()) { 49 | BytebeamLogger::Error(__FILE__, __func__, "failed to get epoch millis"); 50 | return false; 51 | } 52 | 53 | // save the begin epoch millis 54 | this->beginMillis = this->nowMillis; 55 | 56 | BytebeamLogger::Debug(__FILE__, __func__, "beginMillis : %llu", this->beginMillis); 57 | 58 | // reset the durationMillis i.e we will start a new session 59 | this->durationMillis = 0; 60 | 61 | // log begin information to serial :) 62 | BytebeamLogger::Info(__FILE__, __func__, "TIME : Client begin! "); 63 | 64 | return true; 65 | } 66 | 67 | bool BytebeamTime::getEpochMillis() { 68 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 69 | // update the time client 70 | timeClient.update(); 71 | 72 | // get the epcoh time from the server 73 | unsigned long time = timeClient.getEpochTime(); 74 | #endif 75 | 76 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 77 | // will give the time in this format "YY/MM/DD,HH:MM:SS" 78 | String dateTime = this->modem->getGSMDateTime(DATE_FULL); 79 | 80 | BytebeamLogger::Debug(__FILE__, __func__, "dateTime : %s", dateTime.c_str()); 81 | 82 | struct tm tm; 83 | memset(&tm, 0, sizeof(tm)); 84 | 85 | tm.tm_year = 2000 + dateTime.substring(0,2).toInt() - 1900; 86 | tm.tm_mon = dateTime.substring(3,5).toInt() - 1; 87 | tm.tm_mday = dateTime.substring(6,8).toInt(); 88 | 89 | tm.tm_hour = dateTime.substring(9,11).toInt(); 90 | tm.tm_min = dateTime.substring(12,14).toInt(); 91 | tm.tm_sec = dateTime.substring(15,17).toInt(); 92 | 93 | time_t time; 94 | time = mktime(&tm) - 19800; // GMT +5:30h 95 | #endif 96 | 97 | // calculate epoch millis 98 | unsigned long long timeMillis = ((unsigned long long)time * 1000) + (millis() % 1000); 99 | 100 | // save the epoch millis 101 | this->nowMillis = timeMillis; 102 | 103 | BytebeamLogger::Debug(__FILE__, __func__, "prevMillis : %llu", this->prevMillis); 104 | BytebeamLogger::Debug(__FILE__, __func__, "nowMillis : %llu", this->nowMillis); 105 | 106 | unsigned long long threshold = 1000; 107 | 108 | // make sure prev epoch millis shouldn't be greater than the now epoch millis 109 | if(this->prevMillis > this->nowMillis) { 110 | // fix : taking threshold to over come the override that happens when new millis cross high in MSB 111 | if(this->prevMillis > this->nowMillis + threshold) { 112 | BytebeamLogger::Error(__FILE__, __func__, "failed to obtain time"); 113 | return false; 114 | } else { 115 | this->nowMillis += threshold; 116 | BytebeamLogger::Debug(__FILE__, __func__, "threshold added to epoch millis"); 117 | } 118 | } 119 | 120 | // update the prev epoch millis 121 | this->prevMillis = this->nowMillis; 122 | 123 | return true; 124 | } 125 | 126 | bool BytebeamTime::end() { 127 | // get the epoch millis 128 | if(!getEpochMillis()) { 129 | BytebeamLogger::Error(__FILE__, __func__, "failed to get epoch millis"); 130 | return false; 131 | } 132 | 133 | // save the end epoch millis 134 | this->endMillis = this->nowMillis; 135 | 136 | // calculate the duration epoch millis 137 | this->durationMillis = this->endMillis - this->beginMillis; 138 | 139 | BytebeamLogger::Debug(__FILE__, __func__, "endMillis : %llu", this->endMillis); 140 | BytebeamLogger::Debug(__FILE__, __func__, "durationMillis : %llu", this->durationMillis); 141 | 142 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 143 | // end the time client 144 | timeClient.end(); 145 | #endif 146 | 147 | // reset the time variables except durationMillis i.e we need to pump up the duration 148 | this->beginMillis = 0; 149 | this->prevMillis = 0; 150 | this->nowMillis = 0; 151 | this->endMillis = 0; 152 | 153 | // log end information to serial :) 154 | BytebeamLogger::Info(__FILE__, __func__, "TIME : Client end! "); 155 | 156 | return true; 157 | } -------------------------------------------------------------------------------- /src/BytebeamTime.h: -------------------------------------------------------------------------------- 1 | #ifndef BYTEBEAM_TIME_H 2 | #define BYTEBEAM_TIME_H 3 | 4 | #include "BytebeamArduinoDefines.h" 5 | 6 | class BytebeamTime { 7 | public: 8 | // contructor 9 | BytebeamTime(); 10 | 11 | // destructor 12 | ~BytebeamTime(); 13 | 14 | // public functions 15 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 16 | void setModemInstance(TinyGsm* modem); 17 | #endif 18 | 19 | bool begin(); 20 | bool getEpochMillis(); 21 | bool end(); 22 | 23 | // public variables 24 | unsigned long long beginMillis; 25 | unsigned long long prevMillis; 26 | unsigned long long nowMillis; 27 | unsigned long long endMillis; 28 | unsigned long long durationMillis; 29 | 30 | private: 31 | // private variables 32 | #ifdef BYTEBEAM_ARDUINO_USE_WIFI 33 | WiFiUDP udpClient; 34 | NTPClient timeClient; 35 | #endif 36 | 37 | #ifdef BYTEBEAM_ARDUINO_USE_MODEM 38 | TinyGsm* modem; 39 | #endif 40 | }; 41 | 42 | #endif /* BYTEBEAM_TIME_H */ --------------------------------------------------------------------------------