├── .clang-format
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature-request.md
└── workflows
│ ├── stale.yml
│ └── sync_issues.yml
├── .gitignore
├── .vscode
├── extensions.json
└── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── docs
├── 01-Quick-Start
│ ├── K1100-Quick-Start-Guide(old_version).md
│ └── README.md
├── 02-Microsoft-Azure-IoT
│ ├── 1-Connect SenseCAP to Azure IoT Central via Node-RED (SenseCAP)
│ │ └── README.md
│ ├── 1-Connect Wio Terminal to Microsoft Azure IoT Central (WiFi)
│ │ └── README.md
│ ├── 1-Connect the Wio Terminal to Microsoft Azure IoT Hub (WiFi)
│ │ └── README.md
│ ├── 1-Helium integrate into Azure IoT Hub
│ │ └── README.md
│ ├── 2-Develop in Microsoft Azure IoT Central
│ │ └── README.md
│ ├── 3-Configure Web APP Visualization
│ │ └── README.md
│ └── 3-Microsoft Azure IoT Data visualisation with Power BI
│ │ └── README.md
├── 03-SenseCAP
│ ├── 1-SenseCAP Console with Node-RED Quick Start
│ │ └── README.md
│ ├── 2-Connect SenseCAP to Azure IoT Central via Node-RED
│ │ └── README.md
│ ├── 2-Connect SenseCAP to InfluxDB via Node-RED
│ │ └── README.md
│ └── 2-Connect SenseCAP to Power BI via Node-RED
│ │ └── README.md
├── 04-Sensor-Helium-TTN-Arduino-Programme
│ ├── Grove Soil Moisture Sensor
│ │ └── README.md
│ ├── Grove Temp&Humi Sensor (SHT40)
│ │ └── README.md
│ ├── Grove VOC and eCO2 Gas Sensor (SGP30)
│ │ └── README.md
│ ├── Grove Vision AI Module
│ │ └── README.md
│ ├── Wio Terminal IMU Sensor
│ │ └── README.md
│ └── Wio Terminal Light Sensor
│ │ └── README.md
├── 05-Helium
│ ├── 0-Helium Introduction
│ │ └── README.md
│ ├── 1-Connect to Helium
│ │ └── README.md
│ ├── 2-Connect AWS IOT Core via Helium
│ │ └── README.md
│ ├── 2-Integrate into Azure IoT Hub
│ │ └── README.md
│ ├── 2-Integrate into Google Sheets via Helium
│ │ └── README.md
│ └── 3-Configure Web APP Visualization
│ │ └── README.md
├── 06-TTN
│ ├── 0-TTN Introduction
│ │ └── README.md
│ └── 1-Connect to TTN
│ │ └── README.md
├── 07-WiFi
│ ├── 0-Advanced Wi-Fi Usage
│ │ └── README.md
│ ├── 1-Connect Wio Terminal to Google Cloud IoT Core
│ │ └── README.md
│ ├── 1-Connect Wio Terminal to Microsoft Azure IoT Central
│ │ └── README.md
│ ├── 1-Connect the Wio Terminal to Microsoft Azure IoT Hub
│ │ └── README.md
│ ├── 1-Quick Start to Using Blynk
│ │ └── README.md
│ ├── 1-Quickly Start with Ubidots
│ │ └── README.md
│ └── 2-Develop with Ubidots
│ │ └── README.md
├── 08-Cloud
│ ├── Connect AWS IOT Core via Helium (Helium)
│ │ └── README.md
│ ├── Connect Wio Terminal to Google Cloud IoT Core (WiFi)
│ │ └── README.md
│ ├── Connect Wio Terminal to Microsoft Azure IoT Central (WiFi)
│ │ └── README.md
│ ├── Connect the Wio Terminal to Microsoft Azure IoT Hub (WiFi)
│ │ └── README.md
│ ├── Development with Ubidots
│ │ └── README.md
│ ├── Integrate into Azure IoT Hub (Helium)
│ │ └── README.md
│ ├── Quick Start to Using Blynk (WiFi)
│ │ └── README.md
│ └── Quickly Start with Ubidots (WiFi)
│ │ └── README.md
├── 09-TinyML
│ ├── Develop Edge Impulse application to cloud via Helium (built-in sensor)
│ │ └── README.md
│ ├── Train and Deploy Your Own AI Model Into Grove - Vision AI
│ │ └── README.md
│ └── Wio Terminal Edge Impulse Getting Started (built-in sensor)
│ │ └── README.md
├── 10-Project
│ └── Soil moisture monitoring alarm system
│ │ └── README.md
└── README.md
├── examples
├── Network
│ ├── LoRaWAN
│ │ ├── Binding-devices
│ │ │ └── Binding-devices.ino
│ │ ├── Frequency-select
│ │ │ └── Frequency-select.ino
│ │ ├── Network-Select
│ │ │ └── Network-Select.ino
│ │ └── connect-success
│ │ │ └── connect-success.ino
│ └── WiFi
│ │ ├── connect-success
│ │ └── connect-success.ino
│ │ └── wifi-select
│ │ └── wifi-select.ino
├── PAGE_TEMPLE
│ └── PAGE_TEMPLE.ino
├── PAGE_WELCOME
│ └── PAGE_WELCOME.ino
├── PAGE_process_tinyml
│ ├── Free_Fonts.h
│ └── PAGE_process_tinyml.ino
├── Process
│ ├── PAGE_tf
│ │ ├── PAGE_tf.ino
│ │ ├── switch.cpp
│ │ └── switch_ui.h
│ └── Process_main
│ │ ├── Free_Fonts.h
│ │ ├── Process_main.ino
│ │ └── README.md
└── Sense
│ ├── Auto-detect
│ └── Auto-detect.ino
│ ├── Built-in
│ └── Built-in.ino
│ └── Line-chart
│ ├── Free_Fonts.h
│ └── Line-chart.ino
├── include
├── AzureDpsClient.h
├── ButtonThread.h
├── LoRaThread.h
├── SDThread.h
├── SamplerThread.h
├── Signature.h
├── SysConfig.h
├── WiFiThread.h
├── sensor.h
├── ui.h
└── utils.h
├── platformio.ini
├── src
├── AzureDpsClient.cpp
├── ButtonThread.cpp
├── FreeRTOSMemory.cpp
├── Free_Fonts.h
├── LoRaThread.cpp
├── SDThread.cpp
├── SamplerThread.cpp
├── Signature.cpp
├── SysConfig.cpp
├── WiFiThread.cpp
├── cm_backtrace
│ ├── cm_backtrace.c
│ ├── cm_backtrace.h
│ ├── cmb_cfg.h
│ ├── cmb_def.h
│ └── fault_handler
│ │ └── gcc
│ │ └── cmb_fault.S
├── main.cpp
├── sensor.cpp
├── sensors
│ ├── FakeSensor.cpp
│ ├── FakeSensor.h
│ ├── LIS3DHTRSensor.cpp
│ ├── LIS3DHTRSensor.h
│ ├── SensorsUtils.cpp
│ ├── SensorsUtils.h
│ ├── buildin_light_sensor.cpp
│ ├── buildin_light_sensor.h
│ ├── buildin_mic.cpp
│ ├── buildin_mic.h
│ ├── grove_sgp30_sensor.cpp
│ ├── grove_sgp30_sensor.h
│ ├── grove_sht4x_sensor.cpp
│ ├── grove_sht4x_sensor.h
│ ├── grove_soil_sensor.cpp
│ ├── grove_soil_sensor.h
│ ├── grove_visionai_sensor.cpp
│ ├── grove_visionai_sensor.h
│ ├── grove_vl53l0x_sensor.cpp
│ └── grove_vl53l0x_sensor.h
└── ui.cpp
└── tools
└── K1100-decoder.js
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | # BasedOnStyle: LLVM
4 | AccessModifierOffset: -2
5 | AlignAfterOpenBracket: Align
6 | AlignArrayOfStructures: None
7 | AlignConsecutiveMacros: None
8 | AlignConsecutiveAssignments: true
9 | AlignConsecutiveBitFields: true
10 | AlignConsecutiveDeclarations: true
11 | AlignEscapedNewlines: Right
12 | AlignOperands: Align
13 | AlignTrailingComments: true
14 | AllowAllArgumentsOnNextLine: true
15 | AllowAllParametersOfDeclarationOnNextLine: true
16 | AllowShortEnumsOnASingleLine: true
17 | AllowShortBlocksOnASingleLine: Never
18 | AllowShortCaseLabelsOnASingleLine: false
19 | AllowShortFunctionsOnASingleLine: false
20 | AllowShortLambdasOnASingleLine: All
21 | AllowShortIfStatementsOnASingleLine: Never
22 | AllowShortLoopsOnASingleLine: false
23 | AlwaysBreakAfterDefinitionReturnType: None
24 | AlwaysBreakAfterReturnType: None
25 | AlwaysBreakBeforeMultilineStrings: false
26 | AlwaysBreakTemplateDeclarations: MultiLine
27 | AttributeMacros:
28 | - __capability
29 | BinPackArguments: true
30 | BinPackParameters: true
31 | BraceWrapping:
32 | AfterCaseLabel: false
33 | AfterClass: false
34 | AfterControlStatement: Never
35 | AfterEnum: false
36 | AfterFunction: false
37 | AfterNamespace: false
38 | AfterObjCDeclaration: false
39 | AfterStruct: false
40 | AfterUnion: false
41 | AfterExternBlock: false
42 | BeforeCatch: false
43 | BeforeElse: false
44 | BeforeLambdaBody: false
45 | BeforeWhile: false
46 | IndentBraces: false
47 | SplitEmptyFunction: true
48 | SplitEmptyRecord: true
49 | SplitEmptyNamespace: true
50 | BreakBeforeBinaryOperators: None
51 | BreakBeforeConceptDeclarations: true
52 | BreakBeforeBraces: Attach
53 | BreakBeforeInheritanceComma: false
54 | BreakInheritanceList: BeforeColon
55 | BreakBeforeTernaryOperators: true
56 | BreakConstructorInitializersBeforeComma: false
57 | BreakConstructorInitializers: BeforeColon
58 | BreakAfterJavaFieldAnnotations: false
59 | BreakStringLiterals: true
60 | ColumnLimit: 100
61 | CommentPragmas: '^ IWYU pragma:'
62 | QualifierAlignment: Leave
63 | CompactNamespaces: false
64 | ConstructorInitializerIndentWidth: 4
65 | ContinuationIndentWidth: 4
66 | Cpp11BracedListStyle: true
67 | DeriveLineEnding: true
68 | DerivePointerAlignment: false
69 | DisableFormat: false
70 | EmptyLineAfterAccessModifier: Never
71 | EmptyLineBeforeAccessModifier: LogicalBlock
72 | ExperimentalAutoDetectBinPacking: false
73 | PackConstructorInitializers: BinPack
74 | BasedOnStyle: ''
75 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
76 | AllowAllConstructorInitializersOnNextLine: true
77 | FixNamespaceComments: true
78 | ForEachMacros:
79 | - foreach
80 | - Q_FOREACH
81 | - BOOST_FOREACH
82 | IfMacros:
83 | - KJ_IF_MAYBE
84 | IncludeBlocks: Preserve
85 | IncludeCategories:
86 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
87 | Priority: 2
88 | SortPriority: 0
89 | CaseSensitive: false
90 | - Regex: '^(<|"(gtest|gmock|isl|json)/)'
91 | Priority: 3
92 | SortPriority: 0
93 | CaseSensitive: false
94 | - Regex: '.*'
95 | Priority: 1
96 | SortPriority: 0
97 | CaseSensitive: false
98 | IncludeIsMainRegex: '(Test)?$'
99 | IncludeIsMainSourceRegex: ''
100 | IndentAccessModifiers: false
101 | IndentCaseLabels: false
102 | IndentCaseBlocks: false
103 | IndentGotoLabels: true
104 | IndentPPDirectives: None
105 | IndentExternBlock: AfterExternBlock
106 | IndentRequires: false
107 | IndentWidth: 4
108 | IndentWrappedFunctionNames: false
109 | InsertTrailingCommas: None
110 | JavaScriptQuotes: Leave
111 | JavaScriptWrapImports: true
112 | KeepEmptyLinesAtTheStartOfBlocks: true
113 | LambdaBodyIndentation: Signature
114 | MacroBlockBegin: ''
115 | MacroBlockEnd: ''
116 | MaxEmptyLinesToKeep: 1
117 | NamespaceIndentation: None
118 | ObjCBinPackProtocolList: Auto
119 | ObjCBlockIndentWidth: 2
120 | ObjCBreakBeforeNestedBlockParam: true
121 | ObjCSpaceAfterProperty: false
122 | ObjCSpaceBeforeProtocolList: true
123 | PenaltyBreakAssignment: 2
124 | PenaltyBreakBeforeFirstCallParameter: 19
125 | PenaltyBreakComment: 300
126 | PenaltyBreakFirstLessLess: 120
127 | PenaltyBreakOpenParenthesis: 0
128 | PenaltyBreakString: 1000
129 | PenaltyBreakTemplateDeclaration: 10
130 | PenaltyExcessCharacter: 1000000
131 | PenaltyReturnTypeOnItsOwnLine: 60
132 | PenaltyIndentedWhitespace: 0
133 | PointerAlignment: Right
134 | PPIndentWidth: -1
135 | ReferenceAlignment: Pointer
136 | ReflowComments: true
137 | RemoveBracesLLVM: false
138 | SeparateDefinitionBlocks: Leave
139 | ShortNamespaceLines: 1
140 | SortIncludes: CaseSensitive
141 | SortJavaStaticImport: Before
142 | SortUsingDeclarations: true
143 | SpaceAfterCStyleCast: false
144 | SpaceAfterLogicalNot: false
145 | SpaceAfterTemplateKeyword: true
146 | SpaceBeforeAssignmentOperators: true
147 | SpaceBeforeCaseColon: false
148 | SpaceBeforeCpp11BracedList: false
149 | SpaceBeforeCtorInitializerColon: true
150 | SpaceBeforeInheritanceColon: true
151 | SpaceBeforeParens: ControlStatements
152 | SpaceBeforeParensOptions:
153 | AfterControlStatements: true
154 | AfterForeachMacros: true
155 | AfterFunctionDefinitionName: false
156 | AfterFunctionDeclarationName: false
157 | AfterIfMacros: true
158 | AfterOverloadedOperator: false
159 | BeforeNonEmptyParentheses: false
160 | SpaceAroundPointerQualifiers: Default
161 | SpaceBeforeRangeBasedForLoopColon: true
162 | SpaceInEmptyBlock: false
163 | SpaceInEmptyParentheses: false
164 | SpacesBeforeTrailingComments: 1
165 | SpacesInAngles: Never
166 | SpacesInConditionalStatement: false
167 | SpacesInContainerLiterals: true
168 | SpacesInCStyleCastParentheses: false
169 | SpacesInLineCommentPrefix:
170 | Minimum: 1
171 | Maximum: -1
172 | SpacesInParentheses: false
173 | SpacesInSquareBrackets: false
174 | SpaceBeforeSquareBrackets: false
175 | BitFieldColonSpacing: Both
176 | Standard: Latest
177 | StatementAttributeLikeMacros:
178 | - Q_EMIT
179 | StatementMacros:
180 | - Q_UNUSED
181 | - QT_REQUIRE_VERSION
182 | TabWidth: 8
183 | UseCRLF: false
184 | UseTab: Never
185 | WhitespaceSensitiveMacros:
186 | - STRINGIZE
187 | - PP_STRINGIZE
188 | - BOOST_PP_STRINGIZE
189 | - NS_SWIFT_NAME
190 | - CF_SWIFT_NAME
191 | ...
192 |
193 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest a feature/function that you want to have for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: 'Close stale issues and PRs'
2 |
3 | on:
4 | workflow_dispatch:
5 | schedule:
6 | - cron: '0 4 * * *'
7 |
8 | jobs:
9 | stale:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v4
15 |
16 | - name: Checkout script repository
17 | uses: actions/checkout@v4
18 | with:
19 | repository: Seeed-Studio/sync-github-all-issues
20 | path: ci
21 |
22 | - name: Run script
23 | run: ./ci/tools/stale.sh
24 | env:
25 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 |
--------------------------------------------------------------------------------
/.github/workflows/sync_issues.yml:
--------------------------------------------------------------------------------
1 | name: Automate Issue Management
2 |
3 | on:
4 | issues:
5 | types:
6 | - opened
7 | - edited
8 | - assigned
9 | - unassigned
10 | - labeled
11 | - unlabeled
12 | - reopened
13 |
14 | jobs:
15 | add_issue_to_project:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Add issue to GitHub Project
19 | uses: actions/add-to-project@v1.0.2
20 | with:
21 | project-url: https://github.com/orgs/Seeed-Studio/projects/17
22 | github-token: ${{ secrets.ISSUE_ASSEMBLE }}
23 | labeled: bug
24 | label-operator: NOT
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .pio
2 | .vscode/.browse.c_cpp.db*
3 | .vscode/c_cpp_properties.json
4 | .vscode/launch.json
5 | .vscode/ipch
6 | .vs/
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "platformio.platformio-ide"
6 | ],
7 | "unwantedRecommendations": [
8 | "ms-vscode.cpptools-extension-pack"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": {
3 | "list": "cpp",
4 | "deque": "cpp",
5 | "string": "cpp",
6 | "vector": "cpp",
7 | "array": "cpp",
8 | "atomic": "cpp",
9 | "bit": "cpp",
10 | "*.tcc": "cpp",
11 | "cctype": "cpp",
12 | "clocale": "cpp",
13 | "cmath": "cpp",
14 | "compare": "cpp",
15 | "concepts": "cpp",
16 | "cstdarg": "cpp",
17 | "cstddef": "cpp",
18 | "cstdint": "cpp",
19 | "cstdio": "cpp",
20 | "cstdlib": "cpp",
21 | "cstring": "cpp",
22 | "cwchar": "cpp",
23 | "cwctype": "cpp",
24 | "unordered_map": "cpp",
25 | "exception": "cpp",
26 | "algorithm": "cpp",
27 | "functional": "cpp",
28 | "iterator": "cpp",
29 | "memory": "cpp",
30 | "memory_resource": "cpp",
31 | "numeric": "cpp",
32 | "optional": "cpp",
33 | "random": "cpp",
34 | "string_view": "cpp",
35 | "system_error": "cpp",
36 | "tuple": "cpp",
37 | "type_traits": "cpp",
38 | "utility": "cpp",
39 | "initializer_list": "cpp",
40 | "iosfwd": "cpp",
41 | "limits": "cpp",
42 | "new": "cpp",
43 | "ostream": "cpp",
44 | "ranges": "cpp",
45 | "stdexcept": "cpp",
46 | "streambuf": "cpp",
47 | "cinttypes": "cpp",
48 | "typeinfo": "cpp",
49 | "ctime": "cpp",
50 | "iostream": "cpp",
51 | "istream": "cpp",
52 | "sstream": "cpp",
53 | "queue": "cpp",
54 | "bitset": "cpp",
55 | "complex": "cpp",
56 | "map": "cpp",
57 | "set": "cpp",
58 | "iomanip": "cpp",
59 | "valarray": "cpp",
60 | "fstream": "cpp"
61 | }
62 | }
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at zuobaozhu@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## ✨ How you can contribute
2 |
3 | We value contributions and we provide the most active and constant contributors with public recognition, maintainer status and hardware goodies. If you are willing to contribute to our [GitHub](https://github.com/Seeed-Studio) Repositories, please contribute in the following way:
4 |
5 | - Triage open issues: try to reproduce issues reported by other users and confirm whether you can experience them as well, or ask users for more details if needed. Spot duplicates. Improve descriptions. Help users who ask for support.
6 | - Submit fixes and implementations: pick an open issue or feature request that you think you can implement yourself, and submit a pull request with an implementation.
7 | - Test open pull requests: try to run the proposed modifications and report your success or failure. Testing on real hardware takes time and any help in this will speed up our responsiveness in merging contributions.
8 | - Help others contribute by reviewing their code and suggesting good ways to implement fixes and features.
9 | - Write documentation and improve the existing content.
10 | - Assist in translations to your native tongue 🌎
11 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Seeed Studio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/docs/02-Microsoft-Azure-IoT/1-Connect the Wio Terminal to Microsoft Azure IoT Hub (WiFi)/README.md:
--------------------------------------------------------------------------------
1 | # Connecting the Wio Terminal to Microsoft Azure IoT
2 |
3 |

4 |
5 | >This is a document written by [**@Benjamin Cabé**](https://twitter.com/kartben). Thank you Benjamin for the great work! You may also find [Benjamin's work](https://github.com/kartben) here.
6 |
7 | This sample application shows you how to connect your [Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) to [Azure IoT Hub](https://azure.microsoft.com/services/iot-hub). It is built on top of the [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c), a small footprint, easy-to-port library for communicating with Azure services.
8 |
9 | To connect with Microsoft Azure IoT with Wio Terminal, please see the [**Benjamin's Guide**](https://github.com/kartben/wioterminal-azureiothub-sample).
10 |
11 | ## Connecting to MQTT Server
12 |
13 | 
14 |
15 | If you want to connect Wio Terminal to MQTT servers(such as Microsoft Azure IoT), you may also check [**Benjamin's Guide for MQTT on Wio Terminal**](https://github.com/kartben/wioterminal-mqtts-sample)!
16 |
17 | ## Tech Support
18 |
19 | Please submit any technical issue into our [forum](https://forum.seeedstudio.com/)

--------------------------------------------------------------------------------
/docs/05-Helium/2-Connect AWS IOT Core via Helium/README.md:
--------------------------------------------------------------------------------
1 | # Connect AWS IOT Core via Helium
2 |
3 | 
4 |
5 | ## Introduction to AWS IoT Core
6 |
7 | AWS IoT Core provides the cloud services that connect your IoT devices to other devices and AWS cloud services. AWS IoT provides device software that can help you integrate your IoT devices into AWS IoT-based solutions. If your devices can connect to AWS IoT, AWS IoT can connect them to the cloud services that AWS provides.
8 |
9 | 
10 |
11 | AWS IoT lets you select the most appropriate and up-to-date technologies for your solution. To help you manage and support your IoT devices in the field, AWS IoT Core supports these protocols:
12 |
13 | - MQTT (Message Queuing and Telemetry Transport)
14 | - MQTT over WSS (Websockets Secure)
15 | - HTTPS (Hypertext Transfer Protocol - Secure)
16 | - LoRaWAN® (Long Range Wide Area Network)
17 |
18 | AWS IoT Core is a powerful offering that lets developers build device-based applications and services on the AWS Cloud. And this Integration via Helium Console automates the complexity of securely connecting your devices to AWS IoT Core.
19 |
20 | !!!Attention
21 | You may need to pay for AWS IoT Core to experience the full content of this tutorial. A detailed list of payments and costs you can approximate [here](https://calculator.aws/#/estimate).
22 |
23 | Based on the sending frequency of the code we have provided (sending data at approximately 15 second intervals), approximately 178,560 messages will be sent in a month, with a message size of approximately 3 to 4 KB and a monthly cost of 0.18 USD.
24 | 
25 |
26 |
27 | ## Sign up for AWS IoT Core
28 |
29 | Please go to the [AWS IoT Core website](https://portal.aws.amazon.com/billing/signup#/start/email) and register an account.
30 |
31 | 
32 |
33 | Fill out an email with your registered email address and a user name and you will receive an email from AWS with the six-digit verification code required to register.
34 |
35 | Enter your verification code and registration is complete. Sign in to AWS IoT Core with the email address you just filled in.
36 |
37 | After logging in, you will need to continue filling in personal information such as passwords and contacts. You will then be required to link a credit card to verify your personal information.
38 |
39 | 
40 |
41 | When we log in to the AWS IoT Core console, we just select the **Root user** to log in.
42 |
43 | 
44 |
45 | ## Create access to AWS IoT Core
46 |
47 | Create a new user with limited permissions that this Integration will use on AWS.
48 |
49 | 1. Open up the [AWS Console](https://console.aws.amazon.com/).
50 |
51 | 2. Click on Services menu in the upper-left, go to **Security, Identity, & Compliance**, then click **IAM**.
52 |
53 | 
54 |
55 | We are now going to create a new **User**.
56 |
57 | 
58 |
59 | Set the user name and select only **Acess key - Programmatic access**.
60 |
61 | 
62 |
63 | In the next page, select **Attach existing policies directly** and type **AWSIoTConfigAccess** into the **Filter Policies** box and check the box to the left of the row.
64 |
65 | 
66 |
67 |
68 | For other pages we leave the default or leave it empty and just keep clicking **Next** in the bottom right corner.
69 |
70 | 
71 |
72 | We now attach a policy to the newly created user that defines what permissions they hold.
73 |
74 | 
75 |
76 |
77 | !!!Attention
78 | 
79 |
80 | Ensure you record and store these keys securely, as you will not have an opportunity to get access to them again!
81 |
82 | ## Add AWS IoT Core Integration in Helium
83 |
84 | We can go back to the [Helium console](https://console.helium.com/integrations) and create the AWS IoT Core to Helium integration.
85 |
86 | 
87 |
88 | Click **Add Integration** in the new page.
89 |
90 | 
91 |
92 | Fill in the Helium AWS IoT Core integration with the Access Key and Secret Key respectively, which are generated in the content of the **Create access to AWS IoT Core**.
93 |
94 | 
95 |
96 | In Region, you need to fill in the same region code as the address where the AWS IoT Core server is located. This is in the top right hand corner of the AWS IoT Core console at the username.
97 |
98 | 
99 |
100 | The highlighted area is allowed to be adjusted by the user. Here, for example, I have selected the region where the server is located as **US East (N. Virginia)** and the region code as **us-east-1**. Correspondingly, in Helium's Region I need to fill in the **us-east-1**.
101 |
102 | 
103 |
104 | The Topic field is the AWS IoT MQTT topic that this integration will publish uplink messages to, from devices.
105 |
106 | Finally, we give our new Integration a name and click Create Integration. Your new Integration is now ready for use.
107 |
108 | 
109 |
110 |
111 | ## Connecting Integrations to Devices
112 |
113 | Now, use the click and drag interface in the Helium Console to connect the device to the function (Decoder) to the AWS IoT Core as shown [previously](https://wiki.seeedstudio.com/Helium-Introduction/#helium-console-flows).
114 |
115 | 
116 |
117 | At this point, follow the [previous steps](https://wiki.seeedstudio.com/Connecting-to-Helium/#upload-code-send-data-to-helium) to upload the code again, and Wio Terminal will reconnect to Helium and upload the data.
118 |
119 | We can also find out about the success of sending data by checking the data returned by the serial monitor.
120 |
121 | 
122 |
123 | In the AWS IoT Core console, search for **IoT Core** to access the data management interface.
124 |
125 | 
126 |
127 | - In the **Monitor** panel you can see and set up a number of data detection panels to see more visually how the sensor data is being received.
128 |
129 | 
130 |
131 | - In **AWS IOT core -> All devices -> Things** you can see the ID information of the current device and also the activity status of the data in **AWS IOT core -> All devices -> Things -> Activity**.
132 |
133 | 
134 |
135 | 
136 |
137 | - The uplink messages for the data you can view in **AWS IOT core -> MQTT test client**.
138 |
139 | In the **Subscribe to a topic** tab, enter the topicName to subscribe to the topic on which your device publishes. For the getting started sample app, subscribe to **#**, which subscribes to all message topics.
140 |
141 | The topic message log page, **#** opens and **#** appears in the **Subscriptions** list. If the device that you configured in Configure your device is running the example program, you should see the messages it sends to AWS IoT in the **#** message log. The message log entries will appear below the Publish section when messages with the subscribed topic are received by AWS IoT.
142 |
143 | Messages published to subscribed topics appear in the message log as they are received, with the most recent message first.
144 |
145 | 
146 |
147 |
148 | The message received is similar to the one shown below. The data that is useful to us is generally the content following the **payload**, which shows the values of the sensors.
149 |
150 | 
151 |
152 | At this point, we have completed the entirety of Helium's integration into AWS IoT Core. If you want to do more with your data through AWS IoT Core, you can refer to the [Documentation Centre of AWS IoT Core](https://docs.aws.amazon.com/iot/index.html) to continue learning more in depth.
153 |
154 |
155 | ## Tech Support
156 |
157 | Please submit any technical issue into our [forum](https://forum.seeedstudio.com/)

158 |
--------------------------------------------------------------------------------
/docs/05-Helium/2-Integrate into Google Sheets via Helium/README.md:
--------------------------------------------------------------------------------
1 | # Integrate into Google Sheets via Helium
2 |
3 | 
4 |
5 | Google Sheets is a web-based application that enables users to create, update and modify spreadsheets and share the data online in real time.
6 |
7 | The Google Sheets online spreadsheet application enables users to create, edit and format spreadsheets online to organize and analyze information. Google Sheets is often compared to Microsoft Excel, as both applications are used for similar purposes. Google Sheets is essentially Google's cloud-based version of Microsoft Excel's basic features.
8 |
9 | Thanks to Helium's integration capabilities, we can easily save sensor data via Google Sheets and do some simple data analysis accordingly.
10 |
11 | ## Create Google Form
12 |
13 | If you have not registered for a Google account prior to learning this tutorial, please complete your Google account [here](https://accounts.google.com/signup/v2/webcreateaccount?biz=false&flowName=GlifWebSignIn&flowEntry=SignUp&hl=en-GB) first.
14 |
15 | 
16 |
17 | Once you have completed your account registration, please login to the [Google Forms page](https://docs.google.com/forms/u/0/). Then, simply create a new Google Form.
18 |
19 | 
20 |
21 | We recommend setting questions to "Short answer".
22 |
23 | Here, I will create a table using Vision AI Module as an example. This table should have two sets of data, one for the number of people detected and its confidence level.
24 |
25 | 
26 |
27 | !!!Note
28 | Short Answer needs to be selected for each new sensor tag created.
29 |
30 | Head over to the responses tab and tell the form you want your results sent to Google Sheets by clicking the Google Sheets button.
31 |
32 | 
33 |
34 | Simply enter the Google Form title in the new pop-up window and click the **Create** button at the bottom right.
35 |
36 | 
37 |
38 | Make sure we have created the required columns.
39 |
40 | 
41 |
42 | ## Make Form Public
43 |
44 | Go back to our form setup page and click on the **Send** button in the top right hand corner to get the link to share the form.
45 |
46 | 
47 |
48 | You'll get a share link like this one.
49 |
50 | `https://docs.google.com/forms/d/e/1FAIpQLSce9ozQMVwdgIYXYyutRPeE5opGba6724QGEN_I_dvoEH_Muw/viewform?usp=sf_link`
51 |
52 | We're only after the ID of the form, so we're going to remove the prefix `https://docs.google.com/forms/d/e/` and suffix `/viewform?usp=sf_link`. We should be left with a big string that contains no slashes.
53 |
54 | `1FAIpQLSce9ozQMVwdgIYXYyutRPeE5opGba6724QGEN_I_dvoEH_Muw`
55 |
56 | Please record this ID, which will be used in the Helium integration.
57 |
58 | ## Add Google Sheets Integration in Helium
59 |
60 | Go back to Helium and add a Google Sheets integration in Console, go to Integrations on the left-hand menu. Select the integration to add - in this case, the Google Sheets integration as shown below.
61 |
62 | 
63 |
64 | Click **Add Integration** in the new page.
65 |
66 | 
67 |
68 | On the new page, we enter the form ID we obtained above into the corresponding field and click on **Get Google Form Fields** to check if the ID is correct. If, after clicking on it, we are able to get the content of the labels in the columns of the form, the link is correct.
69 |
70 | 
71 |
72 | Click on **Generate Function Body w/ Fields Above** at the bottom and Helium will automatically generate the required decoder for us.
73 |
74 | 
75 |
76 | !!!Tip
77 | At this point, you don't have to rush to click on the Add Integration button on the right, as the integration still needs a little modification to accommodate the sensor values we have passed on.
78 |
79 |
80 | ## Create your Decoder
81 |
82 | We have prepared the code for the complete decoder required to import all the sensors in the kit into Google Sheets for you, please refer to the table below.
83 |
84 | Before using the decoder code for the corresponding sensor, please ensure that you have followed the tutorial above to create and share the Google Form. And if you want to use the code provided by us directly, **the label of the sensor in your form should also match the code**.
85 |
86 |
87 |
88 |
89 | Sensor Type |
90 | Download Address |
91 |
92 |
93 | Wio Terminal built-in light sensor |
94 | Download |
95 |
96 |
97 | Wio Terminal built-in IMU sensor |
98 | Download |
99 |
100 |
101 | Soil Moisture Sensor |
102 | Download |
103 |
104 |
105 | VOC and eCO2 Gas Sensor (SGP30) |
106 | Download |
107 |
108 |
109 | Temp&Humi Sensor (SHT40) |
110 | Download |
111 |
112 |
113 | Vision AI Module |
114 | Download |
115 |
116 |
117 |
118 | !!!Note
119 | The decoder used by Google Forms cannot be used with the decoder provided in the [Connecting to Helium](https://wiki.seeedstudio.com/Connecting-to-Helium/#write-decoders-function-for-different-sensors).
120 |
121 | Continuing from the previous step, we need to copy and replace the code area of Helium with the codec of the sensor you are using, and then just click Add Integration on the right hand side.
122 |
123 | 
124 |
125 | Of course, don't forget that we need to add the integration of the decoder and Google Forms to the **Flow**.
126 |
127 | 
128 |
129 | ## Upload code send data to Helium
130 |
131 | Please follow the instructions in the [Connecting to Helium tutorial](https://wiki.seeedstudio.com/Connecting-to-Helium/#upload-code-send-data-to-helium) to upload the code to send your sensor values to Helium.
132 |
133 | Once the data has started to be sent, you can see a live refresh of the data from Google Sheets.
134 |
135 | 
136 |
137 | 
138 |
139 | 
140 |
141 | 
142 |
143 | 
144 |
145 | 
146 |
147 |
148 | You can also do what I did above, add a variety of table styles to Google Sheets to make it more intuitive and easier for you to see data or understand trends in your data.
149 |
150 | 
151 |
152 |
153 | ## Tech Support
154 | Please submit any technical issue into our [forum](https://forum.seeedstudio.com/).

155 |
--------------------------------------------------------------------------------
/docs/07-WiFi/1-Connect the Wio Terminal to Microsoft Azure IoT Hub/README.md:
--------------------------------------------------------------------------------
1 | # Connecting the Wio Terminal to Microsoft Azure IoT
2 |
3 | 
4 |
5 | >This is a document written by [**@Benjamin Cabé**](https://twitter.com/kartben). Thank you Benjamin for the great work! You may also find [Benjamin's work](https://github.com/kartben) here.
6 |
7 | This sample application shows you how to connect your [Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) to [Azure IoT Hub](https://azure.microsoft.com/services/iot-hub). It is built on top of the [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c), a small footprint, easy-to-port library for communicating with Azure services.
8 |
9 | To connect with Microsoft Azure IoT with Wio Terminal, please see the [**Benjamin's Guide**](https://github.com/kartben/wioterminal-azureiothub-sample).
10 |
11 | ## Connecting to MQTT Server
12 |
13 | 
14 |
15 | If you want to connect Wio Terminal to MQTT servers(such as Microsoft Azure IoT), you may also check [**Benjamin's Guide for MQTT on Wio Terminal**](https://github.com/kartben/wioterminal-mqtts-sample)!
16 |
17 | ## Tech Support
18 |
19 | Please submit any technical issue into our [forum](https://forum.seeedstudio.com/)

--------------------------------------------------------------------------------
/docs/08-Cloud/Connect AWS IOT Core via Helium (Helium)/README.md:
--------------------------------------------------------------------------------
1 | # Connect AWS IOT Core via Helium
2 |
3 | 
4 |
5 | ## Introduction to AWS IoT Core
6 |
7 | AWS IoT Core provides the cloud services that connect your IoT devices to other devices and AWS cloud services. AWS IoT provides device software that can help you integrate your IoT devices into AWS IoT-based solutions. If your devices can connect to AWS IoT, AWS IoT can connect them to the cloud services that AWS provides.
8 |
9 | 
10 |
11 | AWS IoT lets you select the most appropriate and up-to-date technologies for your solution. To help you manage and support your IoT devices in the field, AWS IoT Core supports these protocols:
12 |
13 | - MQTT (Message Queuing and Telemetry Transport)
14 | - MQTT over WSS (Websockets Secure)
15 | - HTTPS (Hypertext Transfer Protocol - Secure)
16 | - LoRaWAN® (Long Range Wide Area Network)
17 |
18 | AWS IoT Core is a powerful offering that lets developers build device-based applications and services on the AWS Cloud. And this Integration via Helium Console automates the complexity of securely connecting your devices to AWS IoT Core.
19 |
20 | !!!Attention
21 | You may need to pay for AWS IoT Core to experience the full content of this tutorial. A detailed list of payments and costs you can approximate [here](https://calculator.aws/#/estimate).
22 |
23 | Based on the sending frequency of the code we have provided (sending data at approximately 15 second intervals), approximately 178,560 messages will be sent in a month, with a message size of approximately 3 to 4 KB and a monthly cost of 0.18 USD.
24 | 
25 |
26 |
27 | ## Sign up for AWS IoT Core
28 |
29 | Please go to the [AWS IoT Core website](https://portal.aws.amazon.com/billing/signup#/start/email) and register an account.
30 |
31 | 
32 |
33 | Fill out an email with your registered email address and a user name and you will receive an email from AWS with the six-digit verification code required to register.
34 |
35 | Enter your verification code and registration is complete. Sign in to AWS IoT Core with the email address you just filled in.
36 |
37 | After logging in, you will need to continue filling in personal information such as passwords and contacts. You will then be required to link a credit card to verify your personal information.
38 |
39 | 
40 |
41 | When we log in to the AWS IoT Core console, we just select the **Root user** to log in.
42 |
43 | 
44 |
45 | ## Create access to AWS IoT Core
46 |
47 | Create a new user with limited permissions that this Integration will use on AWS.
48 |
49 | 1. Open up the [AWS Console](https://console.aws.amazon.com/).
50 |
51 | 2. Click on Services menu in the upper-left, go to **Security, Identity, & Compliance**, then click **IAM**.
52 |
53 | 
54 |
55 | We are now going to create a new **User**.
56 |
57 | 
58 |
59 | Set the user name and select only **Acess key - Programmatic access**.
60 |
61 | 
62 |
63 | In the next page, select **Attach existing policies directly** and type **AWSIoTConfigAccess** into the **Filter Policies** box and check the box to the left of the row.
64 |
65 | 
66 |
67 |
68 | For other pages we leave the default or leave it empty and just keep clicking **Next** in the bottom right corner.
69 |
70 | 
71 |
72 | We now attach a policy to the newly created user that defines what permissions they hold.
73 |
74 | 
75 |
76 |
77 | !!!Attention
78 | 
79 |
80 | Ensure you record and store these keys securely, as you will not have an opportunity to get access to them again!
81 |
82 | ## Add AWS IoT Core Integration in Helium
83 |
84 | We can go back to the [Helium console](https://console.helium.com/integrations) and create the AWS IoT Core to Helium integration.
85 |
86 | 
87 |
88 | Click **Add Integration** in the new page.
89 |
90 | 
91 |
92 | Fill in the Helium AWS IoT Core integration with the Access Key and Secret Key respectively, which are generated in the content of the **Create access to AWS IoT Core**.
93 |
94 | 
95 |
96 | In Region, you need to fill in the same region code as the address where the AWS IoT Core server is located. This is in the top right hand corner of the AWS IoT Core console at the username.
97 |
98 | 
99 |
100 | The highlighted area is allowed to be adjusted by the user. Here, for example, I have selected the region where the server is located as **US East (N. Virginia)** and the region code as **us-east-1**. Correspondingly, in Helium's Region I need to fill in the **us-east-1**.
101 |
102 | 
103 |
104 | The Topic field is the AWS IoT MQTT topic that this integration will publish uplink messages to, from devices.
105 |
106 | Finally, we give our new Integration a name and click Create Integration. Your new Integration is now ready for use.
107 |
108 | 
109 |
110 |
111 | ## Connecting Integrations to Devices
112 |
113 | Now, use the click and drag interface in the Helium Console to connect the device to the function (Decoder) to the AWS IoT Core as shown [previously](https://wiki.seeedstudio.com/Helium-Introduction/#helium-console-flows).
114 |
115 | 
116 |
117 | At this point, follow the [previous steps](https://wiki.seeedstudio.com/Connecting-to-Helium/#upload-code-send-data-to-helium) to upload the code again, and Wio Terminal will reconnect to Helium and upload the data.
118 |
119 | We can also find out about the success of sending data by checking the data returned by the serial monitor.
120 |
121 | 
122 |
123 | In the AWS IoT Core console, search for **IoT Core** to access the data management interface.
124 |
125 | 
126 |
127 | - In the **Monitor** panel you can see and set up a number of data detection panels to see more visually how the sensor data is being received.
128 |
129 | 
130 |
131 | - In **AWS IOT core -> All devices -> Things** you can see the ID information of the current device and also the activity status of the data in **AWS IOT core -> All devices -> Things -> Activity**.
132 |
133 | 
134 |
135 | 
136 |
137 | - The uplink messages for the data you can view in **AWS IOT core -> MQTT test client**.
138 |
139 | In the **Subscribe to a topic** tab, enter the topicName to subscribe to the topic on which your device publishes. For the getting started sample app, subscribe to **#**, which subscribes to all message topics.
140 |
141 | The topic message log page, **#** opens and **#** appears in the **Subscriptions** list. If the device that you configured in Configure your device is running the example program, you should see the messages it sends to AWS IoT in the **#** message log. The message log entries will appear below the Publish section when messages with the subscribed topic are received by AWS IoT.
142 |
143 | Messages published to subscribed topics appear in the message log as they are received, with the most recent message first.
144 |
145 | 
146 |
147 |
148 | The message received is similar to the one shown below. The data that is useful to us is generally the content following the **payload**, which shows the values of the sensors.
149 |
150 | 
151 |
152 | At this point, we have completed the entirety of Helium's integration into AWS IoT Core. If you want to do more with your data through AWS IoT Core, you can refer to the [Documentation Centre of AWS IoT Core](https://docs.aws.amazon.com/iot/index.html) to continue learning more in depth.
153 |
154 |
155 | ## Tech Support
156 |
157 | Please submit any technical issue into our [forum](https://forum.seeedstudio.com/)

158 |
--------------------------------------------------------------------------------
/docs/08-Cloud/Connect the Wio Terminal to Microsoft Azure IoT Hub (WiFi)/README.md:
--------------------------------------------------------------------------------
1 | # Connecting the Wio Terminal to Microsoft Azure IoT
2 |
3 | 
4 |
5 | >This is a document written by [**@Benjamin Cabé**](https://twitter.com/kartben). Thank you Benjamin for the great work! You may also find [Benjamin's work](https://github.com/kartben) here.
6 |
7 | This sample application shows you how to connect your [Wio Terminal](https://www.seeedstudio.com/Wio-Terminal-p-4509.html) to [Azure IoT Hub](https://azure.microsoft.com/services/iot-hub). It is built on top of the [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c), a small footprint, easy-to-port library for communicating with Azure services.
8 |
9 | To connect with Microsoft Azure IoT with Wio Terminal, please see the [**Benjamin's Guide**](https://github.com/kartben/wioterminal-azureiothub-sample).
10 |
11 | ## Connecting to MQTT Server
12 |
13 | 
14 |
15 | If you want to connect Wio Terminal to MQTT servers(such as Microsoft Azure IoT), you may also check [**Benjamin's Guide for MQTT on Wio Terminal**](https://github.com/kartben/wioterminal-mqtts-sample)!
16 |
17 | ## Tech Support
18 |
19 | Please submit any technical issue into our [forum](https://forum.seeedstudio.com/)

--------------------------------------------------------------------------------
/examples/Network/LoRaWAN/Binding-devices/Binding-devices.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 | void DISPLAY_INIT() // Display initialization, black background rotation
13 | {
14 | tft.begin();
15 | tft.setRotation(3);
16 | tft.fillScreen(TFT_BLACK);
17 | }
18 |
19 | void BindDev_Display() // Select Frequency band interface
20 | {
21 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
22 |
23 | // put your main code here
24 | spr.setFreeFont(FSSB9);
25 | spr.setTextColor(TFT_BLACK);
26 |
27 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
28 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
29 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
30 |
31 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
32 | spr.fillRect(30 * PIXEL, 8.0 * FONT_ROW_HEIGHT, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(70, 130, 160));
33 |
34 | spr.fillCircle(160, 55, 10, TFT_BLUE); //button to the left to select LoRa network
35 |
36 | spr.drawString("Sense", 32, 11, GFXFF);
37 | spr.drawString("Process", 127, 11, GFXFF);
38 |
39 | spr.setTextColor(TFT_BLACK);
40 | spr.drawString("Network", 231, 11, GFXFF);
41 |
42 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
43 |
44 | spr.setFreeFont(FSS9);
45 | spr.setTextColor(TFT_WHITE, tft.color565(0, 139, 0));
46 | spr.drawString(" LoRa ", 5, 48, GFXFF); //LoRa(SenseCAP)
47 |
48 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
49 | spr.drawString(" WiFi ", 205, 48, GFXFF); //WiFi(Ubidots)
50 |
51 | spr.setTextColor(TFT_WHITE);
52 | spr.drawString("Please download and register an account", 30, 3.8 * FONT_ROW_HEIGHT, 2);
53 | spr.drawString("on our SenseCAP Mate APP, then scan the", 30, 4.6 * FONT_ROW_HEIGHT, 2);
54 | spr.drawString("QR code on the back of Grove-Wio E5", 30, 5.4 * FONT_ROW_HEIGHT, 2);
55 | spr.drawString("(which is included in the kit) to bind", 30, 6.2 * FONT_ROW_HEIGHT, 2);
56 | spr.drawString("your device to the cloud.", 30, 7.0 * FONT_ROW_HEIGHT, 2);
57 |
58 | spr.setFreeFont(FSS12);
59 | spr.drawString("OK", 36 * PIXEL, 8.4 * FONT_ROW_HEIGHT, GFXFF);
60 |
61 | spr.setFreeFont(FSS9);
62 | spr.drawString("Network :", 5, 218 , GFXFF);
63 |
64 | spr.setTextColor(TFT_RED); //Networking status indication:OFF
65 | spr.drawString("OFF", 82, 218 , GFXFF);
66 |
67 | // spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
68 | // spr.drawString("LoRa(SenseCAP)", 82, 218 , GFXFF); //Show the network you are in
69 |
70 | spr.pushSprite(0, 0);
71 | spr.deleteSprite();
72 | }
73 |
74 | void setup()
75 | {
76 | DISPLAY_INIT();
77 | }
78 |
79 | void loop()
80 | {
81 | BindDev_Display();
82 | }
83 |
--------------------------------------------------------------------------------
/examples/Network/LoRaWAN/Frequency-select/Frequency-select.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 |
13 | //Key
14 | int key_status = 0;
15 |
16 | void key() //set button
17 | {
18 | if (digitalRead(WIO_KEY_C) == LOW) {
19 | Serial.println("A Key pressed");
20 | key_status = 1;
21 | }
22 | else if (digitalRead(WIO_KEY_B) == LOW) {
23 | Serial.println("B Key pressed");
24 | key_status = 2;
25 | }
26 | else if (digitalRead(WIO_KEY_A) == LOW) {
27 | Serial.println("C Key pressed");
28 | key_status = 3;
29 | }
30 | }
31 |
32 | void DISPLAY_INIT() // Display initialization, black background rotation
33 | {
34 | tft.begin();
35 | tft.setRotation(3);
36 | tft.fillScreen(TFT_BLACK);
37 | }
38 |
39 | void Bandselect_Display(int key) // Select Frequency band interface
40 | {
41 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
42 |
43 | // put your main code here
44 | spr.setFreeFont(FSSB9);
45 | spr.setTextColor(TFT_BLACK);
46 |
47 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
48 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
49 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
50 |
51 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
52 |
53 | spr.fillCircle(160, 55, 10, TFT_BLUE); //button to the left to select LoRa network
54 |
55 | spr.drawString("Sense", 32, 11, GFXFF);
56 | spr.drawString("Process", 127, 11, GFXFF);
57 |
58 | spr.setTextColor(TFT_BLACK);
59 | spr.drawString("Network", 231, 11, GFXFF);
60 |
61 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
62 |
63 | spr.setFreeFont(FSS9);
64 | // spr.setTextColor(TFT_WHITE, tft.color565(143, 195, 31));
65 | spr.setTextColor(TFT_WHITE, tft.color565(0, 139, 0));
66 | spr.drawString(" LoRa ", 5, 48, GFXFF); //LoRa(SenseCAP)
67 |
68 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
69 | spr.drawString(" WiFi ", 205, 48, GFXFF); //WiFi(Ubidots)
70 |
71 | spr.setTextColor(TFT_WHITE);
72 | spr.drawString("Select and confirm LoRaWAN frequency band", 20, 3.8 * FONT_ROW_HEIGHT, 2);
73 |
74 | if(key == 1) //Press the A button to select the US915 band
75 | {
76 | spr.fillRect(18, 4.8 * FONT_ROW_HEIGHT, 80, 3.2 * FONT_ROW_HEIGHT, tft.color565(0, 139, 0));
77 | spr.drawString("US915 is commonly used in North America.", 25, 8.5 * FONT_ROW_HEIGHT, 2);
78 | }
79 | if(key == 2) //Press the B button to select the EU868 band
80 | {
81 | spr.fillRect(118, 4.8 * FONT_ROW_HEIGHT, 80, 3.2 * FONT_ROW_HEIGHT, tft.color565(0, 139, 0));
82 | spr.drawString("EU868 is commonly used in the European region.", 10, 8.5 * FONT_ROW_HEIGHT, 2);
83 | }
84 | if(key == 3) //Press the C button to select the AU915 band
85 | {
86 | spr.fillRect(218, 4.8 * FONT_ROW_HEIGHT, 80, 3.2 * FONT_ROW_HEIGHT, tft.color565(0, 139, 0));
87 | spr.drawString("AU915 is commonly used in Australia region.", 18, 8.5 * FONT_ROW_HEIGHT, 2);
88 | }
89 |
90 | spr.drawString("US", 20, 5 * FONT_ROW_HEIGHT, GFXFF);
91 | spr.drawString("EU", 120, 5 * FONT_ROW_HEIGHT, GFXFF);
92 | spr.drawString("AU", 220, 5 * FONT_ROW_HEIGHT, GFXFF);
93 |
94 | spr.setFreeFont(FSS24);
95 | spr.drawString("915", 20, 6 * FONT_ROW_HEIGHT, GFXFF);
96 | spr.drawString("868", 120, 6 * FONT_ROW_HEIGHT, GFXFF);
97 | spr.drawString("915", 220, 6 * FONT_ROW_HEIGHT, GFXFF);
98 |
99 | spr.setFreeFont(FSS9);
100 | spr.drawString("Network :", 5, 218 , GFXFF);
101 |
102 | spr.setTextColor(TFT_RED); //Networking status indication:OFF
103 | spr.drawString("OFF", 82, 218 , GFXFF);
104 |
105 | // spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
106 | // spr.drawString("ON", 82, 218 , GFXFF);
107 |
108 | spr.pushSprite(0, 0);
109 | spr.deleteSprite();
110 | }
111 |
112 | void setup()
113 | {
114 | DISPLAY_INIT();
115 | pinMode(WIO_KEY_C, INPUT_PULLUP);
116 | pinMode(WIO_KEY_B, INPUT_PULLUP);
117 | pinMode(WIO_KEY_A, INPUT_PULLUP);
118 | }
119 |
120 | void loop()
121 | {
122 | key(); //ABC button to select network
123 | Bandselect_Display(key_status);
124 | }
125 |
--------------------------------------------------------------------------------
/examples/Network/LoRaWAN/Network-Select/Network-Select.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 |
13 | //Key
14 | int key_status = 0;
15 |
16 | void key() //set button
17 | {
18 | if (digitalRead(WIO_KEY_C) == LOW) {
19 | Serial.println("A Key pressed");
20 | key_status = 1;
21 | }
22 | else if (digitalRead(WIO_KEY_B) == LOW) {
23 | Serial.println("B Key pressed");
24 | key_status = 2;
25 | }
26 | else if (digitalRead(WIO_KEY_A) == LOW) {
27 | Serial.println("C Key pressed");
28 | key_status = 3;
29 | }
30 | }
31 |
32 | void DISPLAY_INIT() // Display initialization, black background rotation
33 | {
34 | tft.begin();
35 | tft.setRotation(3);
36 | tft.fillScreen(TFT_BLACK);
37 | }
38 |
39 | void NetworkHome_Display() // Select network interface
40 | {
41 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
42 |
43 | // put your main code here
44 | spr.setFreeFont(FSSB9);
45 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
46 |
47 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
48 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
49 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
50 |
51 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
52 |
53 | spr.drawString("Sense", 32, 11, GFXFF);
54 | spr.drawString("Process", 127, 11, GFXFF);
55 |
56 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
57 | spr.drawString("Network", 231, 11, GFXFF);
58 |
59 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
60 |
61 | spr.fillCircle(175, 56, 10, tft.color565(190, 190, 190)); //Default in no network state selected
62 |
63 | spr.setFreeFont(FSS9);
64 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
65 | spr.drawString(" LoRa ", 5, 48, GFXFF); //LoRa(SenseCAP)
66 | spr.drawString(" WiFi ", 205, 48, GFXFF); //WiFi(Ubidots)
67 |
68 | spr.setTextColor(TFT_WHITE, TFT_BLACK);
69 | spr.drawString("Please toggle the bottom right", 30, 95 + FONT_ROW_HEIGHT, GFXFF);
70 | spr.drawString("button left and right to select", 30, 95 + 2 * FONT_ROW_HEIGHT, GFXFF);
71 | spr.drawString("the network.", 30, 95 + 3 * FONT_ROW_HEIGHT, GFXFF);
72 |
73 | spr.drawString("Network :", 5, 218 , GFXFF);
74 |
75 |
76 | spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
77 | spr.drawString("OFF", 82, 218 , GFXFF);
78 |
79 | // spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
80 | // spr.drawString("LoRa(SenseCAP)", 82, 218 , GFXFF); //Show the network you are in
81 |
82 | spr.pushSprite(0, 0);
83 | spr.deleteSprite();
84 | }
85 |
86 | void NetSelection(int key)
87 | {
88 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
89 |
90 | // put your main code here
91 | spr.setFreeFont(FSSB9);
92 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
93 |
94 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
95 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
96 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
97 | spr.fillRect(30 * PIXEL, 8.0 * FONT_ROW_HEIGHT, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(70, 130, 160));
98 |
99 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
100 |
101 | spr.drawString("Sense", 32, 11, GFXFF);
102 | spr.drawString("Process", 127, 11, GFXFF);
103 |
104 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
105 | spr.drawString("Network", 231, 11, GFXFF);
106 |
107 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
108 |
109 | spr.setFreeFont(FSS9);
110 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
111 | spr.drawString(" LoRa ", 5, 48, GFXFF); //LoRa(SenseCAP)
112 | spr.drawString(" WiFi ", 205, 48, GFXFF); //WiFi(Ubidots)
113 |
114 | if(key == 0)spr.fillCircle(175, 56, 10, tft.color565(190, 190, 190)); //Default in no network state selected
115 | if(key == 1)spr.fillCircle(160, 55, 10, TFT_BLUE); //button to the left to select LoRa network
116 | if(key == 2)spr.fillCircle(175, 56, 10, tft.color565(190, 190, 190)); //button to the middle, do not select the network
117 | if(key == 3)spr.fillCircle(192, 55, 10, TFT_BLUE); //button to the right to select the WiFi network
118 |
119 | spr.setTextColor(TFT_WHITE);
120 | spr.drawString("Please press the bottom right", 35, 75 + FONT_ROW_HEIGHT, GFXFF);
121 | spr.drawString("button to confirm your network", 35, 75 + 2 * FONT_ROW_HEIGHT, GFXFF);
122 | spr.drawString("selection.", 35, 75 + 3 * FONT_ROW_HEIGHT, GFXFF);
123 |
124 | spr.setFreeFont(FSS12);
125 | spr.drawString("OK", 36 * PIXEL, 8.4 * FONT_ROW_HEIGHT, GFXFF);
126 |
127 | spr.setFreeFont(FSS9);
128 | spr.drawString("Network :", 5, 218 , GFXFF);
129 |
130 |
131 | spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
132 | spr.drawString("OFF", 82, 218 , GFXFF);
133 |
134 | // spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
135 | // spr.drawString("LoRa(SenseCAP)", 82, 218 , GFXFF); //Show the network you are in
136 |
137 | spr.pushSprite(0, 0);
138 | spr.deleteSprite();
139 | }
140 |
141 | void WioE5connect_Display()
142 | {
143 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
144 |
145 | // put your main code here
146 | spr.setFreeFont(FSSB9);
147 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
148 |
149 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
150 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
151 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
152 | spr.fillRect(30 * PIXEL, 8.0 * FONT_ROW_HEIGHT, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(70, 130, 160));
153 |
154 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
155 |
156 | spr.drawString("Sense", 32, 11, GFXFF);
157 | spr.drawString("Process", 127, 11, GFXFF);
158 |
159 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
160 | spr.drawString("Network", 231, 11, GFXFF);
161 |
162 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
163 |
164 | spr.setFreeFont(FSS9);
165 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
166 | spr.drawString(" LoRa ", 5, 48, GFXFF);
167 | spr.drawString(" WiFi ", 205, 48, GFXFF); //WiFi(Ubidots)
168 |
169 | spr.fillCircle(175, 56, 10, tft.color565(190, 190, 190)); //Default in no network state selected
170 |
171 | spr.setTextColor(TFT_WHITE);
172 | spr.drawString("Please connect the Grove-Wio E5", 25, 75 + FONT_ROW_HEIGHT, GFXFF);
173 | spr.drawString("to the Grove connector on the", 25, 75 + 2 * FONT_ROW_HEIGHT, GFXFF);
174 | spr.drawString("bottom right side of the screen.", 25, 75 + 3 * FONT_ROW_HEIGHT, GFXFF);
175 |
176 | spr.setFreeFont(FSS12);
177 | spr.drawString("OK", 36 * PIXEL, 8.4 * FONT_ROW_HEIGHT, GFXFF);
178 |
179 | spr.setFreeFont(FSS9);
180 | spr.drawString("Network :", 5, 218 , GFXFF);
181 |
182 |
183 | spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
184 | spr.drawString("OFF", 82, 218 , GFXFF);
185 |
186 | // spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
187 | // spr.drawString("LoRa(SenseCAP)", 82, 218 , GFXFF); //Show the network you are in
188 |
189 | spr.pushSprite(0, 0);
190 | spr.deleteSprite();
191 | }
192 |
193 | void setup()
194 | {
195 | DISPLAY_INIT();
196 | pinMode(WIO_KEY_C, INPUT_PULLUP);
197 | pinMode(WIO_KEY_B, INPUT_PULLUP);
198 | pinMode(WIO_KEY_A, INPUT_PULLUP);
199 | }
200 |
201 | void loop()
202 | {
203 | key(); //ABC button to select network
204 | NetworkHome_Display();
205 | delay(2000);
206 | NetSelection(key_status);
207 | delay(2000);
208 | WioE5connect_Display();
209 | delay(2000);
210 | }
211 |
--------------------------------------------------------------------------------
/examples/Network/LoRaWAN/connect-success/connect-success.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 |
13 | //Key
14 | int key_status = 0;
15 |
16 | void key() //set button
17 | {
18 | if (digitalRead(WIO_KEY_C) == LOW) {
19 | Serial.println("A Key pressed");
20 | key_status = 1;
21 | }
22 | else if (digitalRead(WIO_KEY_B) == LOW) {
23 | Serial.println("B Key pressed");
24 | key_status = 2;
25 | }
26 | else if (digitalRead(WIO_KEY_A) == LOW) {
27 | Serial.println("C Key pressed");
28 | key_status = 3;
29 | }
30 | }
31 |
32 | void DISPLAY_INIT() // Display initialization, black background rotation
33 | {
34 | tft.begin();
35 | tft.setRotation(3);
36 | tft.fillScreen(TFT_BLACK);
37 | }
38 |
39 | void ConnectSuc_Display(int key) // Select Frequency band interface
40 | {
41 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
42 |
43 | // put your main code here
44 | spr.setFreeFont(FSSB9);
45 | spr.setTextColor(TFT_BLACK);
46 |
47 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
48 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
49 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
50 |
51 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
52 | spr.fillRect(28 * PIXEL, 8.0 * FONT_ROW_HEIGHT, 25 * PIXEL, FONT_ROW_HEIGHT + 14, tft.color565(160, 34, 34));
53 |
54 | spr.fillCircle(160, 55, 10, TFT_BLUE); //button to the left to select LoRa network
55 |
56 | spr.drawString("Sense", 32, 11, GFXFF);
57 | spr.drawString("Process", 127, 11, GFXFF);
58 |
59 | spr.setTextColor(TFT_BLACK);
60 | spr.drawString("Network", 231, 11, GFXFF);
61 |
62 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
63 |
64 | spr.setFreeFont(FSS9);
65 | spr.setTextColor(TFT_WHITE, tft.color565(0, 139, 0));
66 | spr.drawString(" LoRa ", 5, 48, GFXFF); //LoRa(SenseCAP)
67 |
68 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
69 | spr.drawString(" WiFi ", 205, 48, GFXFF); //iFi(Ubidots)
70 |
71 | spr.setTextColor(TFT_WHITE);
72 | spr.drawString("Connected: LoRa ", 30, 3.8 * FONT_ROW_HEIGHT, 2); //(SenseCAP)
73 | spr.drawString("Signal:", 30, 4.8 * FONT_ROW_HEIGHT, 2);
74 | spr.drawString("All data:", 30, 5.8 * FONT_ROW_HEIGHT, 2);
75 | spr.drawString("packets", 140, 5.8 * FONT_ROW_HEIGHT, 2);
76 | spr.drawString("Success:", 30, 6.8 * FONT_ROW_HEIGHT, 2);
77 | spr.drawString("packets", 140, 6.8 * FONT_ROW_HEIGHT, 2);
78 |
79 | spr.setFreeFont(FSSB9);
80 | spr.setTextColor(tft.color565(0, 139, 0));
81 | spr.drawString("10000", 90, 5.8 * FONT_ROW_HEIGHT, 2); //Show total number of packages issued
82 | spr.drawString("999", 90, 6.8 * FONT_ROW_HEIGHT, 2); //Shows the number of successful deliveries
83 |
84 | // spr.fillRect(78, 110, 3, 11, tft.color565(100, 100, 100)); //No signal
85 | // spr.fillRect(84, 107, 3, 14, tft.color565(100, 100, 100));
86 | // spr.fillRect(90, 104, 3, 17, tft.color565(100, 100, 100));
87 | // spr.fillRect(96, 101, 3, 20, tft.color565(100, 100, 100));
88 |
89 | if(key == 0) //Press the A button to disconnect
90 | {
91 | spr.fillRect(78, 110, 3, 11, tft.color565(0, 139, 0)); //Two-frame signal
92 | spr.fillRect(84, 107, 3, 14, tft.color565(0, 139, 0));
93 | spr.fillRect(90, 104, 3, 17, tft.color565(100, 100, 100));
94 | spr.fillRect(96, 101, 3, 20, tft.color565(100, 100, 100));
95 |
96 | spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, TFT_GREEN); //Data transmission status: normal
97 | spr.setTextColor(TFT_WHITE);
98 | spr.drawString("Send", 253, 5.8 * FONT_ROW_HEIGHT, 2);
99 | spr.drawString("Success", 245, 6.6 * FONT_ROW_HEIGHT, 2);
100 |
101 | spr.setFreeFont(FSS9);
102 | spr.setTextColor(tft.color565(0, 139, 0), TFT_BLACK); //Networking status indication:ON
103 | spr.drawString(" LoRa ", 82, 218 , GFXFF); //(SenseCAP)
104 | }
105 | if(key == 1) //Press the A button to disconnect
106 | {
107 | spr.fillRect(78, 110, 3, 11, tft.color565(0, 139, 0)); //Four-frame signal
108 | spr.fillRect(84, 107, 3, 14, tft.color565(0, 139, 0));
109 | spr.fillRect(90, 104, 3, 17, tft.color565(0, 139, 0));
110 | spr.fillRect(96, 101, 3, 20, tft.color565(0, 139, 0));
111 |
112 | spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, TFT_GREEN); //Data transmission status: normal
113 | spr.setTextColor(TFT_WHITE);
114 | spr.drawString("Send", 253, 5.8 * FONT_ROW_HEIGHT, 2);
115 | spr.drawString("Success", 245, 6.6 * FONT_ROW_HEIGHT, 2);
116 |
117 | spr.setFreeFont(FSS9);
118 | spr.setTextColor(tft.color565(0, 139, 0), TFT_BLACK); //Networking status indication:ON
119 | spr.drawString(" LoRa ", 82, 218 , GFXFF); //LoRa(SenseCAP)
120 | }
121 | if(key == 2) //Press the B button to disconnect
122 | {
123 | spr.fillRect(78, 110, 3, 11, tft.color565(0, 139, 0)); //One frame signal
124 | spr.fillRect(84, 107, 3, 14, tft.color565(100, 100, 100));
125 | spr.fillRect(90, 104, 3, 17, tft.color565(100, 100, 100));
126 | spr.fillRect(96, 101, 3, 20, tft.color565(100, 100, 100));
127 |
128 | spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, tft.color565(255, 165, 0)); //Data transmission status: Packet loss
129 | spr.setTextColor(TFT_WHITE);
130 | spr.drawString("Send", 253, 5.8 * FONT_ROW_HEIGHT, 2);
131 | spr.drawString("Failed", 250, 6.6 * FONT_ROW_HEIGHT, 2);
132 |
133 | spr.setFreeFont(FSS9);
134 | spr.setTextColor(tft.color565(0, 139, 0), TFT_BLACK); //Networking status indication:ON
135 | spr.drawString(" LoRa ", 82, 218 , GFXFF); //LoRa (SenseCAP)
136 | }
137 | if(key == 3) //Press the C button to disconnect
138 | {
139 | spr.fillRect(78, 110, 3, 11, tft.color565(140, 42, 42)); //No signal
140 | spr.fillRect(84, 107, 3, 14, tft.color565(140, 42, 42));
141 | spr.fillRect(90, 104, 3, 17, tft.color565(140, 42, 42));
142 | spr.fillRect(96, 101, 3, 20, tft.color565(140, 42, 42));
143 |
144 |
145 | // Demo version we dont display "Join loRaWAN failed"
146 | // spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, TFT_RED); //Data transmission status: join failed
147 | // spr.setTextColor(TFT_WHITE);
148 | // spr.drawString("Join LoRaWAN", 220, 5.8 * FONT_ROW_HEIGHT, 2);
149 | // spr.drawString("Failed", 250, 6.6 * FONT_ROW_HEIGHT, 2);
150 |
151 | spr.setFreeFont(FSS9);
152 | spr.setTextColor(TFT_RED); //Networking status indication:OFF
153 | spr.drawString("OFF", 82, 218 , GFXFF);
154 | }
155 |
156 | spr.setFreeFont(FSS9);
157 | spr.setTextColor(TFT_WHITE);
158 | spr.drawString("Disconnect", 29 * PIXEL, 8.4 * FONT_ROW_HEIGHT, GFXFF);
159 |
160 | spr.setFreeFont(FSS9);
161 | spr.drawString("Network :", 5, 218 , GFXFF);
162 |
163 | spr.pushSprite(0, 0);
164 | spr.deleteSprite();
165 | }
166 |
167 | void Disconnect_Tip() // Pop-up prompt for sensor insertion
168 | {
169 | spr.createSprite(240, 116);
170 | spr.fillScreen(tft.color565(211, 211, 211));
171 |
172 | spr.setFreeFont(FSS9);
173 | spr.setTextColor(TFT_BLACK);
174 | spr.drawString("Network will be disconnected", 3, 30, GFXFF);
175 |
176 | spr.fillRect(40, 70, 65, 35, tft.color565(140, 42, 42));
177 | spr.fillRect(139, 70, 65, 35, tft.color565(70, 130, 160));
178 |
179 | spr.setTextColor(TFT_WHITE);
180 | spr.drawString("Yes", 57, 78, GFXFF);
181 | spr.drawString("No", 162, 78, GFXFF);
182 |
183 | spr.pushSprite(40, 64);
184 | spr.deleteSprite();
185 | }
186 |
187 | void setup()
188 | {
189 | DISPLAY_INIT();
190 | pinMode(WIO_KEY_C, INPUT_PULLUP);
191 | pinMode(WIO_KEY_B, INPUT_PULLUP);
192 | pinMode(WIO_KEY_A, INPUT_PULLUP);
193 | }
194 |
195 | void loop()
196 | {
197 | key(); //ABC button to select network
198 | ConnectSuc_Display(key_status);
199 | delay(2000);
200 | Disconnect_Tip();
201 | delay(2000);
202 | }
203 |
--------------------------------------------------------------------------------
/examples/Network/WiFi/connect-success/connect-success.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 |
13 | //Key
14 | int key_status = 0;
15 |
16 | void key() //set button
17 | {
18 | if (digitalRead(WIO_KEY_C) == LOW) {
19 | Serial.println("A Key pressed");
20 | key_status = 1;
21 | }
22 | else if (digitalRead(WIO_KEY_B) == LOW) {
23 | Serial.println("B Key pressed");
24 | key_status = 2;
25 | }
26 | else if (digitalRead(WIO_KEY_A) == LOW) {
27 | Serial.println("C Key pressed");
28 | key_status = 3;
29 | }
30 | }
31 |
32 | void DISPLAY_INIT() // Display initialization, black background rotation
33 | {
34 | tft.begin();
35 | tft.setRotation(3);
36 | tft.fillScreen(TFT_BLACK);
37 | }
38 |
39 | void ConnectSuc_Display(int key) // Select Frequency band interface
40 | {
41 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
42 |
43 | // put your main code here
44 | spr.setFreeFont(FSSB9);
45 | spr.setTextColor(TFT_BLACK);
46 |
47 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
48 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
49 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
50 |
51 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
52 | spr.fillRect(28 * PIXEL, 8.0 * FONT_ROW_HEIGHT, 25 * PIXEL, FONT_ROW_HEIGHT + 14, tft.color565(160, 34, 34));
53 |
54 | spr.fillCircle(192, 55, 10, TFT_BLUE); //button to the right to select the WiFi network
55 |
56 | spr.drawString("Sense", 32, 11, GFXFF);
57 | spr.drawString("Process", 127, 11, GFXFF);
58 |
59 | spr.setTextColor(TFT_BLACK);
60 | spr.drawString("Network", 231, 11, GFXFF);
61 |
62 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
63 |
64 | spr.setFreeFont(FSS9);
65 | spr.setTextColor(TFT_WHITE, tft.color565(0, 139, 0));
66 | spr.drawString("WiFi ", 205, 48, GFXFF); // WiFi(Ubidots)
67 |
68 | spr.setFreeFont(FSS9);
69 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
70 | spr.drawString("LoRa ", 5, 48, GFXFF); // LoRa(Sencecap)
71 |
72 | spr.setTextColor(TFT_WHITE);
73 | spr.drawString("Connected: WiFi ", 30, 3.8 * FONT_ROW_HEIGHT, 2);
74 | spr.drawString("Signal:", 30, 4.8 * FONT_ROW_HEIGHT, 2);
75 | spr.drawString("All data:", 30, 5.8 * FONT_ROW_HEIGHT, 2);
76 | spr.drawString("packets", 140, 5.8 * FONT_ROW_HEIGHT, 2);
77 | spr.drawString("Success:", 30, 6.8 * FONT_ROW_HEIGHT, 2);
78 | spr.drawString("packets", 140, 6.8 * FONT_ROW_HEIGHT, 2);
79 |
80 | spr.setFreeFont(FSSB9);
81 | spr.setTextColor(tft.color565(0, 139, 0));
82 | spr.drawString("10000", 90, 5.8 * FONT_ROW_HEIGHT, 2); //Show total number of packages issued
83 | spr.drawString("999", 90, 6.8 * FONT_ROW_HEIGHT, 2); //Shows the number of successful deliveries
84 |
85 | if(key == 0) //Press the A button to disconnect
86 | {
87 | spr.fillRect(78, 110, 3, 11, tft.color565(0, 139, 0)); //Two-frame signal
88 | spr.fillRect(84, 107, 3, 14, tft.color565(0, 139, 0));
89 | spr.fillRect(90, 104, 3, 17, tft.color565(100, 100, 100));
90 | spr.fillRect(96, 101, 3, 20, tft.color565(100, 100, 100));
91 |
92 | spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, TFT_GREEN); //Data transmission status: normal
93 | spr.setTextColor(TFT_WHITE);
94 | spr.drawString("Send", 253, 5.8 * FONT_ROW_HEIGHT, 2);
95 | spr.drawString("Success", 245, 6.6 * FONT_ROW_HEIGHT, 2);
96 |
97 | spr.setFreeFont(FSS9);
98 | spr.setTextColor(tft.color565(0, 139, 0), TFT_BLACK); //Networking status indication:ON
99 | spr.drawString(" WiFi ", 82, 218 , GFXFF); // WIFI(Ubidots)
100 | }
101 | if(key == 1) //Press the A button to disconnect
102 | {
103 | spr.fillRect(78, 110, 3, 11, tft.color565(0, 139, 0)); //Four-frame signal
104 | spr.fillRect(84, 107, 3, 14, tft.color565(0, 139, 0));
105 | spr.fillRect(90, 104, 3, 17, tft.color565(0, 139, 0));
106 | spr.fillRect(96, 101, 3, 20, tft.color565(0, 139, 0));
107 |
108 | spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, TFT_GREEN); //Data transmission status: normal
109 | spr.setTextColor(TFT_WHITE);
110 | spr.drawString("Send", 253, 5.8 * FONT_ROW_HEIGHT, 2);
111 | spr.drawString("Success", 245, 6.6 * FONT_ROW_HEIGHT, 2);
112 |
113 | spr.setFreeFont(FSS9);
114 | spr.setTextColor(tft.color565(0, 139, 0), TFT_BLACK); //Networking status indication:ON
115 | spr.drawString(" WiFi ", 82, 218 , GFXFF); //WiFi(Ubidots)
116 | }
117 | if(key == 2) //Press the B button to disconnect
118 | {
119 | spr.fillRect(78, 110, 3, 11, tft.color565(0, 139, 0)); //One frame signal
120 | spr.fillRect(84, 107, 3, 14, tft.color565(100, 100, 100));
121 | spr.fillRect(90, 104, 3, 17, tft.color565(100, 100, 100));
122 | spr.fillRect(96, 101, 3, 20, tft.color565(100, 100, 100));
123 |
124 | spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, tft.color565(255, 165, 0)); //Data transmission status: Packet loss
125 | spr.setTextColor(TFT_WHITE);
126 | spr.drawString("Send", 253, 5.8 * FONT_ROW_HEIGHT, 2);
127 | spr.drawString("Failed", 250, 6.6 * FONT_ROW_HEIGHT, 2);
128 |
129 | spr.setFreeFont(FSS9);
130 | spr.setTextColor(tft.color565(0, 139, 0), TFT_BLACK); //Networking status indication:ON
131 | spr.drawString(" WiFi ", 82, 218 , GFXFF);
132 | }
133 | if(key == 3) //Press the C button to disconnect
134 | {
135 | spr.fillRect(78, 110, 3, 11, tft.color565(140, 42, 42)); //No signal
136 | spr.fillRect(84, 107, 3, 14, tft.color565(140, 42, 42));
137 | spr.fillRect(90, 104, 3, 17, tft.color565(140, 42, 42));
138 | spr.fillRect(96, 101, 3, 20, tft.color565(140, 42, 42));
139 |
140 | spr.fillCircle(265, 4.9 * FONT_ROW_HEIGHT, 10, TFT_RED); //Data transmission status: join failed
141 | spr.setTextColor(TFT_WHITE);
142 | spr.drawString("Join WiFi", 240, 5.8 * FONT_ROW_HEIGHT, 2);
143 | spr.drawString("Failed", 250, 6.6 * FONT_ROW_HEIGHT, 2);
144 |
145 | spr.setFreeFont(FSS9);
146 | spr.setTextColor(TFT_RED); //Networking status indication:OFF
147 | spr.drawString("OFF", 82, 218 , GFXFF);
148 | }
149 |
150 | spr.setFreeFont(FSS9);
151 | spr.setTextColor(TFT_WHITE);
152 | spr.drawString("Disconnect", 29 * PIXEL, 8.4 * FONT_ROW_HEIGHT, GFXFF);
153 |
154 | spr.setFreeFont(FSS9);
155 | spr.drawString("Network :", 5, 218 , GFXFF);
156 |
157 | spr.pushSprite(0, 0);
158 | spr.deleteSprite();
159 | }
160 |
161 | void Disconnect_Tip() // Pop-up prompt for sensor insertion
162 | {
163 | spr.createSprite(240, 116);
164 | spr.fillScreen(tft.color565(211, 211, 211));
165 |
166 | spr.setFreeFont(FSS9);
167 | spr.setTextColor(TFT_BLACK);
168 | spr.drawString("Network will be disconnected", 3, 30, GFXFF);
169 |
170 | spr.fillRect(40, 70, 65, 35, tft.color565(140, 42, 42));
171 | spr.fillRect(139, 70, 65, 35, tft.color565(70, 130, 160));
172 |
173 | spr.setTextColor(TFT_WHITE);
174 | spr.drawString("Yes", 57, 78, GFXFF);
175 | spr.drawString("No", 162, 78, GFXFF);
176 |
177 | spr.pushSprite(40, 64);
178 | spr.deleteSprite();
179 | }
180 |
181 | void setup()
182 | {
183 | DISPLAY_INIT();
184 | pinMode(WIO_KEY_C, INPUT_PULLUP);
185 | pinMode(WIO_KEY_B, INPUT_PULLUP);
186 | pinMode(WIO_KEY_A, INPUT_PULLUP);
187 | }
188 |
189 | void loop()
190 | {
191 | key(); //ABC button to select network
192 | ConnectSuc_Display(key_status);
193 | delay(2000);
194 | Disconnect_Tip();
195 | delay(2000);
196 | }
197 |
--------------------------------------------------------------------------------
/examples/Network/WiFi/wifi-select/wifi-select.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 |
13 | //Key
14 | int key_status = 0;
15 |
16 | void key() //set button
17 | {
18 | if (digitalRead(WIO_KEY_C) == LOW) {
19 | Serial.println("A Key pressed");
20 | key_status = 1;
21 | }
22 | else if (digitalRead(WIO_KEY_B) == LOW) {
23 | Serial.println("B Key pressed");
24 | key_status = 2;
25 | }
26 | else if (digitalRead(WIO_KEY_A) == LOW) {
27 | Serial.println("C Key pressed");
28 | key_status = 3;
29 | }
30 | }
31 |
32 | void DISPLAY_INIT() // Display initialization, black background rotation
33 | {
34 | tft.begin();
35 | tft.setRotation(3);
36 | tft.fillScreen(TFT_BLACK);
37 | }
38 |
39 | void WifiSelection()
40 | {
41 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
42 |
43 | // put your main code here
44 | spr.setFreeFont(FSSB9);
45 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
46 |
47 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
48 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
49 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
50 | spr.fillRect(30 * PIXEL, 8.0 * FONT_ROW_HEIGHT, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(70, 130, 160));
51 |
52 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
53 |
54 | spr.drawString("Sense", 32, 11, GFXFF);
55 | spr.drawString("Process", 127, 11, GFXFF);
56 |
57 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
58 | spr.drawString("Network", 231, 11, GFXFF);
59 |
60 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
61 |
62 | spr.setFreeFont(FSS9);
63 | spr.setTextColor(TFT_WHITE, tft.color565(0, 139, 0));
64 | spr.drawString(" WiFi ", 205, 48, GFXFF); //(Ubidots)
65 |
66 | spr.setFreeFont(FSS9);
67 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
68 | spr.drawString(" LoRa ", 5, 48, GFXFF); //LoRa(SenseCAP)
69 |
70 | spr.fillCircle(192, 55, 10, TFT_BLUE); //button to the right to select the WiFi network
71 |
72 | spr.setTextColor(TFT_WHITE);
73 | spr.drawString("Please refer to the wiki to modify", 25, 75 + FONT_ROW_HEIGHT, GFXFF);
74 | spr.drawString("the configuration file and send it", 25, 75 + 2 * FONT_ROW_HEIGHT, GFXFF);
75 | spr.drawString("to this device.", 25, 75 + 3 * FONT_ROW_HEIGHT, GFXFF);
76 |
77 | spr.setFreeFont(FSS12);
78 | spr.drawString("OK", 36 * PIXEL, 8.4 * FONT_ROW_HEIGHT, GFXFF);
79 |
80 | spr.setFreeFont(FSS9);
81 | spr.drawString("Network :", 5, 218 , GFXFF);
82 |
83 |
84 | spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
85 | spr.drawString("OFF", 82, 218 , GFXFF);
86 |
87 | // spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
88 | // spr.drawString("WiFi(Ubidots)", 82, 218 , GFXFF); //Show the network you are in
89 |
90 | spr.pushSprite(0, 0);
91 | spr.deleteSprite();
92 | }
93 |
94 | void WifiWait_Display()
95 | {
96 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
97 |
98 | // put your main code here
99 | spr.setFreeFont(FSSB9);
100 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
101 |
102 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
103 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
104 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
105 |
106 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
107 |
108 | spr.drawString("Sense", 32, 11, GFXFF);
109 | spr.drawString("Process", 127, 11, GFXFF);
110 |
111 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
112 | spr.drawString("Network", 231, 11, GFXFF);
113 |
114 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
115 |
116 | spr.setFreeFont(FSS9);
117 | spr.setTextColor(TFT_WHITE, tft.color565(0, 139, 0));
118 | spr.drawString(" WiFi ", 205, 48, GFXFF); //
119 |
120 | spr.setFreeFont(FSS9);
121 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
122 | spr.drawString(" LoRa ", 5, 48, GFXFF);
123 |
124 | spr.fillCircle(192, 55, 10, TFT_BLUE); //button to the right to select the WiFi network
125 |
126 | spr.setTextColor(TFT_WHITE);
127 | spr.drawString("Waiting for configuration...", 55, 75 + 2.5 * FONT_ROW_HEIGHT, GFXFF);
128 |
129 | spr.setFreeFont(FSS9);
130 | spr.drawString("Network :", 5, 218 , GFXFF);
131 |
132 |
133 | spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
134 | spr.drawString("OFF", 82, 218 , GFXFF);
135 |
136 | // spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
137 | // spr.drawString("WiFi(Ubidots)", 82, 218 , GFXFF); //Show the network you are in
138 |
139 | spr.pushSprite(0, 0);
140 | spr.deleteSprite();
141 | }
142 |
143 | void Wificonnect_Display()
144 | {
145 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
146 |
147 | // put your main code here
148 | spr.setFreeFont(FSSB9);
149 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
150 |
151 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
152 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
153 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
154 | spr.fillRect(30 * PIXEL, 8.0 * FONT_ROW_HEIGHT, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(70, 130, 160));
155 |
156 | spr.fillRect(156, 54, 40, 4, tft.color565(220, 220, 220));
157 |
158 | spr.drawString("Sense", 32, 11, GFXFF);
159 | spr.drawString("Process", 127, 11, GFXFF);
160 |
161 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
162 | spr.drawString("Network", 231, 11, GFXFF);
163 |
164 | spr.drawLine(0, 3.5 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 3.5 * FONT_ROW_HEIGHT, TFT_WHITE);
165 |
166 | spr.setFreeFont(FSS9);
167 | spr.setTextColor(TFT_WHITE, tft.color565(0, 139, 0));
168 | spr.drawString(" WiFi ", 205, 48, GFXFF);
169 |
170 | spr.setFreeFont(FSS9);
171 | spr.setTextColor(TFT_WHITE, tft.color565(100, 100, 100));
172 | spr.drawString(" LoRa ", 5, 48, GFXFF);
173 |
174 | spr.fillCircle(192, 55, 10, TFT_BLUE); //button to the right to select the WiFi network
175 |
176 | spr.setTextColor(TFT_WHITE);
177 | spr.drawString("Successful!", 115, 75 + 2 * FONT_ROW_HEIGHT, GFXFF);
178 |
179 | spr.setFreeFont(FSS12);
180 | spr.drawString("OK", 36 * PIXEL, 8.4 * FONT_ROW_HEIGHT, GFXFF);
181 |
182 | spr.setFreeFont(FSS9);
183 | spr.drawString("Network :", 5, 218 , GFXFF);
184 |
185 |
186 | // spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
187 | // spr.drawString("OFF", 82, 218 , GFXFF);
188 |
189 | spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
190 | spr.drawString(" WiFi ", 82, 218 , GFXFF); //Show the network you are in
191 |
192 | spr.pushSprite(0, 0);
193 | spr.deleteSprite();
194 | }
195 |
196 | void setup()
197 | {
198 | DISPLAY_INIT();
199 | pinMode(WIO_KEY_C, INPUT_PULLUP);
200 | pinMode(WIO_KEY_B, INPUT_PULLUP);
201 | pinMode(WIO_KEY_A, INPUT_PULLUP);
202 | }
203 |
204 | void loop()
205 | {
206 | WifiSelection();
207 | delay(2000);
208 | WifiWait_Display();
209 | delay(2000);
210 | Wificonnect_Display();
211 | delay(2000);
212 | }
213 |
--------------------------------------------------------------------------------
/examples/PAGE_TEMPLE/PAGE_TEMPLE.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 | void DISPLAY_INIT() // Display initialization, black background rotation
13 | {
14 | tft.begin();
15 | tft.setRotation(3);
16 | tft.fillScreen(TFT_BLACK);
17 | }
18 |
19 | void Network_state(int s_key)
20 | {
21 | switch (s_key)
22 | {
23 | case 0:
24 | spr.setTextColor(TFT_RED);
25 | spr.drawString("OFF", 82, 218 , GFXFF);
26 | break;
27 | case 1:
28 | spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
29 | spr.drawString(" LoRa ", 82, 218 , GFXFF); //Show the network you are in
30 | break;
31 | default:;
32 | }
33 | spr.setTextColor(TFT_WHITE);
34 | spr.drawString("Network :", 5, 218, GFXFF);
35 | }
36 |
37 | void Sense_Display() // Sense interface display
38 | {
39 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
40 |
41 | // put your main code here
42 | spr.setFreeFont(FSSB9);
43 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
44 |
45 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
46 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
47 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
48 |
49 | spr.drawString("Process", 127, 11, GFXFF);
50 | spr.drawString("Network", 231, 11, GFXFF);
51 |
52 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
53 | spr.drawString("Sense", 32, 11, GFXFF);
54 |
55 | spr.drawLine(0, 2 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 2 * FONT_ROW_HEIGHT, TFT_WHITE);
56 |
57 | spr.setFreeFont(FSS9);
58 | spr.setTextColor(TFT_BLACK, tft.color565(220, 220, 220));
59 | spr.fillRect(128, 50, 16 * PIXEL, FONT_ROW_HEIGHT, tft.color565(220, 220, 220));
60 | spr.drawString("Sensor", 132, 54, GFXFF);
61 |
62 | Network_state(1);
63 |
64 | spr.pushSprite(0, 0);
65 | spr.deleteSprite();
66 | }
67 |
68 | void setup()
69 | {
70 | DISPLAY_INIT();
71 | }
72 |
73 | void loop()
74 | {
75 | Sense_Display();
76 | }
77 |
--------------------------------------------------------------------------------
/examples/PAGE_WELCOME/PAGE_WELCOME.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "disk91_LoRaE5.h"
5 | #include "LIS3DHTR.h"
6 | #include "Seeed_Arduino_GroveAI.h"
7 | #include "seeed_line_chart.h"
8 | #include
9 |
10 | TFT_eSPI tft = TFT_eSPI();
11 | #define DATA_MAX_SIZE 30 // maximum size of data
12 | #define MAX_SIZE 30 // maximum size of data
13 | doubles data; // Initilising a doubles type to store data
14 | TFT_eSprite spr = TFT_eSprite(&tft); // Sprite
15 | LIS3DHTR lis;
16 |
17 |
18 | // Display size settings
19 | #define SCREEN_WIDTH 320
20 | #define SCREEN_HIGH 240
21 | #define SCREEN_PADDING 10
22 | #define PIXEL 4
23 | const static unsigned int FONT_SIZE = 2; // rate
24 | const static unsigned int FONT_ROW_HEIGHT = 22; // px
25 | const static unsigned int FONT_LEFT_START = 0; // px
26 | const static unsigned int FONT_COLOR = TFT_WHITE;
27 | const static unsigned int FONT_BG_COLOR = TFT_RED;
28 | const static unsigned int BACKGROUD = TFT_BLACK;
29 |
30 |
31 | void setup()
32 | {
33 | pinMode(A0, INPUT);
34 | tft.begin();
35 | tft.setRotation(3);
36 | tft.fillScreen(TFT_WHITE);
37 | }
38 |
39 | void PAGE() //Set Band Page
40 | {
41 | tft.fillScreen(TFT_BLACK);
42 | tft.fillRect(0, 140, 320, 100, TFT_WHITE);
43 | tft.setTextSize(1);
44 | tft.setTextColor(TFT_BLACK);
45 | tft.setTextDatum(MC_DATUM);
46 | tft.fillRect(0, 0, 30, 10, TFT_CYAN);
47 | tft.fillRect(73, 0, 40, 10, TFT_GREEN);
48 | tft.fillRect(154, 0, 40, 10, TFT_YELLOW);
49 | tft.drawString("Please select LoRaWAN", 160, 160, 4);
50 | tft.drawString("frequency bands for your", 160, 190, 4);
51 | tft.drawString("device connection.", 160, 220, 4);
52 |
53 | tft.drawLine(12, 30, 12, 125, TFT_CYAN);
54 | tft.drawLine(12, 125, 245, 125, TFT_CYAN);
55 |
56 | tft.drawLine(90, 30, 90, 105, TFT_GREEN);
57 | tft.drawLine(90, 105, 245, 105, TFT_GREEN);
58 |
59 | tft.drawLine(168, 30, 168, 85, TFT_YELLOW);
60 | tft.drawLine(168, 85, 245, 85, TFT_YELLOW);
61 |
62 | tft.setTextColor(TFT_CYAN, TFT_BLACK);
63 | tft.drawString("Button A", 0, 23, 2);
64 | tft.drawString("EU868", 280, 125, 2);
65 |
66 | tft.setTextColor(TFT_GREEN, TFT_BLACK);
67 | tft.drawString("Button B", 95, 23, 2);
68 | tft.drawString("US915", 280, 105, 2);
69 |
70 | tft.setTextColor(TFT_YELLOW, TFT_BLACK);
71 | tft.drawString("Button C", 174, 23, 2);
72 | tft.drawString("AU915", 280, 85, 2);
73 |
74 | tft.setTextDatum(0);
75 | }
76 |
77 | void loop()
78 | {
79 | PAGE();
80 | }
81 |
--------------------------------------------------------------------------------
/examples/PAGE_process_tinyml/PAGE_process_tinyml.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
11 |
12 | void DISPLAY_INIT() // Display initialization, black background rotation
13 | {
14 | tft.begin();
15 | tft.setRotation(3);
16 | tft.fillScreen(TFT_BLACK);
17 | }
18 |
19 | void Process_main(){
20 | spr.drawString("Vision AI real-time analysis", 24, 71, GFXFF);
21 |
22 | spr.drawString("TinyML Example", 24, 71, GFXFF);
23 |
24 | spr.drawString("Vision AI real-time analysis", 24, 71, GFXFF);
25 | }
26 | void Sense_Display() // Sense interface display
27 | {
28 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
29 |
30 | // put your main code here
31 |
32 | Process_main();
33 |
34 | spr.setFreeFont(FSSB9);
35 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
36 |
37 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
38 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
39 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
40 |
41 | spr.drawString("Sense", 32, 11, GFXFF);
42 | spr.drawString("Process", 127, 11, GFXFF);
43 | spr.drawString("Network", 231, 11, GFXFF);
44 |
45 | spr.drawLine(0, 2 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 2 * FONT_ROW_HEIGHT, TFT_WHITE);
46 |
47 | spr.setFreeFont(FSS9);
48 | spr.setTextColor(TFT_BLACK, tft.color565(220, 220, 220));
49 | spr.fillRect(127, 53.5, 16 * PIXEL, FONT_ROW_HEIGHT, tft.color565(220, 220, 220));
50 | spr.drawString("Sensor", 130, 56, GFXFF);
51 |
52 | spr.pushSprite(0, 0);
53 | spr.deleteSprite();
54 | }
55 |
56 |
57 |
58 | void setup()
59 | {
60 | DISPLAY_INIT();
61 | }
62 |
63 | void loop()
64 | {
65 | Sense_Display();
66 | }
67 |
--------------------------------------------------------------------------------
/examples/Process/PAGE_tf/PAGE_tf.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "disk91_LoRaE5.h"
5 | #include "LIS3DHTR.h"
6 | #include "Seeed_Arduino_GroveAI.h"
7 | #include "seeed_line_chart.h"
8 | #include
9 | #include "Free_Fonts.h"
10 | TFT_eSPI tft = TFT_eSPI();
11 | #define DATA_MAX_SIZE 30 // maximum size of data
12 | #define MAX_SIZE 30 // maximum size of data
13 | doubles data; // Initilising a doubles type to store data
14 | TFT_eSprite spr = TFT_eSprite(&tft); // Sprite
15 | LIS3DHTR lis;
16 |
17 | // Display size settings
18 | #define SCREEN_WIDTH 320
19 | #define SCREEN_HIGH 240
20 | #define SCREEN_PADDING 0
21 | #define PIXEL 4
22 | const static unsigned int FONT_SIZE = 2; // rate
23 | const static unsigned int FONT_ROW_HEIGHT = 22; // px
24 | const static unsigned int FONT_LEFT_START = 0; // px
25 | const static unsigned int FONT_COLOR = TFT_WHITE;
26 | const static unsigned int FONT_BG_COLOR = TFT_RED;
27 | const static unsigned int BACKGROUD = TFT_BLACK;
28 | int conf = 0; //Confidence
29 | int num = 0; //number of people
30 | int light = 0, mic_val = 0; //Light value, microphone loudness
31 | bool col = false; //control lora wan light color
32 | float x_values = 0.0, y_value = 0.0, z_val = 0.0; // Imu value
33 | int conf_avg = 0;
34 |
35 | int gg_switch = 0;
36 | int gg_switch_k = 1;
37 | int gg_switch_circle = 10; // r outer great circle radius
38 | int gg_switch_rect_width = 20; // width x++ rectangle width
39 | int gg_switch_rect_high = 1; // high y++
40 | int gg_switch_location_x = FONT_LEFT_START + 260; // location left center
41 | int gg_switch_location_y = 115;
42 | int gg_switch_state = 0; // 0 off 1 on
43 | unsigned int gg_switch_state_color[4] = {tft.color565(211, 211, 211), TFT_BLUE, tft.color565(201, 201, 201), tft.color565(65, 105, 235)};
44 |
45 | void switch_button_gui(int gg_switch_location_x, int gg_switch_location_y, int gg_switch_circle, int gg_switch_rect_width, int gg_switch)
46 | {
47 | if (gg_switch == 1)
48 | {
49 | spr.fillCircle(gg_switch_location_x + gg_switch_rect_width, gg_switch_location_y, gg_switch_circle, gg_switch_state_color[gg_switch]);
50 | spr.fillCircle(gg_switch_location_x, gg_switch_location_y, gg_switch_circle / 2, gg_switch_state_color[gg_switch + 2]);
51 | spr.fillRect(gg_switch_location_x, gg_switch_location_y - gg_switch_circle / 2, gg_switch_rect_width, gg_switch_circle + 1, gg_switch_state_color[gg_switch + 2]);
52 | }
53 | else
54 | {
55 | spr.fillCircle(gg_switch_location_x, gg_switch_location_y, gg_switch_circle, gg_switch_state_color[gg_switch]);
56 | spr.fillCircle(gg_switch_location_x + gg_switch_rect_width, gg_switch_location_y, gg_switch_circle / 2, gg_switch_state_color[gg_switch + 2]);
57 | spr.fillRect(gg_switch_location_x, gg_switch_location_y - gg_switch_circle / 2, gg_switch_rect_width, gg_switch_circle + 1, gg_switch_state_color[gg_switch + 2]);
58 | }
59 | }
60 |
61 | void DISPLAY_INIT() // Display initialization, black background rotation
62 | {
63 | tft.begin();
64 | tft.setRotation(3);
65 | tft.fillScreen(TFT_BLACK);
66 | }
67 |
68 | void Sense_Display() // Sense interface display
69 | {
70 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
71 | spr.setFreeFont(FSSB9);
72 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
73 |
74 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
75 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
76 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
77 |
78 | spr.drawString("Sense", 32, 11, GFXFF);
79 | spr.drawString("Process", 127, 11, GFXFF);
80 | spr.drawString("Network", 231, 11, GFXFF);
81 |
82 | spr.drawLine(0, 2 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 2 * FONT_ROW_HEIGHT, TFT_WHITE);
83 |
84 | spr.setFreeFont(FSS9);
85 | spr.setTextColor(TFT_BLACK, tft.color565(220, 220, 220));
86 | spr.fillRect(127, 53.5, 16 * PIXEL, FONT_ROW_HEIGHT, tft.color565(220, 220, 220));
87 | spr.drawString("Sensor", 130, 56, GFXFF);
88 | }
89 |
90 | void setup()
91 | {
92 | pinMode(A0, INPUT);
93 | DISPLAY_INIT();
94 | pinMode(WIO_KEY_A, INPUT_PULLUP);
95 | pinMode(WIO_KEY_B, INPUT_PULLUP);
96 | pinMode(WIO_KEY_C, INPUT_PULLUP);
97 | }
98 | int gg_storage_is_full = 0;
99 | void Page_tf()
100 | {
101 |
102 | char str_num[1], str_conf[1], str_light[1], str_mic_val[1], str_x_values[8], str_y_value[8], str_z_val[8];
103 | sprintf(str_num, "%d", num);
104 | sprintf(str_conf, "%d", conf_avg);
105 | sprintf(str_light, "%d", light);
106 | sprintf(str_mic_val, "%d", mic_val);
107 | snprintf((char *)str_x_values, 8, "%.2f", x_values);
108 | snprintf((char *)str_y_value, 8, "%.2f", y_value);
109 | snprintf((char *)str_z_val, 8, "%.2f", z_val);
110 |
111 | conf_avg = 0;
112 |
113 | Sense_Display();
114 | spr.setTextColor(TFT_WHITE);
115 | spr.drawString("Save to TF card ", 40, gg_switch_location_y - gg_switch_circle, FONT4);
116 |
117 | if (digitalRead(WIO_KEY_A) == LOW)
118 | {
119 | Serial.println("A Key pressed");
120 | gg_switch_k *= -1;
121 | delay(200);
122 | }
123 | if (digitalRead(WIO_KEY_B) == LOW)
124 | {
125 | Serial.println("B Key pressed");
126 | gg_storage_is_full++;
127 | delay(200);
128 | }
129 |
130 | if (gg_switch_k > 0)
131 | {
132 | gg_switch = 1;
133 | }
134 | else
135 | {
136 | gg_switch = 0;
137 | }
138 |
139 | switch_button_gui(gg_switch_location_x, gg_switch_location_y, gg_switch_circle, gg_switch_rect_width, gg_switch);
140 | // int gg_storage_is_full = 1 ;
141 |
142 | if (gg_storage_is_full % 2)
143 | {
144 | spr.setTextColor(TFT_YELLOW);
145 | spr.setFreeFont(FSSB9);
146 | spr.drawTriangle(148, 155, 159, 132, 170, 155, TFT_YELLOW);
147 | spr.drawString("! ", 158, 140, 2);
148 | spr.drawString("TF card storage space is fully occupied ", 30, 160, 2);
149 | }
150 |
151 | else
152 | {
153 | if (gg_switch == 0)
154 | {
155 | spr.setTextColor(TFT_YELLOW);
156 | spr.setFreeFont(FSSB9);
157 | spr.drawString("Please insert TF card to activate this function ", 10, 140, 2);
158 | }
159 | else
160 | {
161 | spr.fillRect(40, 130, 250, 50, TFT_WHITE);
162 | spr.setTextColor(TFT_BLACK);
163 | spr.setFreeFont(FSSB9);
164 | spr.drawString("Saving has been started", 60, 140, GFXFF);
165 | }
166 | }
167 |
168 | spr.setTextColor(TFT_YELLOW);
169 | spr.drawString("Network:", 10, 220, GFXFF);
170 | spr.setTextColor(tft.color565(254, 0, 0));
171 | spr.drawString("OFF", 100, 220, GFXFF);
172 |
173 | spr.pushSprite(0 + SCREEN_PADDING, 0 + SCREEN_PADDING);
174 | spr.deleteSprite();
175 | }
176 | void loop()
177 | {
178 | Page_tf();
179 | delay(200);
180 | }
181 |
--------------------------------------------------------------------------------
/examples/Process/PAGE_tf/switch.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Seeed-Studio/SenseCraft-Wio/b4f4a40438d0e877676e3b84ae07432ffea0d5cc/examples/Process/PAGE_tf/switch.cpp
--------------------------------------------------------------------------------
/examples/Process/PAGE_tf/switch_ui.h:
--------------------------------------------------------------------------------
1 | #ifndef Morse_h
2 | #define Morse_h
3 |
4 | class Switch_UI
5 | {
6 | public:
7 | Morse(int pin);
8 | void dot();
9 | void dash();
10 | private:
11 | int _pin;
12 | };
13 |
14 | #endif
--------------------------------------------------------------------------------
/examples/Process/Process_main/Process_main.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | #define MOVE_PIXEL_y 20 // Virtual to Reality Moving Distance
11 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
12 | #include "RTC_SAMD51.h"
13 | #include "DateTime.h"
14 | #include
15 |
16 | RTC_SAMD51 rtc;
17 |
18 | DateTime now = DateTime(F(__DATE__), F(__TIME__));
19 |
20 | void DISPLAY_INIT() // Display initialization, black background rotation
21 | {
22 | tft.begin();
23 | tft.setRotation(3);
24 | tft.fillScreen(TFT_BLACK);
25 | }
26 |
27 | void Process_main(int page)
28 | {
29 | //Add page 0 here; page3 For the convenience of testing, this function can be called, or it can be called independently
30 | //case 0 Vision AI log
31 | //case 1 Proccsee Home
32 | //case 2 TinyML example
33 | //case 3 TinyML has entered
34 | switch (page)
35 | {
36 | case 0:
37 | Vision_AI_real_time_analysis();
38 | return;
39 | case 1:
40 | spr.setTextColor(TFT_WHITE);
41 | spr.drawString("Vision AI real-time analysis", 63, 33 + MOVE_PIXEL_y, GFXFF);
42 | spr.fillRect(24, 71 + MOVE_PIXEL_y - 3, 221, FONT_ROW_HEIGHT, tft.color565(0, 204, 2));
43 | break;
44 | case 2:
45 | spr.setTextColor(TFT_WHITE);
46 | spr.drawString("TinyML Example", 107, 32 + MOVE_PIXEL_y, GFXFF);
47 | spr.fillRect(24, 100 + MOVE_PIXEL_y - 3, 135, FONT_ROW_HEIGHT, tft.color565(0, 204, 2));
48 | break;
49 | case 3:
50 | Process_TinyML_ENTER();
51 | return;
52 | default:;
53 | }
54 | spr.setFreeFont(FSS9);
55 | spr.setTextColor(TFT_WHITE);
56 | spr.drawString("Vision AI real-time analysis", 24, 71 + MOVE_PIXEL_y, GFXFF);
57 | spr.drawString("TinyML Example", 24, 100 + MOVE_PIXEL_y, GFXFF);
58 |
59 | spr.setTextColor(tft.color565(169, 169, 169));
60 | spr.drawString("Data Filter(In Development)", 24, 129 + MOVE_PIXEL_y, GFXFF);
61 | }
62 |
63 | void Network_state(int s_key)
64 | {
65 | switch (s_key)
66 | {
67 | case 0:
68 | spr.setTextColor(TFT_RED);
69 | spr.drawString("OFF", 80, 215, GFXFF);
70 | break;
71 | case 1:
72 | spr.setTextColor(TFT_GREEN);
73 | spr.drawString("ON", 80, 215, GFXFF);
74 | break;
75 | default:;
76 | }
77 | spr.setTextColor(TFT_WHITE);
78 | spr.drawString("Network:", 7, 215, GFXFF);
79 | }
80 |
81 | void Process_TinyML_ENTER(void)
82 | {
83 | spr.setTextColor(TFT_WHITE);
84 | spr.drawString("Please scan the QR ", 135, 86, GFXFF);
85 | spr.drawString("code on the screen ", 135, 106, GFXFF);
86 | spr.drawString("to view the Github", 135, 126, GFXFF);
87 | spr.drawString("sample tutorial ", 135, 146, GFXFF);
88 | double PIXELL = 3;
89 |
90 | spr.fillRect(13, 70, 115, 115, TFT_WHITE);
91 | QRCode qrcode;
92 | uint8_t *qrcodeData = (uint8_t *)malloc(qrcode_getBufferSize(5));
93 | qrcode_initText(&qrcode, qrcodeData, 5, 0, "https://wiki.seeedstudio.com/K1100-Getting-Started/#tinyml-section");
94 | for (uint8_t y = 0; y < qrcode.size; y++)
95 | {
96 | // Each horizontal module
97 | for (uint8_t x = 0; x < qrcode.size; x++)
98 | {
99 | if (qrcode_getModule(&qrcode, x, y))
100 | spr.fillRect(x * PIXELL + 15, y * PIXELL + 70 + 2, PIXELL, PIXELL, TFT_BLACK);
101 | }
102 | }
103 |
104 | free(qrcodeData);
105 | }
106 |
107 | int i = 0;
108 | void Vision_AI_real_time_analysis(void) // todo
109 | {
110 | spr.setTextColor(TFT_WHITE);
111 | spr.drawString("Vision AI real-time analysis", 64, 52, GFXFF);
112 | spr.fillRect(40, 73, 216 + 20, 117 + 15, tft.color565(128, 128, 128));
113 | DateTime now = rtc.now();
114 | // Serial.print(now.second(), DEC);
115 | spr.drawString("Time", 52, 80, GFXFF);
116 | spr.drawString("Data", 140, 80, GFXFF);
117 |
118 | char buf_T[4][20];
119 |
120 | uint8_t HH = now.hour();
121 | uint8_t MM = now.minute();
122 | uint8_t SS = now.second();
123 |
124 | int kk = i % 4;
125 | sprintf(buf_T[i % 4], "%02d:%02d:%02d ", HH, MM, SS);
126 | i++;
127 | if (i == 4)
128 | {
129 | i = 0;
130 | }
131 |
132 | for (int i = 0; i < 4; i++)
133 | {
134 | int MM_add = 0;
135 | if (SS + i > 59)
136 | {
137 | MM += 1;
138 | SS -= 60;
139 | }
140 | if (MM > 59)
141 | {
142 | HH += 1;
143 | MM -= 60;
144 | }
145 | sprintf(buf_T[i], " %02d:%02d:%02d ", HH, MM, SS + i);
146 | }
147 | for (int gg = 0; gg < 4; gg++)
148 | {
149 | spr.drawString(buf_T[gg], 45, 103 + gg * 26, GFXFF);
150 | }
151 | }
152 |
153 | void Process_Display(int G, int G_network) // Sense interface display
154 | {
155 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
156 |
157 | // choose func here
158 | Process_main(G);
159 | // Process_TinyML_ENTER();
160 | // Vision_AI_real_time_analysis();
161 | spr.setFreeFont(FSSB9);
162 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
163 |
164 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
165 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
166 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
167 |
168 | spr.setFreeFont(FSS9);
169 | spr.setTextColor(TFT_BLACK);
170 | spr.drawString("Sense", 32, 11, GFXFF);
171 | spr.drawString("Process", 127, 11, GFXFF);
172 | spr.drawString("Network", 231, 11, GFXFF);
173 |
174 | spr.drawLine(0, 2 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 2 * FONT_ROW_HEIGHT, TFT_WHITE);
175 |
176 | Network_state(G_network);
177 |
178 | spr.pushSprite(0, 0);
179 | spr.deleteSprite();
180 | }
181 |
182 | void setup()
183 | {
184 | DISPLAY_INIT();
185 | rtc.begin();
186 | DateTime now = DateTime(F(__DATE__), F(__TIME__));
187 | Serial.println("adjust time!");
188 | rtc.adjust(now);
189 |
190 | pinMode(WIO_KEY_A, INPUT_PULLUP);
191 | pinMode(WIO_KEY_B, INPUT_PULLUP);
192 | pinMode(WIO_KEY_C, INPUT_PULLUP);
193 | }
194 |
195 | int gg_switch = 0;
196 | int gg_switch_flag = 0;
197 | int gg_network_flag = 0;
198 | void loop()
199 | {
200 | // test block begin
201 | if (digitalRead(WIO_KEY_B) == LOW)
202 | {
203 | Serial.println("B Key pressed");
204 | gg_switch++;
205 | delay(200);
206 | }
207 | if (digitalRead(WIO_KEY_C) == LOW)
208 | {
209 | Serial.println("C Key pressed");
210 | gg_network_flag++;
211 | delay(200);
212 | }
213 |
214 | Process_Display(gg_switch % 4, gg_network_flag % 2);
215 | }
216 |
--------------------------------------------------------------------------------
/examples/Process/Process_main/README.md:
--------------------------------------------------------------------------------
1 | # Process part
2 |
3 | The page is implemented as follows according to the modao documentation requirements. Functions are decoupled and can be called independently of each other. As a test ino, burn under example/Process_main and click A to check the network status display in the lower left corner. Click B to view the interfaces in Process. In the Ai vision Log part, due to the limited ability of unfamiliar with ardiuno, the queue of uint8_t and int did not construct the time data currently displayed.
4 |
5 | Process_Display(); //
6 | Process_TinyML_ENTER(); //
7 | Vision_AI_real_time_analysis(); //
8 | Network_state(int s_key); // Change network status 1 display ON 0 display OFF can be imported into Process_Display or anywhere
9 |
10 | | Code | Content | Status|
11 | | :------------ |:---------------:| -----:|
12 | |Vision AI log| Vision_AI_real_time_analysis() |✅ |
13 | |Tiny ml has entered| Process_TinyML_ENTER() |✅✅ |
14 | |Network| Network_state(int s_key)|✅✅|
15 | |Proccsee Home| Network_state(int s_key)|✅✅|
16 |
17 | ## Process_Display()
18 |
19 | draw top three buttons background color default bottom layer
20 |
21 | ## Process_main(int page)
22 |
23 | !!!Note
24 | Add page 0 here; page 3 For the convenience of testing, this function can be called, or it can be called independently
25 |
26 | - case 0 Vision AI log
27 | - case 1 Proccsee Home
28 | - case 2 Tiny ml example
29 | - case 3 Tiny ml has entered
30 |
31 | ## Network_state(int s_key)
32 |
33 | The network status display function Network in the lower left corner. 1 ON 0 OFF
34 |
35 | ## Vision_AI_real_time_analysis(void)
36 |
37 | Vision AI log
38 |
39 | ## Process_TinyML_ENTER()
40 |
41 | This is the interface that TinyML has entered in order to present the QR code.
42 | https://www.arduino.cc/reference/en/libraries/qrcode/ this [library](https://www.arduino.cc/reference/en/libraries/qrcode/)
43 |
44 |
--------------------------------------------------------------------------------
/examples/Sense/Auto-detect/Auto-detect.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
8 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
9 | #define PIXEL 4 // Width of one letter
10 | #define LEFT_SIDE 70
11 | #define HIGHT_SIDE 47
12 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
13 |
14 |
15 | void DISPLAY_INIT() // Display initialization, black background rotation
16 | {
17 | tft.begin();
18 | tft.setRotation(3);
19 | tft.fillScreen(TFT_BLACK);
20 | }
21 |
22 | void Sense_AutoDetecte_Display() //Display screen for accessing sensors
23 | {
24 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
25 |
26 | // put your main code here
27 | spr.setFreeFont(FSSB9);
28 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
29 |
30 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
31 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
32 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
33 |
34 | spr.drawString("Process", 127, 11, GFXFF);
35 | spr.drawString("Network", 231, 11, GFXFF);
36 |
37 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
38 | spr.drawString("Sense", 32, 11, GFXFF);
39 |
40 | spr.drawLine(0, 2 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 2 * FONT_ROW_HEIGHT, TFT_WHITE);
41 |
42 | spr.setFreeFont(FSS9);
43 | spr.setTextColor(TFT_BLACK, tft.color565(220, 220, 220));
44 | spr.fillRect(128, 50, 16 * PIXEL, FONT_ROW_HEIGHT, tft.color565(220, 220, 220));
45 | spr.drawString("Sensor", 132, 54, GFXFF);
46 |
47 | spr.setTextColor(TFT_WHITE, TFT_BLACK);
48 | spr.drawString("Sound", 100 - LEFT_SIDE, 80, GFXFF);
49 | spr.drawString("IMU", 209 - LEFT_SIDE, 80, GFXFF);
50 | spr.drawString("ADD", 316 - LEFT_SIDE, 80, GFXFF);
51 |
52 | spr.setFreeFont(FSS24);
53 | spr.drawString("356", 20, 115 , GFXFF); // Display the value of loudness
54 | spr.setFreeFont(FSS12);
55 | spr.drawString("0.10", 205 - LEFT_SIDE, 102 , GFXFF); //Display the value of IMU X-axis
56 | spr.drawString("-0.23", 205 - LEFT_SIDE, 126 , GFXFF); //Display the value of IMU Y-axis
57 | spr.drawString("-2.33", 205 - LEFT_SIDE, 150 , GFXFF); //Display the value of IMU Z-axis
58 | spr.setFreeFont(FSS9);
59 | spr.drawString("X,Y,Z", 205 - LEFT_SIDE, 174 , GFXFF);
60 |
61 | spr.fillCircle(163, 200, 3, tft.color565(0, 193, 255));
62 | spr.fillCircle(146, 200, 3, tft.color565(220, 220, 220));
63 |
64 | spr.fillRect(244, 117, 40, 40, TFT_WHITE);
65 | spr.fillRect(263, 123, 3, 26, TFT_BLACK);
66 | spr.fillRect(251, 135, 26, 3, TFT_BLACK);
67 |
68 | spr.drawString("Network :", 5, 218 , GFXFF);
69 |
70 | // spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
71 | // spr.drawString("OFF", 82, 218 , GFXFF);
72 |
73 | spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
74 | spr.drawString(" LoRa ", 82, 218 , GFXFF); //Show the network you are in
75 |
76 | spr.pushSprite(0, 0);
77 | spr.deleteSprite();
78 | }
79 |
80 | void Insert_Tip() // Pop-up prompt for sensor insertion
81 | {
82 | spr.createSprite(240, 116);
83 | spr.fillScreen(tft.color565(211, 211, 211));
84 |
85 | spr.setFreeFont(FSS9);
86 | spr.setTextColor(TFT_BLACK, tft.color565(211, 211, 211));
87 | spr.drawString("Please plug in 1 sensor first", 10, 30, GFXFF);
88 |
89 | spr.fillCircle(108, 90, 3, tft.color565(190, 190, 190));
90 | spr.fillCircle(118, 90, 3, tft.color565(140, 140, 140));
91 | spr.fillCircle(128, 90, 3, tft.color565(105, 105, 105));
92 |
93 | spr.pushSprite(40, 64);
94 | spr.deleteSprite();
95 | }
96 |
97 | void Connect_Success_Display() //Connect sensor success alert pop-up.
98 | {
99 | spr.createSprite(240, 116);
100 | spr.fillScreen(tft.color565(211, 211, 211));
101 |
102 | spr.setFreeFont(FSS9);
103 | spr.setTextColor(TFT_BLACK, tft.color565(211, 211, 211));
104 | spr.drawString("Vision AI Sensor connected", 10, 30, GFXFF);
105 |
106 | spr.fillCircle(118, 85, 20, tft.color565(0, 139, 0));
107 | spr.fillCircle(118, 85, 17, tft.color565(211, 211, 211));
108 |
109 | //spr.drawLine(117, 86, 118, 89, tft.color565(0, 255, 0));
110 | spr.fillTriangle(107, 84, 128, 75, 118, 95, tft.color565(0, 139, 0));
111 | spr.fillTriangle(107, 80, 128, 71, 118, 91, tft.color565(211, 211, 211));
112 |
113 | spr.pushSprite(40, 64);
114 | spr.deleteSprite();
115 | }
116 |
117 | void setup() {
118 | DISPLAY_INIT();
119 | }
120 |
121 | void loop() {
122 | Sense_AutoDetecte_Display();
123 | delay(2000);
124 | Insert_Tip();
125 | delay(2000);
126 | Connect_Success_Display();
127 | delay(2000);
128 | }
129 |
--------------------------------------------------------------------------------
/examples/Sense/Built-in/Built-in.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include "Free_Fonts.h"
3 |
4 | TFT_eSPI tft;
5 | TFT_eSprite spr = TFT_eSprite(&tft);
6 |
7 |
8 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
9 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
10 | #define PIXEL 4 // Width of one letter
11 | #define LEFT_SIDE 70
12 | #define HIGHT_SIDE 47
13 | const static unsigned int FONT_ROW_HEIGHT = 22; // The height of a letter
14 |
15 |
16 | void DISPLAY_INIT() // Display initialization, black background rotation
17 | {
18 | tft.begin();
19 | tft.setRotation(3);
20 | tft.fillScreen(TFT_BLACK);
21 | }
22 |
23 | void Sense_BuiltIn_Display() // Wio terminal built-in sensor interface, the main boot screen.
24 | {
25 | spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
26 |
27 | // put your main code here
28 | spr.setFreeFont(FSSB9);
29 | spr.setTextColor(TFT_BLACK, TFT_WHITE);
30 |
31 | spr.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
32 | spr.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
33 | spr.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
34 |
35 | spr.drawString("Process", 127, 11, GFXFF);
36 | spr.drawString("Network", 231, 11, GFXFF);
37 |
38 | spr.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
39 | spr.drawString("Sense", 32, 11, GFXFF);
40 |
41 |
42 | spr.drawLine(0, 2 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 2 * FONT_ROW_HEIGHT, TFT_WHITE);
43 |
44 | spr.setFreeFont(FSS9);
45 | spr.setTextColor(TFT_BLACK, tft.color565(220, 220, 220));
46 | spr.fillRect(128, 50, 16 * PIXEL, FONT_ROW_HEIGHT, tft.color565(220, 220, 220));
47 | spr.drawString("Sensor", 132, 54, GFXFF);
48 |
49 | spr.setTextColor(TFT_WHITE, TFT_BLACK);
50 | spr.drawString("Light", 100 - LEFT_SIDE, 80, GFXFF);
51 | spr.drawString("Sound", 209 - LEFT_SIDE, 80, GFXFF);
52 | spr.drawString("IMU", 316 - LEFT_SIDE, 80, GFXFF);
53 |
54 | spr.setFreeFont(FSS24);
55 | spr.drawString("77", 20, 115 , GFXFF); // Display the value of the light sensor
56 | spr.drawString("356", 125, 115 , GFXFF); // Display the value of loudness
57 | spr.setFreeFont(FSS12);
58 | spr.drawString("0.10", 241, 102 , GFXFF); //Display the value of IMU X-axis
59 | spr.drawString("-0.23", 241, 126 , GFXFF); //Display the value of IMU Y-axis
60 | spr.drawString("-2.33", 241, 150 , GFXFF); //Display the value of IMU Z-axis
61 | spr.setFreeFont(FSS9);
62 | spr.drawString("X,Y,Z", 316 - LEFT_SIDE, 174 , GFXFF);
63 |
64 | spr.fillCircle(146, 200, 3, tft.color565(0, 193, 255));
65 | spr.fillCircle(163, 200, 3, tft.color565(220, 220, 220));
66 |
67 | spr.drawString("Network :", 5, 218 , GFXFF);
68 |
69 | // spr.setTextColor(TFT_RED, TFT_BLACK); //Networking status indication:OFF
70 | // spr.drawString("OFF", 82, 218 , GFXFF);
71 |
72 | spr.setTextColor(TFT_GREEN, TFT_BLACK); //Networking status indication:ON
73 | spr.drawString(" LoRa ", 82, 218 , GFXFF); //Show the network you are in
74 |
75 | spr.pushSprite(0, 0);
76 | spr.deleteSprite();
77 | }
78 |
79 | void setup() {
80 | DISPLAY_INIT();
81 | }
82 |
83 | void loop() {
84 | Sense_BuiltIn_Display();
85 | }
86 |
--------------------------------------------------------------------------------
/examples/Sense/Line-chart/Line-chart.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "disk91_LoRaE5.h"
5 | #include "LIS3DHTR.h"
6 | #include "Seeed_Arduino_GroveAI.h"
7 | #include "seeed_line_chart.h"
8 | #include
9 | #include "Free_Fonts.h"
10 |
11 | TFT_eSPI tft = TFT_eSPI();
12 | #define DATA_MAX_SIZE 30 // maximum size of data
13 | #define MAX_SIZE 30 // maximum size of data
14 | doubles data; // Initilising a doubles type to store data
15 | TFT_eSprite spr = TFT_eSprite(&tft); // Sprite
16 | LIS3DHTR lis;
17 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
18 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
19 | #define PIXEL 4 // Width of one letter
20 |
21 | // Display size settings
22 | #define SCREEN_WIDTH 320
23 | #define SCREEN_HIGH 240
24 | #define SCREEN_PADDING 0
25 | #define PIXEL 4
26 | const static unsigned int FONT_SIZE = 2; // rate
27 | const static unsigned int FONT_ROW_HEIGHT = 22; // px
28 | const static unsigned int FONT_LEFT_START = 0; // px
29 | const static unsigned int FONT_COLOR = TFT_WHITE;
30 | const static unsigned int FONT_BG_COLOR = TFT_RED;
31 | const static unsigned int BACKGROUD = TFT_BLACK;
32 |
33 | void DISPLAY_INIT() // Display initialization, black background rotation
34 | {
35 | tft.begin();
36 | tft.setRotation(3);
37 | tft.fillScreen(TFT_BLACK);
38 | }
39 |
40 | void Sense_Display() // Sense interface display
41 | {
42 |
43 | // spr.createSprite(SCREEN_WIDTH, SCREEN_HIGH);
44 |
45 | tft.setFreeFont(FSSB9);
46 | tft.setTextColor(TFT_BLACK, TFT_WHITE);
47 |
48 | tft.fillRect(4 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
49 | tft.drawString("Sense", 32, 11, GFXFF);
50 |
51 | tft.fillRect(30 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, tft.color565(135, 206, 235));
52 | tft.setTextColor(TFT_BLACK, tft.color565(135, 206, 235));
53 | tft.drawString("Process", 127, 11, GFXFF);
54 |
55 | tft.setTextColor(TFT_BLACK, TFT_WHITE);
56 | tft.fillRect(56 * PIXEL, 0, 21 * PIXEL, FONT_ROW_HEIGHT + 15, TFT_WHITE);
57 | tft.drawString("Network", 231, 11, GFXFF);
58 |
59 | tft.drawLine(0, 2 * FONT_ROW_HEIGHT, SCREEN_WIDTH, 2 * FONT_ROW_HEIGHT, TFT_WHITE);
60 |
61 | tft.setFreeFont(FSS9);
62 | tft.setTextColor(TFT_BLACK, tft.color565(220, 220, 220));
63 | tft.fillRect(127, 53.5, 16 * PIXEL, FONT_ROW_HEIGHT, tft.color565(220, 220, 220));
64 | tft.drawString("Sensor", 130, 56, GFXFF);
65 | }
66 |
67 | void setup()
68 | {
69 | pinMode(A0, INPUT);
70 | tft.begin();
71 | tft.setRotation(3);
72 | tft.fillScreen(TFT_BLACK);
73 | // DISPLAY_INIT();
74 | }
75 |
76 | int brightness;
77 | void loop()
78 | {
79 | // brightness = analogRead(A0);
80 |
81 | Sense_Display();
82 | tft.fillRect(18, 78, 24, 110, TFT_WHITE);
83 |
84 | brightness = analogRead(WIO_MIC);
85 |
86 | if (data.size() > DATA_MAX_SIZE) // keep the old line chart front
87 | {
88 | data.pop(); // this is used to remove the first read variable
89 | }
90 |
91 | data.push(brightness); // read variables and store in data
92 |
93 | // Settings for the line graph
94 | auto content = line_chart(20, 80); //(x,y) where the line graph begins
95 | content
96 | // .height(tft.height() - header.height() * 1.5 - 50) // actual height of the line chart
97 | // .width(tft.width() - content.x() * 2) // actual width of the line chart
98 | .height(120)
99 | .width(260)
100 | .based_on(0.0) // Starting point of y-axis, must be a float
101 | .show_circle(false) // drawing a cirle at each point, default is on.
102 | .value(data) // passing through the data to line graph
103 | .max_size(MAX_SIZE)
104 | .color(TFT_GREEN) // Setting the color for the line
105 | // .backgroud(tft.color565(0,0,0)) // Setting the color for the backgroud
106 | .backgroud(tft.color565(0, 0, 0))
107 | .draw(&tft);
108 |
109 | // spr.fillRect(0, 201, 320, 39, TFT_BLACK);
110 | tft.setFreeFont(FSSB9);
111 | tft.setTextColor(TFT_YELLOW);
112 | tft.drawString("Network:", 10, 220, GFXFF);
113 | tft.setTextColor(tft.color565(254, 0, 0));
114 | tft.drawString("OFF", 100, 220, GFXFF);
115 | // tft.pushSprite(0, 0);
116 | // tft.deleteSprite();
117 | delay(2);
118 | }
119 |
--------------------------------------------------------------------------------
/include/AzureDpsClient.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | class AzureDpsClient
8 | {
9 | public:
10 | AzureDpsClient();
11 | AzureDpsClient(const AzureDpsClient&) = delete;
12 | AzureDpsClient& operator=(const AzureDpsClient&) = delete;
13 |
14 | std::string GetEndpoint() const { return Endpoint; }
15 | void SetEndpoint(const std::string& endpoint) { Endpoint = endpoint; }
16 | std::string GetIdScope() const { return IdScope; }
17 | void SetIdScope(const std::string& idScope) { IdScope = idScope; }
18 | std::string GetRegistrationId() const { return RegistrationId; }
19 | void SetRegistrationId(const std::string& registrationId) { RegistrationId = registrationId; }
20 |
21 | int Init(const std::string& endpoint, const std::string& idScope, const std::string& registrationId);
22 |
23 | std::vector GetSignature(const uint64_t& expirationEpochTime);
24 |
25 | std::string GetMqttClientId();
26 | std::string GetMqttUsername();
27 | std::string GetMqttPassword(const std::string& encryptedSignature, const uint64_t& expirationEpochTime);
28 |
29 | std::string GetRegisterPublishTopic();
30 | std::string GetRegisterSubscribeTopic() const;
31 | int RegisterSubscribeWork(const std::string& topic, const std::vector& payload);
32 | bool IsRegisterOperationCompleted();
33 | int GetWaitBeforeQueryStatusSeconds() const;
34 | std::string GetQueryStatusPublishTopic();
35 |
36 | bool IsAssigned();
37 | std::string GetHubHost();
38 | std::string GetDeviceId();
39 |
40 | private:
41 | std::string Endpoint;
42 | std::string IdScope;
43 | std::string RegistrationId;
44 |
45 | az_iot_provisioning_client ProvClient;
46 |
47 | bool ResponseValid;
48 | std::string ResponseTopic;
49 | std::vector ResponsePayload;
50 | az_iot_provisioning_client_register_response Response;
51 |
52 | private:
53 | static az_iot_provisioning_client_operation_status GetOperationStatus(az_iot_provisioning_client_register_response& response);
54 |
55 | };
56 |
--------------------------------------------------------------------------------
/include/ButtonThread.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef __BUTTON_H__
3 | #define __BUTTON_H__
4 |
5 | #include "Arduino.h"
6 | #include "Seeed_Arduino_ooFreeRTOS.h"
7 | #include "utils.h"
8 |
9 | // create a buttion class use ooFreeRTOS task
10 |
11 | using namespace cpp_freertos;
12 |
13 | class ButtonThread : public Thread
14 | {
15 | public:
16 | ButtonThread(Message &q);
17 |
18 | protected:
19 | virtual void Run();
20 |
21 | private:
22 | uint8_t buttonState; // the current reading from the input pin
23 | uint8_t lastButtonState = LOW; // the previous reading from the input pin
24 |
25 | // the following variables are unsigned longs because the time, measured in
26 | // milliseconds, will quickly become a bigger number than can be stored in an int.
27 | unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
28 | unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
29 |
30 | Message &Mail;
31 |
32 | const uint8_t btn[8] = {WIO_KEY_A, WIO_KEY_B, WIO_KEY_C, WIO_5S_UP, WIO_5S_DOWN, WIO_5S_LEFT, WIO_5S_RIGHT, WIO_5S_PRESS};
33 | };
34 |
35 | #endif // __BUTTON_H__
--------------------------------------------------------------------------------
/include/LoRaThread.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef __LORATHREAD_H__
3 | #define __LORATHREAD_H__
4 |
5 | #include "Arduino.h"
6 | #include "Seeed_Arduino_ooFreeRTOS.h"
7 | #include "SysConfig.h"
8 | #include "disk91_LoRaE5.h"
9 | #include "utils.h"
10 | #include
11 |
12 | // create a buttion class use ooFreeRTOS task
13 |
14 | using namespace cpp_freertos;
15 |
16 | class LoRaThread : public Thread {
17 | public:
18 | LoRaThread(SysConfig &config);
19 | void LoRaPushData(std::vector d);
20 |
21 | private:
22 | void Init();
23 | void Join();
24 | bool SendDeviceInfo();
25 | bool SendVisionAIInfo();
26 | bool SendBuildinSensorData();
27 | bool SendGroveSensorData();
28 | bool SendAiVisionData();
29 | bool SendData(uint8_t *data, uint8_t len, uint8_t ver);
30 |
31 | protected:
32 | virtual void Run();
33 |
34 | private:
35 | SysConfig &cfg;
36 | Disk91_LoRaE5 *lorae5;
37 | const uint8_t v1 = 2;
38 | const uint8_t v2 = 3;
39 | uint8_t downlink_rxBuff[16];
40 | uint8_t downlink_rxSize = 16;
41 | uint8_t downlink_rxPort;
42 | uint8_t frequency;
43 |
44 | std::vector lora_data;
45 | bool lora_data_ready = true;
46 | };
47 |
48 | #endif // __LORATHREAD_H__
--------------------------------------------------------------------------------
/include/SDThread.h:
--------------------------------------------------------------------------------
1 | #ifndef __SDTHREAD_H__
2 | #define __SDTHREAD_H__
3 | #include "DateTime.h"
4 | #include "RTC_SAMD51.h"
5 | #include "SD/Seeed_SD.h"
6 | #include "SysConfig.h"
7 | #include "utils.h"
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | using namespace cpp_freertos;
15 |
16 | class SDThread : public Thread {
17 | public:
18 | SDThread(SysConfig &config);
19 | void SDPushData(std::vector d);
20 |
21 | protected:
22 | virtual void Run();
23 | uint8_t status();
24 | void saveData(String sensorName, int32_t *sensorData, int len, uint8_t type);
25 | void Readdata(String sensorName);
26 |
27 | private:
28 | SysConfig &cfg;
29 |
30 | private:
31 | std::vector sd_data;
32 | bool sd_data_ready = true;
33 | RTC_SAMD51 rtc;
34 | File myFile;
35 | bool is_connected = false;
36 | SemaphoreHandle_t wait_sd_data = NULL;
37 | };
38 |
39 | #endif // __SDTHREAD_H__
--------------------------------------------------------------------------------
/include/SamplerThread.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef __SAMPLER_H
3 | #define __SAMPLER_H
4 | #include "SysConfig.h"
5 | #include "WiFiThread.h"
6 | #include "LoRaThread.h"
7 | #include "SDThread.h"
8 | #include "ui.h"
9 | #include "sensor.h"
10 | #include "utils.h"
11 | #include
12 | #include
13 |
14 | using namespace cpp_freertos;
15 |
16 | class SamplerThread : public Thread {
17 | public:
18 | SamplerThread(SysConfig &config, UI &ui);
19 |
20 | protected:
21 | virtual void Run();
22 |
23 | private:
24 | int DelayInMs;
25 | sensor_base *sensor;
26 |
27 | private:
28 | struct sensor_data sdata;
29 |
30 | UI &display;
31 | SysConfig &cfg;
32 |
33 | private:
34 | WiFiThread *wifi;
35 | LoRaThread *lora;
36 | SDThread *sd;
37 | };
38 |
39 | #endif
--------------------------------------------------------------------------------
/include/Signature.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | std::string GenerateEncryptedSignature(const std::string& symmetricKey, const std::vector& signature);
7 | std::string ComputeDerivedSymmetricKey(const std::string& masterKey, const std::string& registrationId);
8 |
--------------------------------------------------------------------------------
/include/SysConfig.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef __SYSCONFIG_H__
3 | #define __SYSCONFIG_H__
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "utils.h"
10 |
11 |
12 | #include
13 | using namespace cpp_freertos;
14 | class SysConfig {
15 | public:
16 | /* wifi */
17 | String ssid;
18 | String password;
19 | mqtt_server cloud = CLOUD_AZURE;
20 | /* ubidots */
21 | String mqtt_client_name;
22 | String token;
23 | String device_label;
24 | /* azure */
25 | String id_scope;
26 | String registration_id;
27 | String symmetric_key;
28 |
29 | uint8_t lora_frequency;
30 | bool lora_on = false;
31 | bool wifi_on = false;
32 | bool wificonnected = false;
33 | int16_t wifi_rssi = 0;
34 | lora_status_type lora_status = LORA_INIT_START;
35 | int16_t lora_rssi = 0;
36 | int16_t lora_fcnt = 0;
37 | int16_t lora_sucess_cnt = 0;
38 | uint8_t sd_status = 0; // 0- not init, 1- connected, 2- sd full
39 | uint16_t sensor_save_flag = 0;
40 |
41 | static SemaphoreHandle_t lock;
42 |
43 | public:
44 | SysConfig(/* args */);
45 | ~SysConfig();
46 | void init();
47 |
48 | void ReadConfigParam(const String filename, char *prefix_param, String *param);
49 | void ReadAllConfig();
50 |
51 | void WriteConfigParam(char *filename, char *prefix_param, char *param);
52 | void WriteConfigTemp();
53 |
54 | private:
55 | /* data */
56 | bool spi_flash_mount;
57 | bool cfg_available;
58 | Adafruit_USBD_MSC usb_msc;
59 | };
60 |
61 | #endif // __SYSCONFIG_H__
--------------------------------------------------------------------------------
/include/WiFiThread.h:
--------------------------------------------------------------------------------
1 | #ifndef __WIFITHREAD_H__
2 | #define __WIFITHREAD_H__
3 | #include "AzureDpsClient.h"
4 | #include "Seeed_Arduino_ooFreeRTOS.h"
5 | #include "Signature.h"
6 | #include "SysConfig.h"
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #define MQTT_BROKER "industrial.api.ubidots.com"
18 |
19 | #define USE_DPS
20 | #define MQTT_PACKET_SIZE 1024
21 | #define TOKEN_LIFESPAN 3600
22 | #ifndef USE_DPS
23 | #define IOT_CONFIG_IOTHUB "global.azure-devices-provisioning.net"
24 | #define IOT_CONFIG_DEVICE_ID "qian-test"
25 | #endif
26 | #define IOT_CONFIG_GLOBAL_DEVICE_ENDPOINT "global.azure-devices-provisioning.net"
27 | #define IOT_CONFIG_MODEL_ID "dtmi:seeedkk:wioterminal:wioterminal_aziot_example;5"
28 | #define AZ_RETURN_IF_FAILED(exp) \
29 | do { \
30 | az_result const _result = (exp); \
31 | if (az_result_failed(_result)) { \
32 | return _result; \
33 | } \
34 | } while (0)
35 | #define AZ_SPAN_LITERAL_FROM_CHAR(STRING_LITERAL) \
36 | { \
37 | ._internal = { \
38 | .ptr = (uint8_t *)(STRING_LITERAL), \
39 | .size = strlen(STRING_LITERAL), \
40 | }, \
41 | }
42 |
43 | using namespace cpp_freertos;
44 |
45 | class WiFiThread : public Thread {
46 | public:
47 | WiFiThread(SysConfig &config);
48 | void WiFiPushData(std::vector d);
49 |
50 | protected:
51 | virtual void Run();
52 |
53 | int ConnectToHub(az_iot_hub_client *iot_hub_client, const std::string &symmetricKey,
54 | const uint64_t &expirationEpochTime);
55 | int RegisterDeviceToDPS(const std::string &endpoint, const std::string &idScope,
56 | const std::string ®istrationId, const std::string &symmetricKey,
57 | const uint64_t &expirationEpochTime);
58 | void MqttSubscribeCallbackDPS(char *topic, byte *payload, unsigned int length);
59 | void MqttSubscribeCallbackHub(char *topic, byte *payload, unsigned int length);
60 | void HandleCommandMessage(az_span payload, az_iot_hub_client_method_request *command_request);
61 | int SendCommandResponse(az_iot_hub_client_method_request *request, uint16_t status,
62 | az_span response);
63 | void reconnect();
64 | void send_data();
65 |
66 | az_result publish_azure();
67 | void publish_ubidots();
68 |
69 | private:
70 | SysConfig &cfg;
71 |
72 | private:
73 | const char *ssid = "ssid";
74 | const char *password = "password";
75 | std::vector wifi_data;
76 | bool wifi_data_ready = true;
77 | WiFiClientSecure wifiClient;
78 | PubSubClient *client;
79 | WiFiUDP wifi_udp;
80 | NTP *ntp;
81 | std::string HubHost;
82 | std::string DeviceId;
83 | AzureDpsClient DpsClient;
84 | unsigned long DpsPublishTimeOfQueryStatus = 0;
85 | az_iot_hub_client HubClient;
86 | uint64_t reconnectTime;
87 | };
88 |
89 | #endif // __WIFITHREAD_H__
--------------------------------------------------------------------------------
/include/sensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __SENSOR_H
2 | #define __SENSOR_H
3 |
4 | #include "SysConfig.h"
5 | #include
6 | #include "utils.h"
7 |
8 | #define LOG_MAX_SIZE 8
9 |
10 | typedef void (*sampler_callback)(const void *sample_buf, unsigned char byteLenght);
11 |
12 |
13 | class sensor_base
14 | {
15 | public:
16 | static std::vector slog;
17 | virtual void init() = 0;
18 | virtual bool read(struct sensor_data *data) = 0;
19 | virtual const char *get_name() = 0;
20 | void pushlog(const char *msg);
21 | };
22 |
23 | #endif
--------------------------------------------------------------------------------
/include/ui.h:
--------------------------------------------------------------------------------
1 | #ifndef __UI_H__
2 | #define __UI_H__
3 | #include "Free_Fonts.h"
4 | #include "Seeed_Arduino_ooFreeRTOS.h"
5 | #include "SysConfig.h"
6 | #include "seeed_line_chart.h"
7 | #include "sensor.h"
8 | #include "utils.h"
9 | #include
10 | #include
11 | #include
12 |
13 | using namespace cpp_freertos;
14 |
15 | #define SCREEN_WIDTH 320 // Wio Terminal Maximum Width
16 | #define SCREEN_HIGH 240 // Wio Terminal Maximum Height
17 |
18 | #define SENSOR_NUM_MAX 6 // Maximum number of sensors
19 | #define LINE_DATA_MAX_SIZE 30 // maximum size of data
20 | #define DRAW_LINE_MAX_NUM 1 // maximum num of draw line
21 | #define SHOW_LOG_MAX_SIZE 11 // maximum size of log
22 |
23 | enum page_state { NETWORKPAGE, PROCESSPAGE, SENSEPAGE };
24 |
25 | #define NONE_PRESSED 0x0F
26 |
27 | #define FIRST_PAGE 0
28 | #define LORA_PAGE 0
29 | #define WIFI_PAGE 1
30 |
31 | // define a struct with keyboard statemachine
32 | struct PagesStateMachine {
33 | page_state mainstate;
34 | uint8_t key;
35 | int8_t sense_select;
36 | int8_t process_select;
37 | int8_t network_select;
38 | };
39 | struct State {
40 | int8_t current_page;
41 | bool is_next;
42 | int8_t s_select;
43 | };
44 |
45 | struct NetworkState {
46 | int8_t current_network;
47 | struct State nw_state; // network wifi state
48 | struct State nl_state; // network lora state
49 | };
50 |
51 | struct LoRaBandInfo {
52 | char *type;
53 | char *frequency;
54 | char *country;
55 | uint8_t band;
56 | };
57 |
58 | typedef bool (*page_t)(uint8_t key);
59 |
60 | class UI : public Thread {
61 | public:
62 | // UI(TFT_eSPI &lcd, TFT_eSprite &display, SysConfig &config, Message &m1);
63 | UI(TFT_eSPI &lcd, SysConfig &config, Message &m1);
64 |
65 | protected:
66 | virtual void Run();
67 |
68 | public:
69 | void UIPushData(std::vector d);
70 | void UIPushLog(std::vector d);
71 |
72 | private:
73 | TFT_eSPI &tft;
74 | // TFT_eSprite &spr;
75 |
76 | Message &btnMail;
77 |
78 | SysConfig &cfg;
79 |
80 | std::vector s_data;
81 | bool s_data_ready = true;
82 |
83 | std::vector a_log;
84 | bool log_ready = true;
85 |
86 | uint8_t rotate_status = 0;
87 | bool rotate_flag = false;
88 |
89 | uint8_t buff[256];
90 | struct sensor_data sdata;
91 |
92 | struct PagesStateMachine page;
93 |
94 | bool data_refresh; // if new data push, refresh data in screen
95 | bool layout_refresh; // if a button pressed, refresh layout
96 |
97 | /* Label: basic and simple UI elements */
98 | void Label_Network(void);
99 | void Label_Hardware(uint8_t status);
100 | void Label_SensorInfo(String name, String unit, uint8_t pos);
101 | void Label_SensorData(sensor_data& data, uint8_t pos, uint16_t bg_color);
102 | void Label_SensorAdd(uint8_t pos);
103 | void Label_Subtitle(String value);
104 | void Label_CentreBtn(String name, uint16_t color);
105 |
106 | /* Widget: advanced and complex UI elements */
107 | void Widget_Title(uint8_t t);
108 | void Widget_SaveButton(uint8_t button);
109 | void Widget_Signal(int16_t signal, int32_t x, int32_t y);
110 | void Widget_PagePos(int PAGES, int _CHOOSE_PAGE);
111 | void Widget_LoraState(int32_t x, int32_t y);
112 |
113 | void StatusMachine(struct State *ui_state, uint8_t key);
114 |
115 | struct LoRaBandInfo lora_band_info[3] = {
116 | {"US", "915", "North America", 2},
117 | {"EU", "868", "European Region", 1},
118 | {"AU", "915", "Australia", 9},
119 | };
120 |
121 | struct State u_state = {0, true, 0};
122 | void NetworkPageManager(uint8_t keys);
123 | bool Network_Home(uint8_t select);
124 | bool Network_Connect(uint8_t select);
125 | bool Network_LoRa_Band(uint8_t select);
126 | bool Network_LoRa_Confirm(uint8_t select);
127 | bool Network_Disconnect(uint8_t select);
128 |
129 | struct State p_state = {0, true, 0};
130 | void ProcessPageManager(uint8_t keys);
131 | bool Process_1(uint8_t select);
132 | bool Process_2(uint8_t select);
133 |
134 | struct State s_state = {0, true, 0};
135 | void SensePageManager(uint8_t keys);
136 | bool Sensor_1(uint8_t select);
137 | bool Sensor_2(uint8_t select);
138 | bool Sensor_3(uint8_t select);
139 |
140 | void PageMangent(uint8_t key);
141 |
142 | typedef bool (UI::*page_t)(uint8_t key);
143 | typedef void (UI::*main_t)(uint8_t key);
144 |
145 | enum uplink_index { HOME_S, CONNECT, DISCONNECT_S, LORABAND_S, LORACONFIRM };
146 | page_t uplink [5] = { &UI::Network_Home, &UI::Network_Connect, &UI::Network_Disconnect,
147 | &UI::Network_LoRa_Band, &UI::Network_LoRa_Confirm };
148 | page_t process[2] = { &UI::Process_1, &UI::Process_2};
149 | page_t sense [3] = { &UI::Sensor_1, &UI::Sensor_2, &UI::Sensor_3};
150 | main_t get_page[3] = {&UI::NetworkPageManager, &UI::ProcessPageManager, &UI::SensePageManager};
151 | // void (UI::*get_page[3])(uint8_t key) = {&UI::NetworkPageManager, &UI::ProcessPageManager, &UI::SensePageManager};
152 |
153 | private:
154 | // inline function, 4byte uint8_t to float
155 | void uint8_to_float(uint8_t *data, float *destination);
156 |
157 | // temp data
158 | int temp_light;
159 | int temp_mic;
160 | doubles line_chart_data[4];
161 | };
162 |
163 | #endif // __UI_H__
164 |
--------------------------------------------------------------------------------
/include/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef __UTILS_H__
2 | #define __UTILS_H__
3 | #include
4 |
5 | #define LOGSS Serial1
6 | // #define CN_VER
7 | #ifdef CN_VER
8 | #define DEVICE "SenseCAP K1101"
9 | #else
10 | #define DEVICE "SenseCAP K1100"
11 | #endif
12 | #define VERSION "v0.4"
13 |
14 | enum mqtt_server {
15 | CLOUD_AZURE,
16 | CLOUD_UBIDOTS,
17 | };
18 |
19 | enum button_state {
20 | NETWORK_PRESSED,
21 | PROCESS_PRESSED,
22 | SENSE_PRESSED,
23 | UP_PRESSED,
24 | DOWN_PRESSED,
25 | LEFT_PRESSED,
26 | RIGHT_PRESSED,
27 | SELECT_PRESSED,
28 | };
29 |
30 | enum lora_status_type {
31 | LORA_INIT_START,
32 | LORA_INIT_FAILED,
33 | LORA_INIT_SUCCESS,
34 | LORA_JOIN_FAILED,
35 | LORA_JOIN_SUCCESS,
36 | LORA_SEND_FAILED,
37 | LORA_SEND_SUCCESS,
38 | };
39 |
40 | enum sensor_data_type {
41 | SENSOR_DATA_TYPE_INT32 = 0,
42 | SENSOR_DATA_TYPE_FLOAT,
43 | };
44 |
45 | enum sensor_ui_type {
46 | SENSOR_UI_TYPE_NORMAL = 0,
47 | SENSOR_UI_TYPE_AVERAGE,
48 | };
49 |
50 | struct sensor_data {
51 | const char *name;
52 | const char *data_unit;
53 | const void *data;
54 | unsigned char size;
55 | uint16_t id;
56 | bool status; // 0: normal, 1: error
57 | uint8_t data_type = 0; // 0: int32_t, 1: float(*100)
58 | uint8_t ui_type = 0; // 0: normal, 1: average value
59 | };
60 |
61 | struct log_data {
62 | char data[64];
63 | uint32_t time;
64 | };
65 |
66 | enum sensor_type {
67 | /* buildin sensor */
68 | BUILDIN_LIGHT = 1,
69 | BUILDIN_MIC,
70 | LIS3DHTRSENSOR,
71 | /* grove i2c sensor */
72 | GROVE_VISIONAI,
73 | GROVE_SHT4X,
74 | GROVE_SGP30,
75 | GROVE_VL53L0X,
76 | /* grove analog sensor */
77 | GROVE_SOIL,
78 | };
79 |
80 | enum lora_freq {
81 | UNDEFINED,
82 | EU868,
83 | US915,
84 | AS923_1,
85 | AS923_2,
86 | AS923_3,
87 | AS923_4,
88 | KR920,
89 | IN865,
90 | AU915,
91 | };
92 |
93 | #ifdef DEBUG
94 | extern void LogMemoryUsage(const char *s);
95 | extern void LogHeapChange(const char *s);
96 | extern void LogTaskTrace();
97 | #endif // DEBUG
98 |
99 | #endif // __UTILS_H__
100 |
--------------------------------------------------------------------------------
/platformio.ini:
--------------------------------------------------------------------------------
1 | [env:seeed_wio_terminal]
2 | platform = atmelsam
3 | board = seeed_wio_terminal
4 | framework = arduino
5 | platform_packages = framework-arduino-samd-seeed@https://github.com/Seeed-Studio/ArduinoCore-samd.git#k1100
6 | lib_deps =
7 | https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi
8 | https://github.com/Seeed-Studio/Seeed_Arduino_rpcUnified
9 | https://github.com/Seeed-Studio/Seeed_Arduino_mbedtls
10 | https://github.com/IsQianGe/pubsubclient.git
11 | https://github.com/Seeed-Studio/Seeed_Arduino_FS
12 | https://github.com/Seeed-Studio/Seeed_Arduino_SFUD
13 | https://github.com/Seeed-Studio/Seeed_Arduino_FreeRTOS#k1100
14 | https://github.com/Seeed-Studio/Seeed_Arduino_ooFreeRTOS
15 | https://github.com/Seeed-Studio/Seeed_Arduino_Linechart
16 | https://github.com/Seeed-Studio/Seeed_Arduino_GroveAI#k1100
17 | https://github.com/Seeed-Studio/Seeed_Arduino_LoRaE5
18 | https://github.com/Seeed-Studio/Seeed_Arduino_LIS3DHTR
19 | https://github.com/Seeed-Studio/Seeed_Arduino_LCD
20 | https://github.com/LynnL4/Adafruit_TinyUSB_Arduino
21 | https://github.com/ricmoo/QRCode
22 | https://github.com/IsQianGe/Arduino_sht4x_softwire
23 | https://github.com/IsQianGe/Arduino_sgp30_softwire
24 | https://github.com/Seeed-Studio/Grove-Ranging-sensor-VL53L0X#K1101
25 | https://github.com/Seeed-Studio/Arduino_Software_I2C#k1100
26 | adafruit/Adafruit Zero DMA Library
27 | SPI
28 | Wire
29 | SoftwareSerial
30 | https://github.com/Seeed-Studio/Seeed_Arduino_RTC
31 | https://github.com/IsQianGe/CSV-Parser-for-Arduino.git
32 | https://github.com/sstaub/NTP
33 | https://github.com/SeeedJP/pio-azure-sdk-for-c#1.1.0
34 |
35 | build_unflags = -std=gnu++11
36 |
37 | build_flags =
38 | -Wl,-u,_printf_float
39 | -Wl,-u,_scanf_float
40 | -Wl,--wrap,_write
41 | -Wl,-u,__wrap__write
42 | -DARDUINO_WIO_TERMINAL
43 | -DSEEED_K1100_DEV_KIT
44 | -Wl,--wrap=malloc -Wl,--wrap=free -Wl,--wrap=calloc -Wl,--wrap=realloc
45 | -DAZ_NO_LOGGING
46 | -DDEBUG=1
47 | -DUSE_TINYUSB
48 | -std=gnu++14
49 | -DCM_DEBUG
50 | -Isrc/cm_backtrace
51 | -DUSE_FREERTOS
52 | -I"${platformio.libdeps_dir}/seeed_wio_terminal/Seeed Arduino FreeRTOS/src"
--------------------------------------------------------------------------------
/src/AzureDpsClient.cpp:
--------------------------------------------------------------------------------
1 | #include "AzureDpsClient.h"
2 | #include
3 | #include
4 |
5 | static constexpr size_t SignatureMaxSize = 256;
6 | static constexpr size_t MqttClientIdMaxSize = 128;
7 | static constexpr size_t MqttUsernameMaxSize = 128;
8 | static constexpr size_t MqttPasswordMaxSize = 300;
9 | static constexpr size_t RegisterPublishTopicMaxSize = 128;
10 | static constexpr size_t QueryStatusPublishTopicMaxSize = 256;
11 |
12 | AzureDpsClient::AzureDpsClient() :
13 | ResponseValid{ false }
14 | {
15 | }
16 |
17 | int AzureDpsClient::Init(const std::string& endpoint, const std::string& idScope, const std::string& registrationId)
18 | {
19 | ResponseValid = false;
20 |
21 | Endpoint = endpoint;
22 | IdScope = idScope;
23 | RegistrationId = registrationId;
24 |
25 | const az_span endpointSpan{ az_span_create((uint8_t*)&Endpoint[0], Endpoint.size()) };
26 | const az_span idScopeSpan{ az_span_create((uint8_t*)&IdScope[0], IdScope.size()) };
27 | const az_span registrationIdSpan{ az_span_create((uint8_t*)&RegistrationId[0], RegistrationId.size()) };
28 | if (az_result_failed(az_iot_provisioning_client_init(&ProvClient, endpointSpan, idScopeSpan, registrationIdSpan, NULL))) return -1;
29 |
30 | return 0;
31 | }
32 |
33 | std::vector AzureDpsClient::GetSignature(const uint64_t& expirationEpochTime)
34 | {
35 | uint8_t signature[SignatureMaxSize];
36 | az_span signatureSpan = az_span_create(signature, sizeof(signature));
37 | az_span signatureValidSpan;
38 | if (az_result_failed(az_iot_provisioning_client_sas_get_signature(&ProvClient, expirationEpochTime, signatureSpan, &signatureValidSpan))) return std::vector();
39 |
40 | return std::vector(az_span_ptr(signatureValidSpan), az_span_ptr(signatureValidSpan) + az_span_size(signatureValidSpan));
41 | }
42 |
43 | std::string AzureDpsClient::GetMqttClientId()
44 | {
45 | char mqttClientId[MqttClientIdMaxSize];
46 | if (az_result_failed(az_iot_provisioning_client_get_client_id(&ProvClient, mqttClientId, sizeof(mqttClientId), NULL))) return std::string();
47 |
48 | return mqttClientId;
49 | }
50 |
51 | std::string AzureDpsClient::GetMqttUsername()
52 | {
53 | char mqttUsername[MqttUsernameMaxSize];
54 | if (az_result_failed(az_iot_provisioning_client_get_user_name(&ProvClient, mqttUsername, sizeof(mqttUsername), NULL))) return std::string();
55 |
56 | return mqttUsername;
57 | }
58 |
59 | std::string AzureDpsClient::GetMqttPassword(const std::string& encryptedSignature, const uint64_t& expirationEpochTime)
60 | {
61 | char mqttPassword[MqttPasswordMaxSize];
62 | az_span encryptedSignatureSpan = az_span_create((uint8_t*)&encryptedSignature[0], encryptedSignature.size());
63 | if (az_result_failed(az_iot_provisioning_client_sas_get_password(&ProvClient, encryptedSignatureSpan, expirationEpochTime, AZ_SPAN_EMPTY, mqttPassword, sizeof(mqttPassword), NULL))) return std::string();
64 |
65 | return mqttPassword;
66 | }
67 |
68 | std::string AzureDpsClient::GetRegisterPublishTopic()
69 | {
70 | char registerPublishTopic[RegisterPublishTopicMaxSize];
71 | if (az_result_failed(az_iot_provisioning_client_register_get_publish_topic(&ProvClient, registerPublishTopic, sizeof(registerPublishTopic), NULL))) return std::string();
72 |
73 | return registerPublishTopic;
74 | }
75 |
76 | std::string AzureDpsClient::GetRegisterSubscribeTopic() const
77 | {
78 | return AZ_IOT_PROVISIONING_CLIENT_REGISTER_SUBSCRIBE_TOPIC;
79 | }
80 |
81 | int AzureDpsClient::RegisterSubscribeWork(const std::string& topic, const std::vector& payload)
82 | {
83 | ResponseValid = false;
84 |
85 | ResponseTopic = topic;
86 | ResponsePayload = payload;
87 |
88 | if (az_result_failed(az_iot_provisioning_client_parse_received_topic_and_payload(&ProvClient, az_span_create((uint8_t*)&ResponseTopic[0], ResponseTopic.size()), az_span_create((uint8_t*)&ResponsePayload[0], ResponsePayload.size()), &Response))) return -1;
89 |
90 | ResponseValid = true;
91 |
92 | return 0;
93 | }
94 |
95 | bool AzureDpsClient::IsRegisterOperationCompleted()
96 | {
97 | if (!ResponseValid) return false;
98 |
99 | return az_iot_provisioning_client_operation_complete(GetOperationStatus(Response));
100 | }
101 |
102 | int AzureDpsClient::GetWaitBeforeQueryStatusSeconds() const
103 | {
104 | if (!ResponseValid) return 0;
105 |
106 | return Response.retry_after_seconds;
107 | }
108 |
109 | std::string AzureDpsClient::GetQueryStatusPublishTopic()
110 | {
111 | if (!ResponseValid) return std::string();
112 |
113 | char queryStatusPublishTopic[QueryStatusPublishTopicMaxSize];
114 | if (az_result_failed(az_iot_provisioning_client_query_status_get_publish_topic(&ProvClient, Response.operation_id, queryStatusPublishTopic, sizeof(queryStatusPublishTopic), NULL))) return std::string();
115 |
116 | return queryStatusPublishTopic;
117 | }
118 |
119 | bool AzureDpsClient::IsAssigned()
120 | {
121 | if (!ResponseValid) return false;
122 |
123 | return GetOperationStatus(Response) == AZ_IOT_PROVISIONING_STATUS_ASSIGNED;
124 | }
125 |
126 | std::string AzureDpsClient::GetHubHost()
127 | {
128 | if (!IsAssigned()) return std::string();
129 |
130 | const az_span& span{ Response.registration_state.assigned_hub_hostname };
131 | return std::string(az_span_ptr(span), az_span_ptr(span) + az_span_size(span));
132 | }
133 |
134 | std::string AzureDpsClient::GetDeviceId()
135 | {
136 | if (!IsAssigned()) return std::string();
137 |
138 | const az_span& span{ Response.registration_state.device_id };
139 | return std::string(az_span_ptr(span), az_span_ptr(span) + az_span_size(span));
140 | }
141 |
142 | az_iot_provisioning_client_operation_status AzureDpsClient::GetOperationStatus(az_iot_provisioning_client_register_response& response)
143 | {
144 | return response.operation_status;
145 | }
146 |
--------------------------------------------------------------------------------
/src/ButtonThread.cpp:
--------------------------------------------------------------------------------
1 | #include "ButtonThread.h"
2 |
3 | ButtonThread::ButtonThread(Message &m) : Thread("ButtonThread", 128, 3), Mail(m) {
4 | Start();
5 | };
6 |
7 | void ButtonThread::Run() {
8 | LOGSS.println("Starting ButtonThread ");
9 | for (uint8_t i = 0; i < 8; i++) {
10 | pinMode(btn[i], INPUT_PULLUP);
11 | }
12 | uint8_t Message[8];
13 | while (true) {
14 | Delay(Ticks::MsToTicks(10));
15 |
16 | for (uint8_t i = 0; i < 8; i++) {
17 | if (digitalRead(btn[i]) == LOW) {
18 | Delay(Ticks::MsToTicks(100));
19 | if (digitalRead(btn[i]) == LOW) {
20 | // avoid send 0 to Message
21 | Message[0] = i + 1;
22 | Mail.Send(Message, strlen((const char *)Message));
23 | }
24 | }
25 | }
26 | // LOGSS.printf("ButtonThread Free Bytes Remaining %d\r\n",
27 | // uxTaskGetStackHighWaterMark(GetHandle()));
28 | }
29 | }
--------------------------------------------------------------------------------
/src/FreeRTOSMemory.cpp:
--------------------------------------------------------------------------------
1 | #include "FreeRTOS.h"
2 | #include
3 | #if 0
4 | // #ifdef __cplusplus
5 | // extern "C" {
6 | // #endif
7 | // void *malloc(size_t size) {
8 | // /* Call the FreeRTOS version of malloc. */
9 | // return pvPortMalloc(size);
10 | // }
11 | // void free(void *ptr) {
12 | // /* Call the FreeRTOS version of free. */
13 | // vPortFree(ptr);
14 | // }
15 |
16 | // #ifdef __cplusplus
17 | // }
18 | // #endif
19 |
20 | /*inline void *operator new(size_t size)
21 | {
22 | void *p;
23 | if(uxTaskGetNumberOfTasks())
24 | p=pvPortMalloc(size);
25 | else
26 | p=malloc(size);
27 | return p;
28 | }
29 | inline void operator delete(void *p) noexcept
30 | {
31 | if(uxTaskGetNumberOfTasks())
32 | vPortFree( p );
33 | else
34 | free( p );
35 | p = NULL;
36 | }*/
37 |
38 | // Define the �new� operator for C++ to use the freeRTOS memory management
39 | // functions. THIS IS NOT OPTIONAL!
40 | //
41 | void *operator new(size_t size) {
42 | void *p;
43 |
44 | if (uxTaskGetNumberOfTasks())
45 | p = pvPortMalloc(size);
46 | else
47 | p = malloc(size);
48 |
49 | /*#ifdef __EXCEPTIONS
50 | if (p==0) // did pvPortMalloc succeed?
51 | throw std::bad_alloc(); // ANSI/ISO compliant behavior
52 | #endif*/
53 |
54 | return p;
55 | }
56 |
57 | //
58 | // Define the �delete� operator for C++ to use the freeRTOS memory management
59 | // functions. THIS IS NOT OPTIONAL!
60 | //
61 | void operator delete(void *p) noexcept {
62 |
63 | if (uxTaskGetNumberOfTasks())
64 | vPortFree(p);
65 | else
66 | free(p);
67 |
68 | p = NULL;
69 | }
70 |
71 | void *operator new[](size_t size) {
72 | void *p;
73 |
74 | if (uxTaskGetNumberOfTasks())
75 | p = pvPortMalloc(size);
76 | else
77 | p = malloc(size);
78 |
79 | /*#ifdef __EXCEPTIONS
80 | if (p==0) // did pvPortMalloc succeed?
81 | throw std::bad_alloc(); // ANSI/ISO compliant behavior
82 | #endif*/
83 |
84 | return p;
85 | }
86 |
87 | //
88 | // Define the �delete� operator for C++ to use the freeRTOS memory management
89 | // functions. THIS IS NOT OPTIONAL!
90 | //
91 | void operator delete[](void *p) noexcept {
92 |
93 | if (uxTaskGetNumberOfTasks())
94 | vPortFree(p);
95 | else
96 | free(p);
97 |
98 | p = NULL;
99 | }
100 | #endif
--------------------------------------------------------------------------------
/src/SDThread.cpp:
--------------------------------------------------------------------------------
1 | #include "SDThread.h"
2 | #include "utils.h"
3 |
4 | SDThread::SDThread(SysConfig &config) : Thread("SDThread", 128 * 22, 2), cfg(config) {
5 | Start();
6 | }
7 |
8 | // 0- not init, 1- connected, 2- sd full
9 | uint8_t SDThread::status() {
10 | uint64_t cardSize;
11 | if (cfg.sd_status == 0) {
12 | SD.end();
13 | if (!SD.begin(SDCARD_SS_PIN, SDCARD_SPI, 4000000UL)) { // SD卡
14 | LOGSS.println("initialization failed!");
15 | return 0;
16 | }
17 | }
18 | cardSize = SD.totalBytes();
19 | if (cardSize == 0) {
20 | LOGSS.println("SD card is disconnected!");
21 | return 0;
22 | }
23 | cfg.sd_status = 1;
24 | if (cardSize - SD.usedBytes() < 1024 * 1024) {
25 | LOGSS.println("SD card is full!");
26 | return 2;
27 | }
28 | return 1;
29 | }
30 | //保存传感器数值到SD卡,参数:传感器名(同时也是文件名称),数据,数据长度
31 | void SDThread::saveData(String sensorName, int32_t *sensorData, int len, uint8_t type) {
32 | String fileName = sensorName + ".csv";
33 | // LOGSS.println(fileName);
34 | if (SD.exists(fileName)) // header只写一次
35 | {
36 | myFile = SD.open(fileName, FILE_WRITE); //追加写模式
37 | LOGSS.printf("file %s does not found, creating...\r\n", fileName.c_str());
38 | myFile.print(sensorName + ",");
39 | myFile.print("timestamp,");
40 | for (int i = 0; i < len - 1; i++) {
41 | myFile.print("data[" + String(i + 1) + "]");
42 | myFile.print(",");
43 | }
44 | myFile.println("data[" + String(len) + "]");
45 | myFile.close();
46 | }
47 | myFile = SD.open(fileName, FILE_APPEND); //追加写模式
48 | myFile.print(sensorName);
49 | myFile.print(",");
50 |
51 | DateTime now = rtc.now(); //读写当前时间
52 | myFile.print(String(now.year()) + "-" + String(now.month()) + "-" + String(now.day()) + " " +
53 | String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second()) +
54 | ",");
55 |
56 | for (int i = 0; i < len; i++) //写入传感器值
57 | {
58 | /* 根据传感器值类型进行写入 */
59 | if (type == SENSOR_DATA_TYPE_FLOAT) {
60 | myFile.print(sensorData[i]/100);
61 | myFile.print(".");
62 | myFile.print(sensorData[i]%100);
63 | } else {
64 | myFile.print(sensorData[i]);
65 | }
66 | /* 判断是否写完所有传感器值 */
67 | if (i+1 < len) {
68 | myFile.print(",");
69 | } else {
70 | myFile.println(" ");
71 | }
72 | }
73 |
74 | myFile.close();
75 | }
76 |
77 | void SDThread::Readdata(String sensorName) {
78 | CSV_Parser cp(/*format*/ "ssffff", /*has_header*/ true, /*delimiter*/ ',');
79 |
80 | String fileName = sensorName + ".csv";
81 |
82 | char arr[sensorName.length() + 1];
83 | strcpy(arr, sensorName.c_str());
84 | if (cp.readSDfile2(fileName)) { //读模式打开文件,读header
85 | char **column_1 = (char **)cp[arr];
86 | char **column_2 = (char **)cp["timestamp"];
87 | float *column_3 = (float *)cp["data1"];
88 | float *column_4 = (float *)cp["data2"];
89 | float *column_5 = (float *)cp["data3"];
90 | float *column_6 = (float *)cp["data4"];
91 | // float *column_7 = (float*)cp["data5"];
92 |
93 | for (int i = 0; i < cp.getRowsCount(); i++) { //解析csv文件
94 | LOGSS.print(column_1[i]);
95 | LOGSS.print(" - ");
96 | LOGSS.print(column_2[i]);
97 | LOGSS.print(" - ");
98 | LOGSS.print(column_3[i], DEC);
99 | LOGSS.print(" - ");
100 | LOGSS.print(column_4[i], DEC);
101 | LOGSS.print(" - ");
102 | LOGSS.print(column_5[i], DEC);
103 | LOGSS.print(" - ");
104 | LOGSS.print(column_6[i], DEC);
105 | LOGSS.println();
106 | // LOGSS.print(column_6[i], DEC); LOGSS.print(" - ");
107 | // LOGSS.print(column_7[i], DEC); LOGSS.println();
108 | }
109 |
110 | // output parsed values (allows to check that the file was parsed correctly)
111 | cp.print(); // assumes that "LOGSS.begin()" was called before (otherwise it won't work)
112 | } else {
113 | LOGSS.println("ERROR: File does not exist...");
114 | }
115 | }
116 |
117 | void SDThread::Run() {
118 | if (wait_sd_data == NULL) {
119 | wait_sd_data = xSemaphoreCreateBinary();
120 | }
121 | rtc.begin();
122 | DateTime now = DateTime(F(__DATE__), F(__TIME__));
123 | rtc.adjust(now);
124 | now = rtc.now();
125 | while (true) {
126 | if (xSemaphoreTake(wait_sd_data, portMAX_DELAY) == pdTRUE) {
127 | sd_data_ready = false;
128 | for (auto data : sd_data) {
129 | if (cfg.sensor_save_flag & (1 << data.id)) {
130 | cfg.sd_status = status();
131 | if (cfg.sd_status == 1) {
132 | saveData(String(data.name), (int32_t *)data.data, data.size/4,
133 | data.data_type);
134 | }
135 | }
136 | }
137 | sd_data_ready = true;
138 | }
139 | Delay(Ticks::MsToTicks(1000));
140 | }
141 | }
142 |
143 | void SDThread::SDPushData(std::vector d) {
144 | // A loop to deep copy param of d vector into new sd_data queue
145 | // by Iterative method
146 | if (sd_data_ready) {
147 | sd_data.clear();
148 | sd_data.shrink_to_fit();
149 | for (auto data : d)
150 | sd_data.push_back(*data);
151 | if (wait_sd_data != NULL) {
152 | xSemaphoreGive(wait_sd_data);
153 | }
154 | }
155 | }
--------------------------------------------------------------------------------
/src/SamplerThread.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "SamplerThread.h"
3 | #include "sensor.h"
4 | #include "sensors/FakeSensor.h"
5 | #include "sensors/LIS3DHTRSensor.h"
6 | #include "sensors/buildin_light_sensor.h"
7 | #include "sensors/buildin_mic.h"
8 | #include "sensors/grove_sgp30_sensor.h"
9 | #include "sensors/grove_sht4x_sensor.h"
10 | #include "sensors/grove_vl53l0x_sensor.h"
11 | #include "sensors/grove_soil_sensor.h"
12 | #include "sensors/grove_visionai_sensor.h"
13 | #include "sensors/SensorsUtils.h"
14 | #include
15 |
16 | SamplerThread::SamplerThread(SysConfig &config, UI &ui)
17 | : Thread("SamplerThread", 128 * 4, 1), cfg(config), display(ui) {
18 | // start thread when created
19 | Start();
20 | }
21 |
22 | void SamplerThread::Run() {
23 | wifi = new WiFiThread(cfg);
24 | lora = new LoRaThread(cfg);
25 | sd = new SDThread(cfg);
26 |
27 | std::vector sensors;
28 | sensors.push_back(new buildin_light_sensor());
29 | sensors.push_back(new buildin_mic());
30 | sensors.push_back(new LIS3DHTRSensor()); // buildin-imu
31 | sensors.push_back(new grove_soil_sensor());
32 | sensors.push_back(new grove_sht4x_sensor());
33 | sensors.push_back(new grove_sgp30_sensor());
34 | sensors.push_back(new grove_vl53l0x_sensor());
35 | sensors.push_back(new grove_visionai_sensor());
36 | // sensors.push_back(new FakeSensor());
37 |
38 | for (auto sensor : sensors) {
39 | sensor->init();
40 | }
41 |
42 | while (true) {
43 | std::vector datas;
44 | for (auto sensor : sensors) {
45 | if (sensor->read(&sdata)) {
46 | // LOGSS.printf("Sampling %s\r\n", sdata.name);
47 | // for (size_t i = 0; i < sdata.size; i++) {
48 | // LOGSS.printf("%02x ", ((uint8_t *)sdata.data)[i]);
49 | // }
50 | // for (auto sensor : sensors) {
51 | // LOGSS.printf("Sampling %s\n", sensor->get_name());
52 | // }
53 | // LOGSS.println(sensors.size());
54 | // sensorMail.Send((void *)&sdata, sizeof(sdata));
55 | // deep Copy data into datas vector
56 | datas.push_back(new sensor_data(sdata));
57 | }
58 | // LOGSS.println("SamplerThread");
59 | }
60 | lora->LoRaPushData(datas);
61 | wifi->WiFiPushData(datas);
62 | sd->SDPushData(datas);
63 | display.UIPushData(datas);
64 | display.UIPushLog(sensor_base::slog);
65 | for (auto data : datas) {
66 | delete data;
67 | }
68 | datas.clear();
69 | datas.shrink_to_fit();
70 | Delay(Ticks::MsToTicks(SENSOR_READ_DELAY));
71 | // LOGSS.printf("SamplerThread Stacks Free Bytes Remaining %d\r\n",
72 | // uxTaskGetStackHighWaterMark(GetHandle()));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/Signature.cpp:
--------------------------------------------------------------------------------
1 | #include "Signature.h"
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | std::string GenerateEncryptedSignature(const std::string& symmetricKey, const std::vector& signature)
8 | {
9 | unsigned char base64DecodedSymmetricKey[symmetricKey.size() + 1];
10 |
11 | // Base64-decode device key
12 | // <-- symmetricKey
13 | // --> base64DecodedSymmetricKey
14 | size_t base64DecodedSymmetricKeyLength;
15 | if (mbedtls_base64_decode(base64DecodedSymmetricKey, sizeof(base64DecodedSymmetricKey), &base64DecodedSymmetricKeyLength, (unsigned char*)&symmetricKey[0], symmetricKey.size()) != 0) abort();
16 | if (base64DecodedSymmetricKeyLength == 0) abort();
17 |
18 | // SHA-256 encrypt
19 | // <-- base64DecodedSymmetricKey
20 | // <-- signature
21 | // --> encryptedSignature
22 | uint8_t encryptedSignature[32]; // SHA-256
23 | mbedtls_md_context_t ctx;
24 | const mbedtls_md_type_t mdType{ MBEDTLS_MD_SHA256 };
25 | if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(mdType), 1) != 0) abort();
26 | if (mbedtls_md_hmac_starts(&ctx, base64DecodedSymmetricKey, base64DecodedSymmetricKeyLength) != 0) abort();
27 | if (mbedtls_md_hmac_update(&ctx, &signature[0], signature.size()) != 0) abort();
28 | if (mbedtls_md_hmac_finish(&ctx, encryptedSignature) != 0) abort();
29 | mbedtls_md_free(&ctx);
30 |
31 | // Base64 encode encrypted signature
32 | // <-- encryptedSignature
33 | // --> b64encHmacsha256Signature
34 | char b64encHmacsha256Signature[(size_t)(sizeof(encryptedSignature) * 1.5f) + 1];
35 | size_t b64encHmacsha256SignatureLength;
36 | if (mbedtls_base64_encode((unsigned char*)b64encHmacsha256Signature, sizeof(b64encHmacsha256Signature), &b64encHmacsha256SignatureLength, encryptedSignature, mbedtls_md_get_size(mbedtls_md_info_from_type(mdType))) != 0) abort();
37 |
38 | return std::string(b64encHmacsha256Signature, b64encHmacsha256SignatureLength);
39 | }
40 |
41 | std::string ComputeDerivedSymmetricKey(const std::string& masterKey, const std::string& registrationId)
42 | {
43 | unsigned char base64DecodedMasterKey[masterKey.size() + 1];
44 |
45 | // Base64-decode device key
46 | // <-- masterKey
47 | // --> base64DecodedMasterKey
48 | size_t base64DecodedMasterKeyLength;
49 | if (mbedtls_base64_decode(base64DecodedMasterKey, sizeof(base64DecodedMasterKey), &base64DecodedMasterKeyLength, (unsigned char*)&masterKey[0], masterKey.size()) != 0) abort();
50 | if (base64DecodedMasterKeyLength == 0) abort();
51 |
52 | // SHA-256 encrypt
53 | // <-- base64DecodedMasterKey
54 | // <-- registrationId
55 | // --> derivedSymmetricKey
56 | uint8_t derivedSymmetricKey[32]; // SHA-256
57 | mbedtls_md_context_t ctx;
58 | const mbedtls_md_type_t mdType{ MBEDTLS_MD_SHA256 };
59 | if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(mdType), 1) != 0) abort();
60 | if (mbedtls_md_hmac_starts(&ctx, base64DecodedMasterKey, base64DecodedMasterKeyLength) != 0) abort();
61 | if (mbedtls_md_hmac_update(&ctx, (const unsigned char*)®istrationId[0], registrationId.size()) != 0) abort();
62 | if (mbedtls_md_hmac_finish(&ctx, derivedSymmetricKey) != 0) abort();
63 | mbedtls_md_free(&ctx);
64 |
65 | // Base64 encode encrypted signature
66 | // <-- derivedSymmetricKey
67 | // --> b64encDerivedSymmetricKey
68 | char b64encDerivedSymmetricKey[(size_t)(sizeof(derivedSymmetricKey) * 1.5f) + 1];
69 | size_t b64encDerivedSymmetricKeyLength;
70 | if (mbedtls_base64_encode((unsigned char*)b64encDerivedSymmetricKey, sizeof(b64encDerivedSymmetricKey), &b64encDerivedSymmetricKeyLength, derivedSymmetricKey, mbedtls_md_get_size(mbedtls_md_info_from_type(mdType))) != 0) abort();
71 |
72 | return std::string(b64encDerivedSymmetricKey, b64encDerivedSymmetricKeyLength);
73 | }
74 |
--------------------------------------------------------------------------------
/src/SysConfig.cpp:
--------------------------------------------------------------------------------
1 | #include "SysConfig.h"
2 |
3 | using namespace cpp_freertos;
4 |
5 | SemaphoreHandle_t SysConfig::lock = NULL;
6 |
7 | extern "C" {
8 | void cm_printf(const char *format, ...) {
9 | char print_buf[1024] = {0};
10 |
11 | va_list args;
12 | va_start(args, format);
13 | int r = vsnprintf(print_buf, sizeof(print_buf), format, args);
14 | va_end(args);
15 |
16 | if (r > 0) {
17 | LOGSS.write(print_buf);
18 | }
19 | }
20 | }
21 |
22 | static int32_t msc_read_cb(uint32_t lba, void *buffer, uint32_t bufsize, uint32_t offset) {
23 | // LOGSS.printf("read: lba:%d, bufsize:%d, offset: %d\n", lba, bufsize, offset);
24 | uint32_t ret_size = -1;
25 |
26 | xSemaphoreTake(SysConfig::lock, portMAX_DELAY);
27 |
28 | const sfud_flash *_flash = sfud_get_device_table() + 0;
29 | uint8_t result =
30 | sfud_read(_flash, lba * _flash->chip.erase_gran + offset, bufsize, (uint8_t *)buffer);
31 | if (result == SFUD_SUCCESS) {
32 | ret_size = bufsize;
33 | }
34 | xSemaphoreGive(SysConfig::lock);
35 | return ret_size;
36 | }
37 |
38 | static int32_t msc_write_cb(uint32_t lba, uint8_t *buffer, uint32_t bufsize, uint32_t offset) {
39 | // LOGSS.printf("write: lba:%d, bufsize:%d, offset:%d\n", lba, bufsize, offset);
40 | uint32_t ret_size = -1;
41 | const sfud_flash *_flash = sfud_get_device_table() + 0;
42 | uint8_t result = SFUD_SUCCESS;
43 | xSemaphoreTake(SysConfig::lock, portMAX_DELAY);
44 | if (offset == 0) {
45 | result = sfud_erase_write(_flash, lba * _flash->chip.erase_gran, bufsize, buffer);
46 | } else {
47 | result = sfud_write(_flash, lba * _flash->chip.erase_gran + offset, bufsize, buffer);
48 | }
49 | if (result == SFUD_SUCCESS) {
50 | ret_size = bufsize;
51 | }
52 | xSemaphoreGive(SysConfig::lock);
53 | return ret_size;
54 | }
55 |
56 | static void msc_flush_cb(void) {
57 | }
58 |
59 | SysConfig::SysConfig(/* args */) {
60 | }
61 |
62 | SysConfig::~SysConfig() {
63 | }
64 |
65 | void SysConfig::init() {
66 | // mount filesystem
67 | if (SysConfig::lock == NULL) {
68 | SysConfig::lock = xSemaphoreCreateMutex();
69 | }
70 | spi_flash_mount = SFUD.begin();
71 |
72 | //If the flash mount is successful, map the space
73 | if (spi_flash_mount) {
74 | const sfud_flash *_flash = sfud_get_device_table() + 0;
75 | // Set disk vendor id, product id and revision with string up to 8, 16, 4 characters
76 | // respectively
77 | usb_msc.setID("K1101", "Mass Storage", "1.0");
78 | // Set disk size
79 | usb_msc.setCapacity((_flash->chip.capacity / _flash->chip.erase_gran),
80 | _flash->chip.erase_gran);
81 | // Set callback
82 | usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
83 | // Set Lun ready (RAM disk is always ready)
84 | usb_msc.setUnitReady(true);
85 | usb_msc.begin();
86 | ReadAllConfig();
87 | }
88 | // pinMode(SDCARD_DET_PIN, INPUT);
89 | // if (digitalRead(SDCARD_DET_PIN) == LOW) {
90 | // sd_mount = SD.begin(SDCARD_SS_PIN, SDCARD_SPI, 4000000UL);
91 | // }else
92 | // LOGSS.println("sd card not insert");
93 | }
94 |
95 | // void SysConfig::set_lora_freq(uint8_t frequency)
96 | // {
97 | // this->frequency = frequency;
98 | // }
99 |
100 | // uint8_t SysConfig::get_lora_freq()
101 | // {
102 | // return this->frequency;
103 | // }
104 |
105 | void SysConfig::ReadConfigParam(const String filename, char *prefix_param, String *param) {
106 | xSemaphoreTake(SysConfig::lock, portMAX_DELAY);
107 | if (spi_flash_mount && cfg_available) {
108 | File config = SFUD.open(filename, "r");
109 | if (config) {
110 | if (config.find(prefix_param) == true) {
111 | *param = config.readStringUntil('\n');
112 | param->trim();
113 | } else { // missing parameter
114 | cfg_available = false;
115 | }
116 | config.close();
117 | }
118 | }
119 | xSemaphoreGive(SysConfig::lock);
120 | }
121 |
122 | void SysConfig::ReadAllConfig() {
123 | if (SFUD.exists("config.txt")) {
124 | cfg_available = true; // assume that the configuration is available
125 | ReadConfigParam("config.txt", "SSID=", &this->ssid);
126 | ReadConfigParam("config.txt", "PASSWORD=", &this->password);
127 | ReadConfigParam("config.txt", "MQTT_CLIENT_NAME=", &this->mqtt_client_name);
128 | ReadConfigParam("config.txt", "TOKEN=", &this->token);
129 | ReadConfigParam("config.txt", "DEVICE_LABEL=", &this->device_label);
130 | ReadConfigParam("config.txt", "ID_SCOPE=", &this->id_scope);
131 | ReadConfigParam("config.txt", "DEVICE_ID=", &this->registration_id);
132 | ReadConfigParam("config.txt", "PRIMARY_KEY=", &this->symmetric_key);
133 | if (!cfg_available) {
134 | SFUD.remove("config.txt");
135 | LOGSS.println("missing parameter!");
136 | ReadAllConfig();
137 | }
138 | } else { // config file does not exist, create a template
139 | WriteConfigTemp();
140 | // WriteConfigParam("config.txt", "SSID=", "WiFi_Name");
141 | // WriteConfigParam("config.txt", "PASSWORD=", "WiFi_Password");
142 | // WriteConfigParam("config.txt", "MQTT_CLIENT_NAME=", "Topic");
143 | // WriteConfigParam("config.txt", "TOKEN=", "Default_Token");
144 | // WriteConfigParam("config.txt", "DEVICE_LABEL=", "Device_Name");
145 | // WriteConfigParam("config.txt", "ID_SCOPE=", "Default_ID_Scope");
146 | // WriteConfigParam("config.txt", "DEVICE_ID=", "Default_Device_ID");
147 | // WriteConfigParam("config.txt", "PRIMARY_KEY=", "Default_Primay_Key");
148 | }
149 | }
150 |
151 | void SysConfig::WriteConfigParam(char *filename, char *prefix_param, char *param) {
152 | xSemaphoreTake(SysConfig::lock, portMAX_DELAY);
153 | LOGSS.println("===> write param");
154 | if (spi_flash_mount) {
155 | File config = SFUD.open(filename, "r+");
156 | if (config) { // file already has content
157 | LOGSS.println("cfg file already has content");
158 | if (config.find(prefix_param) == true) { // param already in the file
159 | config.seek(config.position());
160 | }
161 | config.print(prefix_param);
162 | config.print(param);
163 | config.print("\n");
164 | } else { // file is empty
165 | LOGSS.println("cfg file is empty");
166 | config = SFUD.open(filename, "w");
167 | if (config) {
168 | config.print(prefix_param);
169 | config.print(param);
170 | config.print("\n");
171 | }
172 | }
173 | config.close();
174 | }
175 | xSemaphoreGive(SysConfig::lock);
176 | }
177 |
178 | void SysConfig::WriteConfigTemp() {
179 | xSemaphoreTake(SysConfig::lock, portMAX_DELAY);
180 | File config = SFUD.open("config.txt", "w");
181 | if (config) {
182 | config.print("SSID=WiFi_Name\n");
183 | config.print("PASSWORD=WiFi_Password\n");
184 | config.print("MQTT_CLIENT_NAME=Topic\n");
185 | config.print("TOKEN=Default_Token\n");
186 | config.print("DEVICE_LABEL=Device_Name\n");
187 | config.print("ID_SCOPE=Default_ID_Scope\n");
188 | config.print("DEVICE_ID=Default_Device_ID\n");
189 | config.print("PRIMARY_KEY=Default_Primay_Key\n");
190 | }
191 | config.close();
192 | xSemaphoreGive(SysConfig::lock);
193 | }
--------------------------------------------------------------------------------
/src/cm_backtrace/cm_backtrace.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the CmBacktrace Library.
3 | *
4 | * Copyright (c) 2016, Armink,
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining
7 | * a copy of this software and associated documentation files (the
8 | * 'Software'), to deal in the Software without restriction, including
9 | * without limitation the rights to use, copy, modify, merge, publish,
10 | * distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to
12 | * the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | *
25 | * Function: It is an head file for this library. You can see all be called functions.
26 | * Created on: 2016-12-15
27 | */
28 |
29 | #ifndef _CORTEXM_BACKTRACE_H_
30 | #define _CORTEXM_BACKTRACE_H_
31 | #ifdef __cplusplus
32 | extern "C"{
33 | #endif
34 | #include "cmb_def.h"
35 |
36 | void cm_backtrace_init(const char *firmware_name, const char *hardware_ver, const char *software_ver);
37 | void cm_backtrace_firmware_info(void);
38 | size_t cm_backtrace_call_stack(uint32_t *buffer, size_t size, uint32_t sp);
39 | void cm_backtrace_assert(uint32_t sp);
40 | void cm_backtrace_fault(uint32_t fault_handler_lr, uint32_t fault_handler_sp);
41 | #ifdef __cplusplus
42 | }//extern "C"{
43 | #endif
44 | #endif /* _CORTEXM_BACKTRACE_H_ */
45 |
--------------------------------------------------------------------------------
/src/cm_backtrace/cmb_cfg.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the CmBacktrace Library.
3 | *
4 | * Copyright (c) 2016, Armink,
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining
7 | * a copy of this software and associated documentation files (the
8 | * 'Software'), to deal in the Software without restriction, including
9 | * without limitation the rights to use, copy, modify, merge, publish,
10 | * distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to
12 | * the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | *
25 | * Function: It is the configure head file for this library.
26 | * Created on: 2016-12-15
27 | */
28 |
29 | #ifndef _CMB_CFG_H_
30 | #define _CMB_CFG_H_
31 |
32 | /* print line, must config by user */
33 | #define cmb_println(...) cm_printf(__VA_ARGS__);cm_printf("\r\n"); /* e.g., printf(__VA_ARGS__);printf("\r\n") */
34 | /* enable bare metal(no OS) platform */
35 | /* #define CMB_USING_BARE_METAL_PLATFORM */
36 | /* enable OS platform */
37 | #define CMB_USING_OS_PLATFORM 1
38 | /* OS platform type, must config when CMB_USING_OS_PLATFORM is enable */
39 | #define CMB_OS_PLATFORM_TYPE CMB_OS_PLATFORM_FREERTOS /* CMB_OS_PLATFORM_RTT or CMB_OS_PLATFORM_UCOSII or CMB_OS_PLATFORM_UCOSIII or CMB_OS_PLATFORM_FREERTOS */
40 | /* cpu platform type, must config by user */
41 | #define CMB_CPU_PLATFORM_TYPE CMB_CPU_ARM_CORTEX_M4 /* CMB_CPU_ARM_CORTEX_M0 or CMB_CPU_ARM_CORTEX_M3 or CMB_CPU_ARM_CORTEX_M4 or CMB_CPU_ARM_CORTEX_M7 */
42 | /* enable dump stack information */
43 | #define CMB_USING_DUMP_STACK_INFO 1
44 | /* language of print information */
45 | /* #define CMB_PRINT_LANGUAGE CMB_PRINT_LANGUAGE_ENGLISH(default) or CMB_PRINT_LANGUAGE_CHINESE */
46 | #endif /* _CMB_CFG_H_ */
47 |
--------------------------------------------------------------------------------
/src/cm_backtrace/fault_handler/gcc/cmb_fault.S:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of the CmBacktrace Library.
3 | *
4 | * Copyright (c) 2016, Armink,
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining
7 | * a copy of this software and associated documentation files (the
8 | * 'Software'), to deal in the Software without restriction, including
9 | * without limitation the rights to use, copy, modify, merge, publish,
10 | * distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to
12 | * the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | *
25 | * Function: Fault handler by GCC assembly code
26 | * Created on: 2016-12-16
27 | */
28 |
29 | .syntax unified
30 | .thumb
31 | .text
32 |
33 | /* NOTE: If use this file's HardFault_Handler, please comments the HardFault_Handler code on other file. */
34 |
35 | .global HardFault_Handler
36 | .type HardFault_Handler, %function
37 | HardFault_Handler:
38 | MOV r0, lr /* get lr */
39 | MOV r1, sp /* get stack pointer (current is MSP) */
40 | BL cm_backtrace_fault
41 |
42 | Fault_Loop:
43 | BL Fault_Loop /* while(1) */
44 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "ButtonThread.h"
3 | #include "FreeRTOS.h"
4 | #include "LoRaThread.h"
5 | #include "SamplerThread.h"
6 | #include "Seeed_Arduino_ooFreeRTOS.h"
7 | #include "SysConfig.h"
8 | #include "ui.h"
9 | #include
10 | #include
11 | #ifdef CM_DEBUG
12 | #include "cm_backtrace.h"
13 | #endif
14 | #define HARDWARE_VERSION "seeed_k1100_dev_kit"
15 | #define SOFTWARE_VERSION "V1.0.0"
16 |
17 | #define ANSI_R "\x1b[31m"
18 | #define ANSI_G "\x1b[32m"
19 | #define ANSI_Y "\x1b[33m"
20 | #define ANSI_B "\x1b[34m"
21 | #define ANSI_MAGENTA "\x1b[35m"
22 | #define ANSI_CYAN "\x1b[36m"
23 | #define ANSI_RESET "\x1b[0m"
24 |
25 | using namespace cpp_freertos;
26 |
27 | TFT_eSPI tft;
28 | // TFT_eSprite spr = TFT_eSprite(&tft);
29 |
30 | void display_init() // Display initialization, black background rotation
31 | {
32 | tft.begin();
33 | tft.setRotation(3);
34 | tft.fillScreen(TFT_BLACK);
35 | tft.setTextColor(TFT_WHITE);
36 | tft.setFreeFont(FSSB9);
37 | tft.drawString(DEVICE, 90, 110, GFXFF);
38 | tft.setFreeFont(FSS9);
39 | tft.drawString(VERSION, 150, 150, FONT2);
40 | }
41 |
42 | using namespace std;
43 | void LogMemoryUsage(const char *s);
44 | void LogHeapChange(const char *s);
45 | void LogTaskTrace(void);
46 |
47 | void setup() {
48 | LOGSS.begin(115200);
49 | display_init();
50 | SysConfig *cfg = new SysConfig();
51 | cfg->init();
52 |
53 | #ifdef CM_DEBUG
54 | cm_backtrace_init("Seeed K1100 dev kit", HARDWARE_VERSION, SOFTWARE_VERSION);
55 | #endif
56 | // put your setup code here, to run once:
57 | uint32_t start = millis();
58 | while (!LOGSS && (millis() - start) < 1500)
59 | ; // Open the Serial Monitor to get started or wait for 1.5"
60 |
61 |
62 | Message *btnMail = new Message(256);
63 | // Message *sensorMail = new Message(256);
64 |
65 | ButtonThread *btn = new ButtonThread(*btnMail);
66 | UI *u = new UI(tft, *cfg, *btnMail);
67 | SamplerThread *sampler = new SamplerThread(*cfg, *u);
68 | }
69 |
70 | // Get the size of memory left in the system in freertos.
71 | void LogMemoryUsage(const char *s) {
72 | int CurFree, MinFree, Percentage;
73 | int Total = configTOTAL_HEAP_SIZE;
74 | CurFree = xPortGetFreeHeapSize();
75 | MinFree = xPortGetMinimumEverFreeHeapSize();
76 | Percentage = (Total-CurFree)*100 / Total;
77 | string UsageGraph = "["ANSI_G;
78 | for(int i=0; i<25; i++)
79 | {
80 | if(i == Percentage/4)
81 | UsageGraph += "#"ANSI_RESET;
82 | else
83 | UsageGraph += "#";
84 | }
85 | UsageGraph += "]";
86 | LOGSS.println("====== RTOS HEAP USAGE =======");
87 | LOGSS.printf("| Log in : "ANSI_Y"%s \r\n"ANSI_RESET, s);
88 | LOGSS.printf("| Total : "ANSI_B"%d "ANSI_RESET"bytes\r\n", Total);
89 | LOGSS.printf("| Maximum : "ANSI_R"%d "ANSI_RESET"bytes\r\n", Total-MinFree);
90 | LOGSS.printf("| Current : "ANSI_G"%d "ANSI_RESET"bytes\r\n", (Total-CurFree), UsageGraph.c_str());
91 | LOGSS.printf("| %s \r\n", UsageGraph.c_str());
92 | }
93 |
94 | void LogTaskTrace() {
95 | char TraceBuf[512];
96 | vTaskList(TraceBuf);
97 | LOGSS.println("========= RTOS task stack usage ==========");
98 | LOGSS.println("TaskName State Priority FreeStack");
99 | LOGSS.printf("%s", TraceBuf);
100 | LOGSS.println("================== end ===================");
101 | }
102 |
103 | void LogHeapChange(const char *s) {
104 | static int pre_free_heap = 0;
105 | int heap_change = configTOTAL_HEAP_SIZE - xPortGetFreeHeapSize() - pre_free_heap;
106 | if(heap_change > 0) {
107 | LOGSS.printf(ANSI_R" => %s +%d\r\n"ANSI_RESET, s, heap_change);
108 | }
109 | else if(heap_change < 0) {
110 | LOGSS.printf(ANSI_G" => %s %d\r\n"ANSI_RESET, s, heap_change);
111 | }
112 | pre_free_heap += heap_change;
113 | }
114 |
115 | void loop() {
116 | // LOGSS.printf("Main Stacks Free Bytes Remaining %d\r\n", uxTaskGetStackHighWaterMark(NULL));
117 | vTaskDelete(NULL);
118 | }
119 |
--------------------------------------------------------------------------------
/src/sensor.cpp:
--------------------------------------------------------------------------------
1 | #include "sensor.h"
2 |
3 | std::vector sensor_base::slog;
4 |
5 | void sensor_base::pushlog(const char *msg)
6 | {
7 | log_data log;
8 | strcpy(log.data, msg);
9 | log.time = millis();
10 | if (slog.size() > LOG_MAX_SIZE)
11 | {
12 | slog.erase(slog.begin());
13 | }
14 | slog.push_back(log);
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/src/sensors/FakeSensor.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * @file FakeSensor.cpp
3 | * @author Baozhu Zuo (zuobaozhu@gmail.com)
4 | * @brief This is a fake sensor drive, which simulates random disconnection of the sensor during use
5 | * and random acquisition of measured data.
6 | * @version 0.1
7 | * @date 2022-08-07
8 | *
9 | * @copyright Copyright (c) 2022 Seeed technology inc.
10 | *
11 | */
12 | #include "FakeSensor.h"
13 | #include "Arduino.h"
14 |
15 | Fake::Fake() : Thread("Fake", 128, 1) {
16 | }
17 | void Fake::Run() {
18 | uint16_t delay;
19 | while (true) {
20 | delay = random(100,2000);
21 | dsize = random(0,10);
22 | for (int i = 0; i < dsize; i++) {
23 | data[i] = random(-10000, 10000);
24 | }
25 | status = random(0, 2);
26 | Delay(Ticks::MsToTicks(delay));
27 | }
28 | }
29 |
30 | FakeSensor::FakeSensor() {
31 | fake = new Fake();
32 | }
33 |
34 | void FakeSensor::init() {
35 | fake->Start();
36 | }
37 |
38 | bool FakeSensor::read(struct sensor_data *data) {
39 | data->data = fake->data;
40 | data->size = fake->dsize*sizeof(int);
41 | data->id = 0;
42 | data->name = name;
43 | data->status = fake->status;
44 | return data->size == 0 ? false : true;
45 | }
46 |
47 | const char *FakeSensor::get_name() {
48 | return this->name;
49 | }
--------------------------------------------------------------------------------
/src/sensors/FakeSensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __FAKESENSOR_H__
2 | #define __FAKESENSOR_H__
3 |
4 | #include "sensor.h"
5 | #include "utils.h"
6 |
7 | #include
8 |
9 | using namespace cpp_freertos;
10 |
11 | class Fake : public Thread {
12 |
13 | public:
14 | Fake();
15 | int data[10];
16 | uint8_t dsize;
17 | bool status;
18 |
19 | protected:
20 | virtual void Run();
21 | };
22 |
23 | class FakeSensor : public sensor_base {
24 | public:
25 | FakeSensor();
26 | void init();
27 | bool read(struct sensor_data *data);
28 | const char *get_name();
29 |
30 | private:
31 | const char *name = "FakeSensor";
32 | bool status;
33 | Fake *fake;
34 | };
35 |
36 | #endif // __FAKESENSOR_H__
--------------------------------------------------------------------------------
/src/sensors/LIS3DHTRSensor.cpp:
--------------------------------------------------------------------------------
1 | #include "LIS3DHTRSensor.h"
2 | #include "SensorsUtils.h"
3 |
4 | LIS3DHTRSensor::LIS3DHTRSensor() {
5 | }
6 |
7 | void LIS3DHTRSensor::init() {
8 | if (I2CScanner(LIS3DHTR_DEFAULT_ADDRESS, Wire)) {
9 | lis.begin(Wire);
10 | lis.setOutputDataRate(LIS3DHTR_DATARATE_25HZ); // Data output rate
11 | lis.setFullScaleRange(LIS3DHTR_RANGE_2G);
12 | status = true;
13 | } else {
14 | status = false;
15 | }
16 | }
17 |
18 | bool LIS3DHTRSensor::read(struct sensor_data *sdata) {
19 | float x_values, y_values, z_values;
20 |
21 | sdata->id = LIS3DHTRSENSOR;
22 | sdata->name = name;
23 |
24 | if (status) {
25 | if (!I2CScanner(LIS3DHTR_DEFAULT_ADDRESS, Wire)) {
26 | status = false;
27 | return false;
28 | }
29 |
30 | lis.getAcceleration(&x_values, &y_values, &z_values);
31 | data[0] = (int)(x_values * 100);
32 | data[1] = (int)(y_values * 100);
33 | data[2] = (int)(z_values * 100);
34 | sdata->data = data;
35 | sdata->data_type = SENSOR_DATA_TYPE_FLOAT;
36 | sdata->size = sizeof(data);
37 | sdata->id = LIS3DHTRSENSOR;
38 | sdata->ui_type = SENSOR_UI_TYPE_NORMAL;
39 | sdata->data_unit = data_unit;
40 | sdata->status = true;
41 | return true;
42 | } else {
43 | sdata->data = NULL;
44 | sdata->status = false;
45 | init(); // init again, try to find the sensor
46 | return false;
47 | }
48 | }
49 |
50 | const char *LIS3DHTRSensor::get_name() {
51 | return this->name;
52 | }
53 |
--------------------------------------------------------------------------------
/src/sensors/LIS3DHTRSensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __LIS3DHTRSENSOR_H__
2 | #define __LIS3DHTRSENSOR_H__
3 | #include "sensor.h"
4 | #include "utils.h"
5 | #include "Wire.h"
6 | #include "LIS3DHTR.h"
7 |
8 |
9 |
10 | class LIS3DHTRSensor : public sensor_base
11 | {
12 | public:
13 | LIS3DHTRSensor();
14 | void init();
15 | bool read(struct sensor_data *data);
16 | const char *get_name();
17 | private:
18 | const char *name = "IMU"; //LIS3DHTR
19 | const char *data_unit = "X-Y-Z";
20 | int data[3];
21 |
22 | bool status;
23 |
24 | LIS3DHTR lis;
25 | };
26 |
27 | #endif // __LIS3DHTRSENSOR_H__
--------------------------------------------------------------------------------
/src/sensors/SensorsUtils.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "Arduino.h"
3 | #include "Wire.h"
4 | #include "SoftwareI2C.h"
5 | #include "sensor.h"
6 | #include "SensorsUtils.h"
7 |
8 | SoftwareI2C softwarei2c;
9 |
10 | template bool I2CScanner(uint8_t address, T wire) {
11 | uint8_t error = 0;
12 | wire.begin();
13 | wire.beginTransmission(address & 0x7F);
14 |
15 | error = wire.endTransmission();
16 |
17 | // features: for samd21 & samd51
18 | if (error == 0) {
19 | wire.beginTransmission(0x1);
20 | error = wire.endTransmission();
21 | if (error == 0) {
22 | wire.beginTransmission(0x7F);
23 | error = wire.endTransmission();
24 | if (error == 0)
25 | return false;
26 | }
27 | } else {
28 | return false;
29 | }
30 |
31 | return true;
32 | }
33 | template bool I2CScanner(uint8_t address, TwoWire wire);
34 |
35 | template bool I2CScanner(T wire) {
36 | for (unsigned char i = 1; i <= 127; i++) {
37 | if (wire.beginTransmission(i)) {
38 | // LOGSS.printf("Found I2C device at address: ");
39 | // LOGSS.println( i);
40 | return true;
41 | }
42 | wire.endTransmission();
43 | }
44 | // LOGSS.println(" not Found I2C device ");
45 | return false;
46 | }
47 | template bool I2CScanner(SoftwareI2C wire);
48 |
49 | /*************************************************************************************************
50 | Function Name: Grove_I2C_Check
51 | Description: check for i2c sensor connect
52 | Return: true: i2c sensor connected
53 | *************************************************************************************************/
54 | bool Grove_I2C_Check(SoftwareI2C& wire){
55 | wire.begin(SOFT_I2C_SDA, SOFT_I2C_SCL);
56 | for(int i=0; i bool I2CScanner(uint8_t address, T wire);
29 | template bool I2CScanner(T wire);
30 | #endif // __SENSORSUTILS_H__
--------------------------------------------------------------------------------
/src/sensors/buildin_light_sensor.cpp:
--------------------------------------------------------------------------------
1 |
2 | #include "buildin_light_sensor.h"
3 | #include "Arduino.h"
4 |
5 | buildin_light_sensor::buildin_light_sensor() {
6 | }
7 | void buildin_light_sensor::init() {
8 | pinMode(WIO_LIGHT, INPUT);
9 | }
10 |
11 | bool buildin_light_sensor::read(struct sensor_data *sdata) {
12 | light_value = analogRead(WIO_LIGHT);
13 | sdata->data_type = SENSOR_DATA_TYPE_INT32;
14 | sdata->data = &light_value;
15 | sdata->size = sizeof(light_value);
16 | sdata->id = BUILDIN_LIGHT;
17 | sdata->name = name;
18 | sdata->ui_type = SENSOR_UI_TYPE_NORMAL;
19 | sdata->data_unit = data_unit;
20 | sdata->status = true;
21 | return true;
22 | }
23 |
24 | const char *buildin_light_sensor::get_name() {
25 | return "light";
26 | }
27 |
28 | // buildin_light_sensor buildin_light;
--------------------------------------------------------------------------------
/src/sensors/buildin_light_sensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __BUILDIN_LIGHT_SENSOR_H
2 | #define __BUILDIN_LIGHT_SENSOR_H
3 |
4 | #include "sensor.h"
5 | #include "utils.h"
6 |
7 | class buildin_light_sensor : public sensor_base
8 | {
9 | public:
10 | buildin_light_sensor();
11 | void init();
12 | const char *get_name();
13 | bool read(struct sensor_data *data);
14 | private:
15 | const char *name = "Light"; /// buildin-light
16 | const char *data_unit = " ";
17 | int light_value;
18 |
19 | };
20 |
21 | #endif
--------------------------------------------------------------------------------
/src/sensors/buildin_mic.cpp:
--------------------------------------------------------------------------------
1 | #include "buildin_mic.h"
2 | #include "Arduino.h"
3 |
4 | buildin_mic::buildin_mic() {
5 | }
6 | void buildin_mic::init() {
7 | pinMode(WIO_MIC, INPUT);
8 | }
9 | bool buildin_mic::read(struct sensor_data *sdata) {
10 | mic_value = analogRead(WIO_MIC);
11 | if(mic_value < 250)
12 | mic_value = 0;
13 | else
14 | mic_value = (uint32_t)((mic_value - 250) / 3.19);
15 | sdata->data_type = SENSOR_DATA_TYPE_INT32;
16 | sdata->data = &mic_value;
17 | sdata->size = sizeof(mic_value);
18 | sdata->id = BUILDIN_MIC;
19 | sdata->name = name;
20 | sdata->ui_type = SENSOR_UI_TYPE_NORMAL;
21 | sdata->data_unit = data_unit;
22 | sdata->status = true;
23 | return true;
24 | }
25 |
26 | const char *buildin_mic::get_name() {
27 | return "buildin-mic";
28 | }
29 |
--------------------------------------------------------------------------------
/src/sensors/buildin_mic.h:
--------------------------------------------------------------------------------
1 | #ifndef __BUILDIN_MIC_H
2 | #define __BUILDIN_MIC_H
3 |
4 | #include "sensor.h"
5 | #include "utils.h"
6 |
7 |
8 | class buildin_mic : public sensor_base
9 | {
10 | public:
11 | buildin_mic();
12 | void init();
13 | bool read(struct sensor_data *data);
14 | const char *get_name();
15 | private:
16 | const char *name = "Sound"; //buildin-mic
17 | const char *data_unit = "dB";
18 | int mic_value;
19 |
20 | };
21 |
22 | // buildin_mic buildin_mic;
23 | #endif
--------------------------------------------------------------------------------
/src/sensors/grove_sgp30_sensor.cpp:
--------------------------------------------------------------------------------
1 | #include "grove_sgp30_sensor.h"
2 | #include "Arduino.h"
3 | #include "SensorsUtils.h"
4 |
5 | grove_sgp30_sensor::grove_sgp30_sensor() { }
6 | void grove_sgp30_sensor::init() {
7 | if (is_connected) {
8 | sgp30.begin(softwarei2c);
9 | sgp30.initAirQuality();
10 | }
11 | }
12 |
13 | bool grove_sgp30_sensor::read(struct sensor_data *sdata) {
14 | /* check out connection */
15 | if (!I2C_Detect(grove_i2c_addr[S_SGP30], softwarei2c)) {
16 | is_connected = false;
17 | return false;
18 | }
19 | else if (!is_connected) { // first connect
20 | is_connected = true;
21 | init();
22 | return false; // waiting for next read
23 | }
24 |
25 | /* check out measurement */
26 | if (sgp30.measureAirQuality() != SGP30_SUCCESS) {
27 | sdata->status = false;
28 | sgp30.initAirQuality();
29 | } else {
30 | sdata->status = true;
31 | sgp30_value[0] = sgp30.CO2;
32 | sgp30_value[1] = sgp30.TVOC;
33 |
34 | sdata->data = sgp30_value;
35 | sdata->data_type = SENSOR_DATA_TYPE_INT32;
36 | sdata->size = sizeof(sgp30_value);
37 | sdata->id = GROVE_SGP30;
38 | sdata->name = name;
39 | sdata->ui_type = SENSOR_UI_TYPE_NORMAL;
40 | sdata->data_unit = data_unit;
41 | }
42 | return sdata->status;
43 | }
44 |
45 | const char *grove_sgp30_sensor::get_name() {
46 | return "sgp30";
47 | }
48 |
49 | // grove_sgp30_sensor buildin_sgp30; // Serial.println("Measurement failed!");
--------------------------------------------------------------------------------
/src/sensors/grove_sgp30_sensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __GROVE_SGP30_SENSOR_H
2 | #define __GROVE_SGP30_SENSOR_H
3 |
4 | #include "SparkFun_SGP30_Arduino_Library.h"
5 | #include "sensor.h"
6 | #include "utils.h"
7 | #include "SoftwareI2C.h"
8 |
9 | #define SGP30_SDAPIN D1
10 | #define SGP30_SCLPIN D0
11 |
12 | class grove_sgp30_sensor : public sensor_base {
13 | public:
14 | grove_sgp30_sensor();
15 | void init();
16 | const char *get_name();
17 | bool read(struct sensor_data *data);
18 | bool is_connected;
19 |
20 | private:
21 | const char *name = "Gas";
22 | const char *data_unit = "ppm,ppb";
23 | int sgp30_value[2];
24 | SGP30 sgp30;
25 | };
26 |
27 | #endif
--------------------------------------------------------------------------------
/src/sensors/grove_sht4x_sensor.cpp:
--------------------------------------------------------------------------------
1 | #include "grove_sht4x_sensor.h"
2 | #include "Arduino.h"
3 | #include "SensorsUtils.h"
4 | #include "SoftwareI2C.h"
5 |
6 | grove_sht4x_sensor::grove_sht4x_sensor() { }
7 | void grove_sht4x_sensor::init() {
8 | if (is_connected) {
9 | sht4x.setPort(softwarei2c);
10 | sht4x.setChipType(SHT4X_CHIPTYPE_A);
11 | sht4x.setMode(SHT4X_CMD_MEAS_HI_PREC);
12 | sht4x.checkSerial();
13 | }
14 | }
15 |
16 | bool grove_sht4x_sensor::read(struct sensor_data *sdata) {
17 | /* check out connection */
18 | if (!I2C_Detect(grove_i2c_addr[S_SHT4X], softwarei2c)) {
19 | is_connected = false;
20 | return false;
21 | }
22 | else if (!is_connected) { // first connect
23 | is_connected = true;
24 | init();
25 | return false; // waiting for next read
26 | }
27 |
28 | /* check out measurement */
29 | if (sht4x.measure() != SHT4X_STATUS_OK) {
30 | sdata->status = false;
31 | } else {
32 | sdata->status = true;
33 | sht4x_value[0] = (sht4x.TcrcOK) ? (int32_t)(sht4x.TtoDegC() * 100) : 0xFF;
34 | sht4x_value[1] = (sht4x.RHcrcOK) ? (int32_t)(sht4x.RHtoPercent() * 100) : 0xFF;
35 | sdata->data = sht4x_value;
36 | sdata->data_type = SENSOR_DATA_TYPE_FLOAT;
37 | sdata->size = sizeof(sht4x_value);
38 | sdata->id = GROVE_SHT4X;
39 | sdata->name = name;
40 | sdata->ui_type = SENSOR_UI_TYPE_NORMAL;
41 | sdata->data_unit = data_unit;
42 | return sdata->status;
43 | }
44 | return sdata->status;
45 | }
46 |
47 | const char *grove_sht4x_sensor::get_name() {
48 | return "sht4x";
49 | }
50 |
--------------------------------------------------------------------------------
/src/sensors/grove_sht4x_sensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __GROVE_SHT4X_SENSOR_H
2 | #define __GROVE_SHT4X_SENSOR_H
3 | #include "SHT4x.h"
4 | #include "sensor.h"
5 | #include "utils.h"
6 | #include "SoftwareI2C.h"
7 |
8 | #define SHT4X_SDAPIN D1
9 | #define SHT4X_SCLPIN D0
10 |
11 | class grove_sht4x_sensor : public sensor_base
12 | {
13 | public:
14 | grove_sht4x_sensor();
15 | const char *get_name();
16 | void init();
17 | bool read(struct sensor_data *data);
18 | bool is_connected;
19 |
20 | private:
21 | const char *name = "T_H";
22 | const char *data_unit = "C,%RH";
23 | int sht4x_value[2];
24 | SHT4x sht4x;
25 | };
26 |
27 | #endif
--------------------------------------------------------------------------------
/src/sensors/grove_soil_sensor.cpp:
--------------------------------------------------------------------------------
1 | #include "grove_soil_sensor.h"
2 | #include "SensorsUtils.h"
3 |
4 | grove_soil_sensor::grove_soil_sensor() {
5 | }
6 | void grove_soil_sensor::init() {
7 | is_available = (Grove_I2C_Check(softwarei2c)) ? false : true;
8 | }
9 |
10 | bool grove_soil_sensor::read(struct sensor_data *sdata) {
11 | uint16_t sum = 0, data[READ_NUM] = {0};
12 | double variance = 0.0;
13 | init();
14 | if (!is_available) {
15 | return false;
16 | }
17 | analogRead(SOILPIN);
18 | delay(2);
19 | // sum
20 | for (int i = 0; i < READ_NUM; i++) {
21 | data[i] = analogRead(SOILPIN);
22 | delayMicroseconds(2);
23 | sum += data[i];
24 | }
25 | //Find the variance
26 | for (int i = 0; i < READ_NUM; i++) {
27 | variance = variance + pow(data[i] - sum / READ_NUM, 2);
28 | }
29 | variance = variance / READ_NUM;
30 |
31 | if (variance > DATA_VARIANCE_MAX || sum / READ_NUM > SOIL_DATA_MAX)
32 | return false;
33 | soil_value = sum / READ_NUM;
34 | sdata->data = &soil_value;
35 | sdata->data_type = SENSOR_DATA_TYPE_INT32;
36 | sdata->size = sizeof(soil_value);
37 | sdata->id = GROVE_SOIL;
38 | sdata->name = name;
39 | sdata->ui_type = SENSOR_UI_TYPE_NORMAL;
40 | sdata->data_unit = data_unit;
41 | sdata->status = true;
42 | return true;
43 | }
44 |
45 | const char *grove_soil_sensor::get_name() {
46 | return "soil";
47 | }
48 |
49 | // grove_soil_sensor buildin_soil; // Serial.println("Measurement failed!");
--------------------------------------------------------------------------------
/src/sensors/grove_soil_sensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __GROVE_SOIL_SENSOR_H
2 | #define __GROVE_SOIL_SENSOR_H
3 |
4 | #include "sensor.h"
5 | #include "utils.h"
6 | #include "Arduino.h"
7 | #include "SoftwareI2C.h"
8 |
9 | #define SOILPIN A0
10 | #define READ_NUM 10
11 | #define SOIL_DATA_MAX 1000
12 | #define DATA_VARIANCE_MAX 20
13 | #define SOFTWRIE_SDAPIN D1
14 | #define SOFTWRIE_SCLPIN D0
15 |
16 | class grove_soil_sensor : public sensor_base {
17 | public:
18 | grove_soil_sensor();
19 | void init();
20 | const char *get_name();
21 | bool read(struct sensor_data *data);
22 | bool is_available;
23 |
24 | private:
25 | const char *name = "Soil";
26 | const char *data_unit = " ";
27 | int soil_value;
28 | };
29 |
30 | #endif
--------------------------------------------------------------------------------
/src/sensors/grove_visionai_sensor.cpp:
--------------------------------------------------------------------------------
1 | #include "grove_visionai_sensor.h"
2 | #include "Arduino.h"
3 | #include "SensorsUtils.h"
4 |
5 | Visionai::Visionai() : Thread("Visionai", 256, 1) {
6 | }
7 |
8 | void Visionai::pushlog(const char *msg) {
9 | log_data log;
10 | strcpy(log.data, msg);
11 | log.time = millis();
12 | if (ai_log.size() > LOG_MAX_SIZE) {
13 | ai_log.erase(ai_log.begin());
14 | }
15 | ai_log.push_back(log);
16 | }
17 |
18 | void Visionai::Run() {
19 | char log[32];
20 | // softwarei2c.begin(VISIONAI_SDAPIN, VISIONAI_SCLPIN);
21 | ai.begin(ALGO_OBJECT_DETECTION, MODEL_EXT_INDEX_1); // Object detection and externel model 1
22 | while (true) {
23 | uint32_t tick = millis();
24 | if (ai.invoke()) // begin invoke
25 | {
26 | while (1) // wait for invoking finished
27 | {
28 | CMD_STATE_T ret = ai.state();
29 | if (ret == CMD_STATE_IDLE) {
30 | break;
31 | } else if (ret == CMD_STATE_ERROR) {
32 | pushlog("Vision Ai is disconnect.");
33 | status = false;
34 | goto next;
35 | }
36 | Delay(Ticks::MsToTicks(100));
37 | }
38 | dsize = ai.get_result_len(); // receive how many people detect
39 | if (dsize > 0 && dsize <= MAX_DETECTION) {
40 | int time1 = millis() - tick;
41 | sprintf(log, "Time consuming: %d", time1);
42 | pushlog(log);
43 | sprintf(log, "Number of people: %d", dsize);
44 | pushlog(log);
45 | object_detection_t g_data; // get data
46 | for (int i = 0; i < dsize; i++) {
47 | sprintf(log, "Detecting and calculating: %d", i + 1);
48 | pushlog(log);
49 | ai.get_result(i, (uint8_t *)&g_data, sizeof(object_detection_t)); // get result
50 | data[i] = (g_data.confidence < 100) ? g_data.confidence : 100;
51 | sprintf(log, "confidence: %d", data[i]);
52 | pushlog(log);
53 | }
54 | } else {
55 | dsize = 0;
56 | data[0] = 0;
57 | pushlog("No identification");
58 | }
59 | status = true;
60 | } else {
61 | pushlog("Vision Ai is disconnect.");
62 | status = false;
63 | }
64 | next:
65 | Delay(Ticks::MsToTicks(SENSOR_READ_DELAY));
66 | }
67 | }
68 |
69 | grove_visionai_sensor::grove_visionai_sensor() {
70 | visionai = new Visionai();
71 | }
72 | void grove_visionai_sensor::init() {
73 | visionai->Start();
74 | // if (is_connected) {
75 | // ai.begin(ALGO_OBJECT_DETECTION, MODEL_EXT_INDEX_1);
76 | // }
77 | }
78 |
79 | bool grove_visionai_sensor::read(struct sensor_data *sdata) {
80 | /* check out connection */
81 | // if (!I2C_Detect(grove_i2c_addr[S_VISION], softwarei2c)) {
82 | // is_connected = false;
83 | // return false;
84 | // } else if (!is_connected) { // first connect
85 | // is_connected = true;
86 | // init();
87 | // return false; // waiting for next read
88 | // }
89 |
90 | sdata->size = visionai->dsize * sizeof(visionai->data[0]);
91 | sdata->data_type = SENSOR_DATA_TYPE_INT32;
92 | sdata->data = &visionai->data;
93 | sdata->id = GROVE_VISIONAI;
94 | sdata->name = name;
95 | sdata->status = visionai->status;
96 | sdata->ui_type = SENSOR_UI_TYPE_AVERAGE;
97 | sdata->data_unit = data_unit;
98 | grove_visionai_sensor::slog = visionai->ai_log;
99 | return sdata->status;
100 | }
101 |
102 | const char *grove_visionai_sensor::get_name() {
103 | return "visionai";
104 | }
105 |
106 | // grove_visionai_sensor buildin_visionai;
--------------------------------------------------------------------------------
/src/sensors/grove_visionai_sensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __GROVE_VISIONAI_SENSOR_H
2 | #define __GROVE_VISIONAI_SENSOR_H
3 |
4 | #include "Seeed_Arduino_GroveAI.h"
5 | #include "SoftwareI2C.h"
6 | #include "SensorsUtils.h"
7 | #include "SysConfig.h"
8 | #include "sensor.h"
9 | #include
10 | #include
11 |
12 | using namespace cpp_freertos;
13 |
14 | #define VISIONAI_SDAPIN D1
15 | #define VISIONAI_SCLPIN D0
16 | #define MAX_DETECTION 10
17 |
18 | class Visionai : public Thread {
19 |
20 | public:
21 | Visionai();
22 | int data[20];
23 | uint8_t dsize;
24 | bool status;
25 | std::vector ai_log;
26 | // SoftwareI2C softwarei2c;
27 | GroveAI ai = GroveAI(softwarei2c);
28 |
29 | protected:
30 | virtual void Run();
31 | void pushlog(const char *msg);
32 | };
33 |
34 | class grove_visionai_sensor : public sensor_base {
35 | public:
36 | grove_visionai_sensor();
37 | void init();
38 | const char *get_name();
39 | bool read(struct sensor_data *data);
40 | bool is_connected;
41 |
42 | private:
43 | const char *name = "Vision";
44 | const char *data_unit = "count,%";
45 | int visionai_value[20];
46 | Visionai *visionai;
47 | // GroveAI ai = GroveAI(softwarei2c);
48 | };
49 |
50 | #endif
--------------------------------------------------------------------------------
/src/sensors/grove_vl53l0x_sensor.cpp:
--------------------------------------------------------------------------------
1 | #include "grove_vl53l0x_sensor.h"
2 | #include "Arduino.h"
3 | #include "SensorsUtils.h"
4 | #include "SoftwareI2C.h"
5 |
6 | grove_vl53l0x_sensor::grove_vl53l0x_sensor() { }
7 | void grove_vl53l0x_sensor::init() {
8 | if (is_connected) {
9 | VL53L0X_Error ret = VL53L0X_ERROR_NONE;
10 | ret = VL53L0X.VL53L0X_common_init();
11 | ret = VL53L0X.VL53L0X_high_accuracy_ranging_init();
12 | // VL53L0X.VL53L0X_high_speed_ranging_init();
13 | // VL53L0X.VL53L0X_long_distance_ranging_init();
14 | // VL53L0X.VL53L0X_single_ranging_init();
15 | if (ret != VL53L0X_ERROR_NONE)
16 | LOGSS.printf("init failed, error code: %d\r\n", ret);
17 | }
18 | }
19 |
20 | bool grove_vl53l0x_sensor::read(struct sensor_data *sdata) {
21 | /* check out connection */
22 | if (!I2C_Detect(grove_i2c_addr[S_VL53LX0], softwarei2c)) {
23 | is_connected = false;
24 | return false;
25 | }
26 | else if (!is_connected) { // first connect
27 | is_connected = true;
28 | init();
29 | return false; // waiting for next read
30 | }
31 |
32 | /* check out measurement */
33 | VL53L0X_RangingMeasurementData_t range_data;
34 | VL53L0X_Error ret = VL53L0X.PerformSingleRangingMeasurement(&range_data);
35 | if (ret != VL53L0X_ERROR_NONE) {
36 | LOGSS.printf("mesurement failed, error code : %d\r\n", ret);
37 | memset(&range_data, 0, sizeof(VL53L0X_RangingMeasurementData_t));
38 | sdata->status = false;
39 | } else {
40 | vl53l0x_value = range_data.RangeMilliMeter;
41 | if (vl53l0x_value > 2000) {
42 | vl53l0x_value = 2000;
43 | // LOGSS.println("VL53L0X : out of range");
44 | }
45 | sdata->data = &vl53l0x_value;
46 | sdata->data_type = SENSOR_DATA_TYPE_INT32;
47 | sdata->size = sizeof(vl53l0x_value);
48 | sdata->id = GROVE_VL53L0X;
49 | sdata->name = name;
50 | sdata->ui_type = SENSOR_UI_TYPE_NORMAL;
51 | sdata->data_unit = data_unit;
52 | sdata->status = true;
53 | }
54 | return sdata->status;
55 | }
56 |
57 | const char *grove_vl53l0x_sensor::get_name() {
58 | return "vl53l0x";
59 | }
--------------------------------------------------------------------------------
/src/sensors/grove_vl53l0x_sensor.h:
--------------------------------------------------------------------------------
1 | #ifndef __GROVE_VL53L0X_SENSOR_H
2 | #define __GROVE_VL53L0X_SENSOR_H
3 | #include "Seeed_vl53l0x.h"
4 | #include "sensor.h"
5 | #include "utils.h"
6 | #include "SoftwareI2C.h"
7 |
8 | #define VL53L0X_SDAPIN D1
9 | #define VL53L0X_SCLPIN D0
10 |
11 | class grove_vl53l0x_sensor : public sensor_base
12 | {
13 | public:
14 | grove_vl53l0x_sensor();
15 | const char *get_name();
16 | void init();
17 | bool read(struct sensor_data *data);
18 | bool is_connected;
19 | private:
20 | const char *name = "Distance";
21 | const char *data_unit = "mm";
22 | int vl53l0x_value;
23 |
24 | Seeed_vl53l0x VL53L0X;
25 | };
26 |
27 | #endif
--------------------------------------------------------------------------------
/tools/K1100-decoder.js:
--------------------------------------------------------------------------------
1 | function Decoder(bytes, port) {
2 |
3 | var decoded = {};
4 |
5 | function transformersint(bytes){
6 | value = bytes[0] * 256 + bytes[1];
7 | if (value == 32768){
8 | return;
9 | }
10 | if (value > 32768) {
11 | value = 32768 - value;
12 | }
13 | value = value;
14 | return value;
15 | }
16 |
17 | function transformersfloat(bytes){
18 | value = bytes[0] * 256 + bytes[1];
19 | if (value == 32768){
20 | return;
21 | }
22 | if (value > 32768) {
23 | value = 32768 - value;
24 | }
25 | value = value;
26 | return value/100;
27 | }
28 |
29 | function transformersAI(bytes){
30 | value = bytes[0];
31 | if (value == 255 || value >100){
32 | return;
33 | }
34 | return value;
35 | }
36 |
37 | if (port == 3) {
38 | if(bytes[0]==0x40) {
39 | decoded.light = transformersint(bytes.slice(1, 3));
40 | decoded.mic = transformersint(bytes.slice(3, 5));
41 | decoded.imux = transformersfloat(bytes.slice(5, 7));
42 | decoded.imuy = transformersfloat(bytes.slice(7, 9));
43 | decoded.imuz = transformersfloat(bytes.slice(9, 11));
44 | }
45 | if(bytes[0]==0x42) {
46 | decoded.temp = transformersfloat(bytes.slice(1, 3));
47 | decoded.humi = transformersfloat(bytes.slice(3, 5));
48 | decoded.voc = transformersint(bytes.slice(5, 7));
49 | decoded.co2 = transformersint(bytes.slice(7, 9));
50 | decoded.soil = transformersint(bytes.slice(9, 11));
51 | }
52 | if(bytes[0]==0x44) {
53 | decoded.confidence_1 = transformersAI(bytes.slice(2));
54 | decoded.confidence_2 = transformersAI(bytes.slice(4));
55 | decoded.confidence_3 = transformersAI(bytes.slice(6));
56 | decoded.confidence_4 = transformersAI(bytes.slice(8));
57 | decoded.confidence_5 = transformersAI(bytes.slice(10));
58 | }
59 |
60 | }
61 |
62 | return decoded;
63 | }
--------------------------------------------------------------------------------