Compare commits
168 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a83959ab5f | ||
|
|
b1896002e5 | ||
|
|
cc39de9b04 | ||
|
|
a286b5d067 | ||
|
|
f071f57abf | ||
|
|
0e0fe334cd | ||
|
|
23410c618d | ||
|
|
b44898f08d | ||
|
|
165f356439 | ||
|
|
1d0df2936b | ||
|
|
1684d63e04 | ||
|
|
cf5dfb43d6 | ||
|
|
ded6638ef6 | ||
|
|
a8228851d9 | ||
|
|
633289def6 | ||
|
|
f4ff13d6b7 | ||
|
|
0493ec2245 | ||
|
|
4c6bbb8aae | ||
|
|
b625f636be | ||
|
|
3bfd62d075 | ||
|
|
b405adb359 | ||
|
|
accf37de39 | ||
|
|
582eed3be8 | ||
|
|
35d5ec03a3 | ||
|
|
737c627d44 | ||
|
|
84a3120c7f | ||
|
|
99b9ed1181 | ||
|
|
0d636a3285 | ||
|
|
79ccd47f71 | ||
|
|
3ffc70abe5 | ||
|
|
f4f2eda481 | ||
|
|
f4b2c74b0e | ||
|
|
111e5a66b6 | ||
|
|
b90723130d | ||
|
|
e6179761d4 | ||
|
|
b371fd3468 | ||
|
|
c8fccdbb47 | ||
|
|
4876401809 | ||
|
|
45af7c188a | ||
|
|
236e9ccda6 | ||
|
|
94e8b9f87e | ||
|
|
c9580d6627 | ||
|
|
87929373e2 | ||
|
|
4e2aec9ced | ||
|
|
fa7957f5e2 | ||
|
|
4f15805246 | ||
|
|
cf67c815e9 | ||
|
|
5533dc807f | ||
|
|
ac2aabe6e3 | ||
|
|
c6a428ddd4 | ||
|
|
a83a845d5a | ||
|
|
c91b188f96 | ||
|
|
53a6f4593e | ||
|
|
0dda769d0f | ||
|
|
848df066c4 | ||
|
|
b4005d8bad | ||
|
|
34c0df2761 | ||
|
|
cedfc2c8db | ||
|
|
c9fe63ec7b | ||
|
|
2fedcb61b5 | ||
|
|
272b033253 | ||
|
|
cae03d54d6 | ||
|
|
e70f1a591f | ||
|
|
0e768ac6e4 | ||
|
|
bc056eaca2 | ||
|
|
a6ad84a3b8 | ||
|
|
a5b953dc80 | ||
|
|
d446b05387 | ||
|
|
e864e5ef24 | ||
|
|
e669507759 | ||
|
|
e50c04cbe1 | ||
|
|
56dd57f4a0 | ||
|
|
f2abb564c7 | ||
|
|
4e7abb2350 | ||
|
|
540e499389 | ||
|
|
191a2bdd2a | ||
|
|
4d1c8357b4 | ||
|
|
85b5b1df91 | ||
|
|
c3e2c105d4 | ||
|
|
dba602a081 | ||
|
|
c3f2ce57f0 | ||
|
|
bbf8e0b6b6 | ||
|
|
03ab020dc8 | ||
|
|
9c1f3225a6 | ||
|
|
f72dd3b7d7 | ||
|
|
48f6210607 | ||
|
|
6f9be2b139 | ||
|
|
3217525873 | ||
|
|
e26972bd2f | ||
|
|
bf31533306 | ||
|
|
0ca0577667 | ||
|
|
0e797e7e04 | ||
|
|
a661ef3a3f | ||
|
|
17dc1dcf8c | ||
|
|
4c27aa57b1 | ||
|
|
a21c07fa03 | ||
|
|
bdffa7ef53 | ||
|
|
22d40825bb | ||
|
|
50f26f546c | ||
|
|
9c7ea46ec3 | ||
|
|
5b4cf53d8a | ||
|
|
79a701a4d4 | ||
|
|
81897e634c | ||
|
|
3e11da4dd4 | ||
|
|
12aa7fef04 | ||
|
|
1ea6420bbc | ||
|
|
f3f1f36525 | ||
|
|
dee9a98cc3 | ||
|
|
3345ce3fb9 | ||
|
|
de70583838 | ||
|
|
a43a737004 | ||
|
|
1f6899354f | ||
|
|
9110a0c47e | ||
|
|
b549790798 | ||
|
|
5df430f3be | ||
|
|
f3e8bcd74a | ||
|
|
4b050e11cf | ||
|
|
7ddbc09564 | ||
|
|
d3d62f80fd | ||
|
|
bc7dbe6eec | ||
|
|
e625f55353 | ||
|
|
aeebff9d5d | ||
|
|
9a3c077ef1 | ||
|
|
91ae692058 | ||
|
|
ad590d1eb2 | ||
|
|
8b00358901 | ||
|
|
bf4d8bb9be | ||
|
|
157dd2f407 | ||
|
|
1dc47878d4 | ||
|
|
36e4b6fd45 | ||
|
|
36d9a6e7e4 | ||
|
|
b7cceed4d3 | ||
|
|
694c06e7f5 | ||
|
|
12338747bf | ||
|
|
f4f9788f68 | ||
|
|
b9cdcad262 | ||
|
|
e4cd2ddec8 | ||
|
|
1477649a50 | ||
|
|
2e80469ab3 | ||
|
|
ccf63a4cdb | ||
|
|
b464871f73 | ||
|
|
e44834a95e | ||
|
|
4efefc5c6c | ||
|
|
dfd852b2db | ||
|
|
afa7141ceb | ||
|
|
ed76b23c69 | ||
|
|
a469a466ff | ||
|
|
589d3ef4d8 | ||
|
|
5aba2eb4a1 | ||
|
|
b7df8d7b37 | ||
|
|
61554e6c7e | ||
|
|
d8cc61bc0e | ||
|
|
4b6e3956d6 | ||
|
|
9659ff8afa | ||
|
|
783955cc5d | ||
|
|
048556803b | ||
|
|
5c46939556 | ||
|
|
222d58e973 | ||
|
|
38343112a5 | ||
|
|
770a7bc4fa | ||
|
|
d6695f127d | ||
|
|
35e5fc5173 | ||
|
|
b58ea46c22 | ||
|
|
470eb64051 | ||
|
|
6192e9be72 | ||
|
|
b518451888 | ||
|
|
7b5dcdf07e | ||
|
|
515d47f055 |
29
.clang-format
Normal file
29
.clang-format
Normal file
@@ -0,0 +1,29 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AlignArrayOfStructures: Left
|
||||
AlignConsecutiveAssignments: true
|
||||
AlignConsecutiveMacros: AcrossComments
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeTernaryOperators: true
|
||||
ColumnLimit: 120
|
||||
ContinuationIndentWidth: 4
|
||||
EmptyLineBeforeAccessModifier: Always
|
||||
FixNamespaceComments: true
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseLabels: true
|
||||
IndentWidth: 4
|
||||
LambdaBodyIndentation: Signature
|
||||
MaxEmptyLinesToKeep: 1
|
||||
# PointerAlignment: Left # TODO enable this and reformat project
|
||||
QualifierAlignment: Left
|
||||
ReflowComments: true
|
||||
SeparateDefinitionBlocks: Always
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
22
.github/workflows/docs.yml
vendored
Normal file
22
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Deploy docs on GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
docs:
|
||||
name: Deploy docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout main
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Deploy docs
|
||||
uses: mhausenblas/mkdocs-deploy-gh-pages@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
CONFIG_FILE: mkdocs.yml
|
||||
EXTRA_PACKAGES: build-base doxygen
|
||||
REQUIREMENTS: docs/requirements.txt
|
||||
35
.github/workflows/lint.yml
vendored
Normal file
35
.github/workflows/lint.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
name: Lint check
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
lint-clang-format:
|
||||
name: Lint with clang-format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Check code with clang-format
|
||||
uses: jidicula/clang-format-action@v4.5.0
|
||||
with:
|
||||
clang-format-version: "14"
|
||||
lint-black:
|
||||
name: Lint with black
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.9"
|
||||
- name: Install test dependencies
|
||||
uses: BSFishy/pip-action@v1
|
||||
with:
|
||||
packages: |
|
||||
black
|
||||
isort
|
||||
- name: Check code with black
|
||||
run: black --check .
|
||||
- name: Check code with isort
|
||||
run: isort --profile black . --check-only
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -252,3 +252,10 @@ cython_debug/
|
||||
# End of https://www.toptal.com/developers/gitignore/api/c,c++,visualstudiocode,python
|
||||
|
||||
.vscode/settings.json
|
||||
|
||||
# mkdocs
|
||||
xml/
|
||||
ltapi/
|
||||
ltambz/
|
||||
hashChanges.yaml
|
||||
.piopm
|
||||
|
||||
2
.gitmodules
vendored
Normal file
2
.gitmodules
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
[submodule "tools/boardgen"]
|
||||
url = https://github.com/kuba2k2/boardgen
|
||||
211
README.md
211
README.md
@@ -1,197 +1,90 @@
|
||||
# LibreTuya
|
||||
|
||||
<div align="center">
|
||||
<div align="center" markdown>
|
||||
|
||||
[](https://kuba2k2.github.io/libretuya/)
|
||||

|
||||
|
||||
[](.clang-format)
|
||||
[](https://github.com/psf/black)
|
||||
|
||||
[](https://discord.gg/SyGCB9Xwtf)
|
||||
[](https://registry.platformio.org/platforms/kuba2k2/libretuya)
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
PlatformIO development platform for IoT modules manufactured by Tuya Inc.
|
||||
|
||||
The main goal of this project is to provide a usable build environment for IoT developers. While also providing vendor SDKs as PlatformIO cores,
|
||||
the project focuses on developing working Arduino-compatible cores for supported platforms. The cores are inspired by Espressif's official core for ESP32,
|
||||
which should make it easier to port/run existing ESP apps on Tuya IoT (and 3-rd party) platforms.
|
||||
the project focuses on developing working Arduino-compatible cores for supported families. The cores are inspired by Espressif's official core for ESP32,
|
||||
which should make it easier to port/run existing ESP apps on Tuya IoT (and 3-rd party) modules.
|
||||
|
||||
LibreTuya also provides a common interface for all platform implementations. The interface is based on ESP32 official libraries.
|
||||
LibreTuya also provides a common interface for all family implementations. The interface is based on ESP32 official libraries.
|
||||
|
||||
**Note:** this project is work-in-progress.
|
||||
|
||||
## Usage
|
||||
|
||||
1. [Install PlatformIO](https://platformio.org/platformio-ide)
|
||||
2. `platformio platform install libretuya`
|
||||
2. `platformio platform install https://github.com/kuba2k2/libretuya`
|
||||
3. Create a project, build it and upload!
|
||||
4. See the [docs](docs/README.md) for any questions/problems.
|
||||
4. See the [docs](https://kuba2k2.github.io/libretuya/) for any questions/problems.
|
||||
|
||||
## Board List
|
||||
|
||||
A (mostly) complete* list of Tuya wireless module boards.
|
||||
|
||||
| Module Name | MCU | Flash | RAM | Pins** | Wi-Fi | BLE | Platform name
|
||||
------------------------------|------------------------------------------------------------------------------------------------|-------------------------|-------|----------|-------------|-------|-----|---------------
|
||||
❌ | [WB1S](https://developer.tuya.com/en/docs/iot/wb1s?id=K9duevbj3ol4x) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WB2L](https://developer.tuya.com/en/docs/iot/wb2l-datasheet?id=K9duegc9bualu) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WB2S](https://developer.tuya.com/en/docs/iot/wb2s-module-datasheet?id=K9ghecl7kc479) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WB3L](https://developer.tuya.com/en/docs/iot/wb3l-module-datasheet?id=K9duiggw2v8sp) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WB3S](https://developer.tuya.com/en/docs/iot/wb3s-module-datasheet?id=K9dx20n6hz5n4) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 16 (11 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WB3S-IPEX](https://developer.tuya.com/en/docs/iot/wb3sipex-module-datasheet?id=K9irq0laun21z) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 16 (11 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WB8P](https://developer.tuya.com/en/docs/iot/wb8p-module-datasheet?id=K9fwx4f89tvzd) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 10 (8 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WBLC5](https://developer.tuya.com/en/docs/iot/wblc5-module-datasheet?id=K9duilns1f3gi) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 6 (3 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WBLC9](https://developer.tuya.com/en/docs/iot/wblc9-module-datasheet?id=K9hgglry2jp5h) | BK7231T @ 120 MHz | 2 MiB | 256 KiB | 8 (6 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB1S](https://developer.tuya.com/en/docs/iot/cb1s-module-datasheet?id=Kaij1abmwyjq2) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB2L](https://developer.tuya.com/en/docs/iot/cb2l-module-datasheet?id=Kai2eku1m3pyl) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB2S](https://developer.tuya.com/en/docs/iot/cb2s-module-datasheet?id=Kafgfsa2aaypq) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB3L](https://developer.tuya.com/en/docs/iot/cb3l-module-datasheet?id=Kai51ngmrh3qm) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 16 (11 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB3S](https://developer.tuya.com/en/docs/iot/cb3s?id=Kai94mec0s076) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 22 (14 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB3S-NL](https://developer.tuya.com/en/docs/iot/CB3S-NL-module-datasheet?id=Kbaesan0vyoms) | BK7231NL (?) @ 120 MHz | 2 MiB | 256 KiB | 22 (14 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB3SE](https://developer.tuya.com/en/docs/iot/CB3SE-Module-Datasheet?id=Kanoiluul7nl2) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 22 (17 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CB8P](https://developer.tuya.com/en/docs/iot/cb8p-module-datasheet?id=Kahvig14r1yk9) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 10 (8 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CBLC5](https://developer.tuya.com/en/docs/iot/cblc5-module-datasheet?id=Ka07iqyusq1wm) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 6 (3 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CBLC9](https://developer.tuya.com/en/docs/iot/cblc9-module-datasheet?id=Ka42cqnj9r0i5) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 8 (6 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CBU](https://developer.tuya.com/en/docs/iot/cbu-module-datasheet?id=Ka07pykl5dk4u) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 21 (18 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CBU-IPEX](https://developer.tuya.com/en/docs/iot/cbuipex-module-datasheet?id=Kaedsyurckrhu) | BK7231N @ 120 MHz | 2 MiB | 256 KiB | 21 (18 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [CBU-NL](https://developer.tuya.com/en/docs/iot/CBU-NL-module-datasheet?id=Kbaeq6j53y0yg) | BK7231N (?) @ 120 MHz | 2 MiB | 256 KiB | 21 (18 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WR1](https://developer.tuya.com/en/docs/iot/wifiwr1module?id=K9605tc0k90t3) | RTL8710BN @ 125 MHz | 1 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR1-IPEX](https://developer.tuya.com/en/docs/iot/wifiwr1ipexmodule?id=K9605t977tx5u) | RTL8710BN @ 125 MHz | 1 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR1E](https://developer.tuya.com/en/docs/iot/wr1e?id=K96smbbeycxtf) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 18 (11 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR2](https://developer.tuya.com/en/docs/iot/wifiwr2module?id=K9605tko0juc3) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR2E](https://developer.tuya.com/en/docs/iot/wr2e?id=K97scnsjhue4h) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 11 (8 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR2L](https://developer.tuya.com/en/docs/iot/wifiwr2lmodule?id=K9605tnbj7gva) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR2LE](https://developer.tuya.com/en/docs/iot/wr2le?id=K9eio9y9e8i8c) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 7 (5 I/O) | ✔️ | ❌ | -
|
||||
[`wr3`](boards/wr3/README.md) | [WR3](https://developer.tuya.com/en/docs/iot/wr3-module-datasheet?id=K9g3ainzbj9z1) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | `realtek-ambz`
|
||||
❌ | [WR3E](https://developer.tuya.com/en/docs/iot/wr3e-module-datasheet?id=K9elwlqbfosbc) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR3L](https://developer.tuya.com/en/docs/iot/wifiwr3lmodule?id=K9605tt0kveqm) | RTL8710BX @ 125 MHz (?) | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR3LE](https://developer.tuya.com/en/docs/iot/wr3le?id=K986l7a1ha8tm) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR3N](https://developer.tuya.com/en/docs/iot/wr3n-datasheet?id=K98zdx31ztdge) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 16 (10 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR4](https://developer.tuya.com/en/docs/iot/wifiwr4module?id=K9605tvu78p3e) | RTL8710BN @ 125 MHz | 1 MiB | 256 KiB | 16 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR5E](https://developer.tuya.com/en/docs/iot/wr5e?id=K986r9pxqxa8i) | RTL8710BX @ 62.5 MHz | 2 MiB | 256 KiB | 15 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR6-H](https://developer.tuya.com/en/docs/iot/wr6h-module-datasheet?id=K9pork8eeowgl) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 18 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WR6](https://developer.tuya.com/en/docs/iot/wr6-datasheet?id=K97rp45u6gff9) | RTL8710BN @ 125 MHz | 2 MiB | 256 KiB | 18 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WRG1](https://developer.tuya.com/en/docs/iot/wr6-datasheet?id=K97rp45u6gff9) | RTL8711AM @ 166 MHz | 4 MiB | 2048 KiB | 25 (20 I/O) | ✔️ | ❌ | -
|
||||
❌ | [XR1](https://developer.tuya.com/en/docs/iot/xr1?id=K9lq3y9xo0zkx) | XR809 @ 160 MHz | 2 MiB | 384 KiB | 18 (11 I/O) | ✔️ | ❌ | -
|
||||
❌ | [XR1-IPEX](https://developer.tuya.com/en/docs/iot/xr1ipex-module-datasheet?id=K9razqu9gqele) | XR809 @ 160 MHz | 2 MiB | 384 KiB | 18 (11 I/O) | ✔️ | ❌ | -
|
||||
❌ | [XR3](https://developer.tuya.com/en/docs/iot/xr3-datasheet?id=K98s9168qi49g) | XR809 @ 160 MHz | 2 MiB | 384 KiB | 22 (17 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WE1S](https://developer.tuya.com/en/docs/iot/wifie1smodule?id=K9605thnvg3e7) | ESP8266EX @ 80/160 MHz | 2 MiB | 36 KiB | 18 (11 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WE2L](https://developer.tuya.com/en/docs/iot/wifie2lmodule?id=K9605ud0gkjmh) | ESP8285 @ 80/160 MHz | 1 MiB | 50 KiB | 7 (5 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WE2S](https://developer.tuya.com/en/docs/iot/wifie2smodule?id=K9605u79tgxug) | ESP8285 @ 80/160 MHz | 1 MiB | 50 KiB | 11 (8 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WE3L](https://developer.tuya.com/en/docs/iot/wifie3lpinmodule?id=K9605uj1ar87n) | ESP8266 @ 80/160 MHz | 2 MiB | 50 KiB | 16 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WE3S](https://developer.tuya.com/en/docs/iot/wifie3smodule?id=K9605ua1cx9tv) | ESP8266 @ 80/160 MHz | 2 MiB | 50 KiB | 16 (12 I/O) | ✔️ | ❌ | -
|
||||
❌ | [WE3SE](https://developer.tuya.com/en/docs/iot/we3se?id=K97qv6ab7oh8d) | ESP32 @ 240 MHz | 4 MiB | 520 KiB | 22 (17 I/O) | ✔️ | ✔️ | -
|
||||
❌ | [WE5P](https://developer.tuya.com/en/docs/iot/wifie5pmodule?id=K9605um3dtjbx) | ESP8266 @ 80/160 MHz | 1 MiB | 50 KiB | 15 (11 I/O) | ✔️ | ❌ | -
|
||||
|
||||
\* Only modules featuring at least Wi-Fi. WBR, JWBR, CR, (TY)JW and (TY)LC Series are not included here
|
||||
|
||||
** I/O count includes GPIOs, ADCs, PWM outputs and UART, but doesn't count CEN/RST and power pins.
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
arduino/
|
||||
├─ <platform name>/ Arduino Core for specific platform
|
||||
│ ├─ cores/ Core files
|
||||
│ ├─ libraries/ Supported built-in libraries
|
||||
├─ libretuya/
|
||||
│ ├─ api/ LibreTuya API for Arduino frameworks
|
||||
│ ├─ compat/ Fixes for compatibility with ESP32 framework
|
||||
│ ├─ libraries/ Built-in platform-independent libraries
|
||||
boards/
|
||||
├─ <board name>/ Board-specific code
|
||||
│ ├─ variant.cpp Arduino variant initialization
|
||||
│ ├─ variant.h Arduino variant pin configs
|
||||
├─ <board name>.json PlatformIO board description
|
||||
builder/
|
||||
├─ frameworks/ Framework builders for PlatformIO
|
||||
│ ├─ <platform name>-sdk.py Vanilla SDK build system
|
||||
│ ├─ <platform name>-arduino.py Arduino Core build system
|
||||
├─ arduino-common.py Builder to provide ArduinoCore-API and LibreTuya APIs
|
||||
├─ main.py Main PlatformIO builder
|
||||
docs/ Project documentation, guides, tips, etc.
|
||||
platform/
|
||||
├─ <platform name>/ Platform-specific configurations
|
||||
│ ├─ bin/ Binary blobs (bootloaders, etc.)
|
||||
│ ├─ fixups/ Code fix-ups to replace SDK parts
|
||||
│ ├─ ld/ Linker scripts
|
||||
│ ├─ openocd/ OpenOCD configuration files
|
||||
tools/
|
||||
├─ <tool name>/ Tools used during the build
|
||||
platform.json PlatformIO manifest
|
||||
platform.py Custom PlatformIO script
|
||||
```
|
||||
|
||||
## Platforms
|
||||
|
||||
A list of platforms currently available in this project.
|
||||
|
||||
Platform name | Supported MCU(s) | Arduino Core | Source SDK (PIO framework)
|
||||
---------------|------------------------------------------------------------------------|--------------|--------------------------------------------------------------------------
|
||||
`realtek-ambz` | Realtek [AmebaZ](https://www.amebaiot.com/en/amebaz/) SoC (`RTL87xxB`) | ✔️ | `framework-realtek-amb1` ([amb1_sdk](https://github.com/ambiot/amb1_sdk))
|
||||
|
||||
### Realtek Ameba
|
||||
|
||||
The logic behind naming of Realtek chips and their series took me some time to figure out:
|
||||
- RTL8xxxA - Ameba1/Ameba Series
|
||||
- RTL8xxxB - AmebaZ Series
|
||||
- RTL8xxxC - AmebaZ2/ZII Series
|
||||
- RTL8xxxD - AmebaD Series
|
||||
|
||||
As such, there are numerous CPUs with the same numbers but different series, which makes them require different code and SDKs.
|
||||
- [RTL8195AM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8195am)
|
||||
- RTL8710AF (found in amb1_arduino)
|
||||
- [RTL8711AM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8711am)
|
||||
- [RTL8710BN](https://www.realtek.com/en/products/communications-network-ics/item/rtl8710bn)
|
||||
- RTL8710BX (found in Tuya product pages)
|
||||
- RTL8710B? (found in amb1_sdk)
|
||||
- RTL8711B? (found in amb1_sdk)
|
||||
- [RTL8710CM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8710cm)
|
||||
- RTL8722CSM (found in ambd_arduino)
|
||||
- RTL8720DN (found in ambd_arduino)
|
||||
- [RTL8721DM](https://www.realtek.com/en/products/communications-network-ics/item/rtl8721dm)
|
||||
- RTL8722DM (found in ambd_arduino)
|
||||
- and probably many more
|
||||
|
||||
Different Ameba series are not compatible with each other. Apparently, there isn't an official public SDK for AmebaZ that can support C++ properly.
|
||||
See [Boards & CPU list](https://kuba2k2.github.io/libretuya/docs/supported/).
|
||||
|
||||
## Arduino Core support status
|
||||
|
||||
Note: this list will probably change with each functionality update.
|
||||
|
||||
| `realtek-ambz`
|
||||
--------------------|---------------
|
||||
Core functions | ✔️
|
||||
GPIO/PWM/IRQ | ✔️/❓/✔️
|
||||
Analog input | ❓
|
||||
UART I/O | ✔️
|
||||
Flash I/O | ❓
|
||||
**CORE LIBRARIES** |
|
||||
SoftwareSerial | ❌
|
||||
SPI | ❌
|
||||
Wire | ❌
|
||||
**OTHER LIBRARIES** |
|
||||
Wi-Fi Station | ✔️
|
||||
Wi-Fi Access Point | ✔️
|
||||
Wi-Fi Events | ❌
|
||||
Wi-Fi Client (SSL) | ✔️ (❌)
|
||||
Wi-Fi Server | ✔️
|
||||
SPIFFS | ❌
|
||||
BLE | -
|
||||
HTTP | ❌
|
||||
NTP | ❌
|
||||
OTA | ❌
|
||||
MDNS | ❌
|
||||
MQTT | ❌
|
||||
SD | ❌
|
||||
| `realtek-ambz` | `beken-72xx`
|
||||
--------------------|----------------|-------------
|
||||
Core functions | ✔️ | ✔️
|
||||
GPIO/PWM/IRQ | ✔️/✔️/✔️ | ❓/✔️/❌
|
||||
Analog input (ADC) | ✔️ | ✔️
|
||||
Serial | ✔️ | ✔️
|
||||
Serial (extra) | ❌ | 1, 2
|
||||
Flash I/O | ✔️ | ✔️
|
||||
**CORE LIBRARIES** | |
|
||||
SoftwareSerial | ❌ | ❌
|
||||
SPI | ❌ | ❌
|
||||
Wire | ❗ | ❌
|
||||
**OTHER LIBRARIES** | |
|
||||
Wi-Fi STA/AP/Mixed | ✔️ | ✔️/❌/❌
|
||||
Wi-Fi Events | ✔️ | ❌
|
||||
TCP Client (SSL) | ✔️ (✔️) | ✔️ (❗)
|
||||
TCP Server | ✔️ | ✔️
|
||||
IPv6 | ❌ | ❌
|
||||
HTTP Client (SSL) | ✔️ (✔️) | ❓
|
||||
HTTP Server | ✔️ | ✔️
|
||||
NVS / Preferences | ❌ | ❌
|
||||
SPIFFS | ❌ | ❌
|
||||
BLE | - | ❌
|
||||
NTP | ❌ | ❌
|
||||
OTA | ✔️ | ❌
|
||||
MDNS | ✔️ | ✔️
|
||||
MQTT | ✅ | ❌
|
||||
SD | ❌ | ❌
|
||||
|
||||
Symbols:
|
||||
|
||||
Legend:
|
||||
- ✔️ working
|
||||
- ❗ broken
|
||||
- ✅ tested, external library
|
||||
- ❓ untested
|
||||
- ❗ broken
|
||||
- ❌ not implemented (yet?)
|
||||
- \- not applicable
|
||||
|
||||
Names:
|
||||
|
||||
- Core functions - stuff like delay(), millis(), yield(), etc.
|
||||
- **CORE LIBRARIES** - included normally in all Arduino cores
|
||||
- **OTHER LIBRARIES** - included in ESP32 core or downloadable
|
||||
|
||||
## License
|
||||
|
||||
See [LICENSE](LICENSE). Project is licensed under MIT License.
|
||||
|
||||
53
SUMMARY.md
Normal file
53
SUMMARY.md
Normal file
@@ -0,0 +1,53 @@
|
||||
* [Home](README.md)
|
||||
* [💻 Boards & CPU list](docs/supported.md)
|
||||
* [✔️ Implementation status](docs/implementation-status.md)
|
||||
* [🔧 Configuration](docs/config.md)
|
||||
* [📁 Project structure](docs/project-structure.md)
|
||||
* 🔖 Code reference
|
||||
* [LibreTuya API](docs/reference/lt-api.md)
|
||||
* [LT class reference](ltapi/class_libre_tuya.md)
|
||||
* [Common methods](ltapi/_libre_tuya_a_p_i_8h.md)
|
||||
* [Wiring custom methods](ltapi/_libre_tuya_custom_8h.md)
|
||||
* [Logger](ltapi/lt__logger_8h.md)
|
||||
* [Chip & family IDs](ltapi/_chip_type_8h_source.md)
|
||||
* [POSIX utilities](ltapi/lt__posix__api_8h.md)
|
||||
* Common API
|
||||
* [FS](ltapi/classfs_1_1_f_s.md)
|
||||
* [Preferences](ltapi/class_i_preferences.md)
|
||||
* [WiFi API](ltapi/class_wi_fi_class.md)
|
||||
* [TCP Client](ltapi/class_i_wi_fi_client.md)
|
||||
* [SSL Client](ltapi/class_i_wi_fi_client_secure.md)
|
||||
* [TCP Server](ltapi/class_i_wi_fi_server.md)
|
||||
* [LibreTuya libraries](docs/libs-built-in.md)
|
||||
* [base64](ltapi/classbase64.md)
|
||||
* [Flash](ltapi/class_flash_class.md)
|
||||
* [HTTPClient](ltapi/class_h_t_t_p_client.md)
|
||||
* [mDNS](ltapi/classm_d_n_s.md)
|
||||
* NetUtils
|
||||
* [ssl/MbedTLSClient](ltapi/class_mbed_t_l_s_client.md)
|
||||
* [IPv6Address](ltapi/classarduino_1_1_i_pv6_address.md)
|
||||
* [LwIPRxBuffer](ltapi/class_lw_i_p_rx_buffer.md)
|
||||
* [Update](ltapi/class_update_class.md)
|
||||
* [WebServer](ltapi/class_web_server.md)
|
||||
* [WiFiMulti](ltapi/class_wi_fi_multi.md)
|
||||
* [Third party libraries](docs/libs-3rd-party.md)
|
||||
* Full documentation
|
||||
* [Classes](ltapi/classes.md)
|
||||
* [Functions](ltapi/functions.md)
|
||||
* [Macros](ltapi/macros.md)
|
||||
* [File list](ltapi/files.md)
|
||||
* [✈️ OTA format](docs/ota/README.md)
|
||||
* [uf2ota.py tool](docs/ota/uf2ota.md)
|
||||
* [uf2ota.h library](docs/ota/library.md)
|
||||
* [uf2ota.h reference](ltapi/uf2ota_8h.md)
|
||||
* Families
|
||||
* [Realtek - notes](docs/platform/realtek/README.md)
|
||||
* [Beken 72xx - notes](docs/platform/beken-72xx/README.md)
|
||||
* Realtek AmebaZ Series
|
||||
* C library
|
||||
* [Built-in functions](docs/platform/realtek-ambz/stdlib.md)
|
||||
* [Memory management](docs/platform/realtek-ambz/memory-management.md)
|
||||
* [Debugging](docs/platform/realtek/debugging.md)
|
||||
* [Exception decoder](docs/platform/realtek/exception-decoder.md)
|
||||
* [All supported boards](boards/)
|
||||
* [🔗 Resources](docs/resources.md)
|
||||
32
arduino/beken-72xx/cores/arduino/Arduino.h
Normal file
32
arduino/beken-72xx/cores/arduino/Arduino.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-14. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "WCharacterFixup.h"
|
||||
#endif
|
||||
|
||||
#include <api/ArduinoAPI.h>
|
||||
#include <core/LibreTuyaAPI.h>
|
||||
|
||||
// Include family-specific code
|
||||
#include "WVariant.h"
|
||||
// Include board variant
|
||||
#include "variant.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "SerialClass.h"
|
||||
#ifdef HAS_SERIAL_CLASS
|
||||
// declare instances of available Serial* components
|
||||
// map Serial to Serial2 if available, else to Serial1
|
||||
#ifdef PIN_SERIAL1_RX
|
||||
extern SerialClass Serial1;
|
||||
#endif
|
||||
#ifdef PIN_SERIAL2_RX
|
||||
extern SerialClass Serial2;
|
||||
#define Serial Serial2
|
||||
#else
|
||||
#define Serial Serial1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
130
arduino/beken-72xx/cores/arduino/LibreTuyaAPI.cpp
Normal file
130
arduino/beken-72xx/cores/arduino/LibreTuyaAPI.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <LibreTuyaAPI.h>
|
||||
|
||||
// can't include <flash.h> as it collides with <Flash.h> on Windows -_-
|
||||
#define REG_FLASH_BASE 0x00803000
|
||||
#define REG_FLASH_OPERATE_SW (REG_FLASH_BASE + 0 * 4)
|
||||
#define REG_FLASH_RDID (REG_FLASH_BASE + 4 * 4)
|
||||
#define FLASH_BUSY_SW (0x01UL << 31)
|
||||
#define FLASH_WP_VALUE (0x01UL << 30)
|
||||
#define FLASH_OP_SW (0x01UL << 29)
|
||||
#define FLASH_OP_TYPE_POS 24
|
||||
#define FLASH_OP_RDID 20
|
||||
|
||||
extern "C" {
|
||||
#include <flash_pub.h>
|
||||
#include <sys_ctrl.h>
|
||||
#include <sys_rtos.h>
|
||||
#include <wlan_ui_pub.h>
|
||||
}
|
||||
|
||||
void LibreTuya::restart() {
|
||||
bk_reboot();
|
||||
}
|
||||
|
||||
/* CPU-related */
|
||||
|
||||
ChipType LibreTuya::getChipType() {
|
||||
uint8_t chipId = *(uint8_t *)(SCTRL_CHIP_ID);
|
||||
return CHIP_TYPE_ENUM(FAMILY, chipId);
|
||||
}
|
||||
|
||||
const char *LibreTuya::getChipModel() {
|
||||
return STRINGIFY_MACRO(MCU);
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getChipId() {
|
||||
// TODO determine if this really is unique
|
||||
uint32_t chipId = REG_READ(SCTRL_DEVICE_ID);
|
||||
chipId &= 0xFFFFFF;
|
||||
return chipId;
|
||||
}
|
||||
|
||||
uint8_t LibreTuya::getChipCores() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *LibreTuya::getChipCoreType() {
|
||||
return "ARM968E-S";
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getCpuFreq() {
|
||||
return configCPU_CLOCK_HZ;
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getCycleCount() {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Flash memory utilities */
|
||||
|
||||
FlashId LibreTuya::getFlashChipId() {
|
||||
uint32_t data = (FLASH_OP_RDID << FLASH_OP_TYPE_POS) | FLASH_OP_SW | FLASH_WP_VALUE;
|
||||
REG_WRITE(REG_FLASH_OPERATE_SW, data);
|
||||
while (REG_READ(REG_FLASH_OPERATE_SW) & FLASH_BUSY_SW) {}
|
||||
FlashId id = {
|
||||
.manufacturerId = REG_RD8(REG_FLASH_RDID, 2),
|
||||
.chipId = REG_RD8(REG_FLASH_RDID, 1),
|
||||
.chipSizeId = REG_RD8(REG_FLASH_RDID, 0),
|
||||
};
|
||||
return id;
|
||||
}
|
||||
|
||||
/* Memory management */
|
||||
|
||||
uint32_t LibreTuya::getRamSize() {
|
||||
return 256 * 1024;
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getHeapSize() {
|
||||
#if configDYNAMIC_HEAP_SIZE
|
||||
extern unsigned char _empty_ram;
|
||||
#if CFG_SOC_NAME == SOC_BK7231N
|
||||
return (0x00400000 + 192 * 1024) - (uint32_t)(&_empty_ram);
|
||||
#else
|
||||
return (0x00400000 + 256 * 1024) - (uint32_t)(&_empty_ram);
|
||||
#endif
|
||||
#else
|
||||
return configTOTAL_HEAP_SIZE;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getFreeHeap() {
|
||||
return xPortGetFreeHeapSize();
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getMinFreeHeap() {
|
||||
return xPortGetMinimumEverFreeHeapSize();
|
||||
}
|
||||
|
||||
uint32_t LibreTuya::getMaxAllocHeap() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* OTA-related */
|
||||
|
||||
uint8_t LibreTuya::otaGetStoredIndex() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool LibreTuya::otaSupportsDual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LibreTuya::otaHasImage1() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LibreTuya::otaHasImage2() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LibreTuya::otaSwitch(bool force) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Global instance */
|
||||
|
||||
LibreTuya LT;
|
||||
75
arduino/beken-72xx/cores/arduino/SerialClass.cpp
Normal file
75
arduino/beken-72xx/cores/arduino/SerialClass.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-23. */
|
||||
|
||||
#include "SerialClass.h"
|
||||
|
||||
extern "C" {
|
||||
#include <uart_pub.h>
|
||||
|
||||
extern void bk_send_byte(uint8_t uport, uint8_t data);
|
||||
extern void uart_hw_set_change(uint8_t uport, bk_uart_config_t *uart_config);
|
||||
extern int uart_rx_callback_set(int uport, uart_callback callback, void *param);
|
||||
}
|
||||
|
||||
#ifdef PIN_SERIAL1_RX
|
||||
SerialClass Serial1(UART1_PORT);
|
||||
#endif
|
||||
#ifdef PIN_SERIAL2_RX
|
||||
SerialClass Serial2(UART2_PORT);
|
||||
#endif
|
||||
|
||||
SerialClass::SerialClass(uint8_t port) {
|
||||
this->port = port;
|
||||
this->buf = NULL;
|
||||
}
|
||||
|
||||
static void callback(int port, void *param) {
|
||||
RingBuffer *buf = (RingBuffer *)param;
|
||||
buf->store_char(uart_read_byte(port));
|
||||
}
|
||||
|
||||
void SerialClass::begin(unsigned long baudrate, uint16_t config) {
|
||||
uint8_t dataWidth = ((config & SERIAL_DATA_MASK) >> 8) - 1; // 0x100..0x400 -> 0..3
|
||||
uint8_t parity = 3 - (config & SERIAL_PARITY_MASK); // 0x3..0x1 -> 0..2
|
||||
uint8_t stopBits = (config & SERIAL_STOP_BIT_MASK) == SERIAL_STOP_BIT_2; // 0x10..0x30 -> 0..1
|
||||
|
||||
bk_uart_config_t cfg = {
|
||||
.baud_rate = baudrate,
|
||||
.data_width = (uart_data_width_t)dataWidth,
|
||||
.parity = (uart_parity_t)parity,
|
||||
.stop_bits = (uart_stop_bits_t)stopBits,
|
||||
.flow_control = FLOW_CTRL_DISABLED,
|
||||
};
|
||||
if (this->buf) {
|
||||
this->buf->clear();
|
||||
} else {
|
||||
this->buf = new RingBuffer();
|
||||
}
|
||||
uart_hw_set_change(port, &cfg);
|
||||
uart_rx_callback_set(port, callback, this->buf);
|
||||
}
|
||||
|
||||
void SerialClass::end() {
|
||||
uart_rx_callback_set(port, NULL, NULL);
|
||||
delete this->buf;
|
||||
}
|
||||
|
||||
int SerialClass::available() {
|
||||
return buf->available();
|
||||
}
|
||||
|
||||
int SerialClass::peek() {
|
||||
return buf->peek();
|
||||
}
|
||||
|
||||
int SerialClass::read() {
|
||||
return buf->read_char();
|
||||
}
|
||||
|
||||
void SerialClass::flush() {
|
||||
uart_wait_tx_over();
|
||||
}
|
||||
|
||||
size_t SerialClass::write(uint8_t c) {
|
||||
bk_send_byte(port, c);
|
||||
return 1;
|
||||
}
|
||||
38
arduino/beken-72xx/cores/arduino/SerialClass.h
Normal file
38
arduino/beken-72xx/cores/arduino/SerialClass.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-23. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/HardwareSerial.h>
|
||||
#include <api/RingBuffer.h>
|
||||
|
||||
using namespace arduino;
|
||||
|
||||
class SerialClass : public HardwareSerial {
|
||||
private:
|
||||
uint8_t port;
|
||||
RingBuffer *buf;
|
||||
|
||||
public:
|
||||
SerialClass(uint8_t port);
|
||||
|
||||
inline void begin(unsigned long baudrate) {
|
||||
begin(baudrate, SERIAL_8N1);
|
||||
}
|
||||
|
||||
void begin(unsigned long baudrate, uint16_t config);
|
||||
void end();
|
||||
int available();
|
||||
int peek();
|
||||
int read();
|
||||
void flush();
|
||||
size_t write(uint8_t c);
|
||||
|
||||
operator bool() {
|
||||
return !!buf;
|
||||
}
|
||||
|
||||
using Print::write;
|
||||
};
|
||||
|
||||
#define HAS_SERIAL_CLASS 1
|
||||
21
arduino/beken-72xx/cores/arduino/WVariant.h
Normal file
21
arduino/beken-72xx/cores/arduino/WVariant.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-18. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sdk_extern.h"
|
||||
#include "sdk_mem.h"
|
||||
|
||||
// allow BDK use its own delay() and let Arduino code use delayMilliseconds()
|
||||
void delayMilliseconds(unsigned long);
|
||||
#define delay delayMilliseconds
|
||||
|
||||
// from fixups/arch_main.c
|
||||
extern unsigned char __bk_rf_is_init;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
25
arduino/beken-72xx/cores/arduino/main.cpp
Normal file
25
arduino/beken-72xx/cores/arduino/main.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
extern "C" {
|
||||
#include <rtos_pub.h>
|
||||
#include <sys_rtos.h>
|
||||
}
|
||||
|
||||
beken_thread_t mainThread;
|
||||
|
||||
bool startMainTask() {
|
||||
OSStatus ret = rtos_create_thread(
|
||||
&mainThread,
|
||||
THD_APPLICATION_PRIORITY,
|
||||
"main",
|
||||
(beken_thread_function_t)main_task,
|
||||
8192,
|
||||
NULL
|
||||
);
|
||||
if (ret != kNoErr)
|
||||
return false;
|
||||
vTaskStartScheduler();
|
||||
return true;
|
||||
}
|
||||
30
arduino/beken-72xx/cores/arduino/sdk_extern.h
Normal file
30
arduino/beken-72xx/cores/arduino/sdk_extern.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-18. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// for printf() etc (they are wrapped anyway)
|
||||
#include <stdio.h>
|
||||
|
||||
// most stuff is here
|
||||
#include <include.h>
|
||||
// for os_printf
|
||||
#include <uart_pub.h>
|
||||
// for GPIO names
|
||||
#include <gpio_pub.h>
|
||||
|
||||
// conflict with stl_algobase.h
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
// include printf() wrapper disable methods
|
||||
#include <printf_port.h>
|
||||
|
||||
// make non-SDK code call the proper printf()
|
||||
#undef bk_printf
|
||||
#undef os_printf
|
||||
#undef warning_prf
|
||||
#undef fatal_prf
|
||||
#define bk_printf printf
|
||||
#define os_printf printf
|
||||
#define warning_prf printf
|
||||
#define fatal_prf printf
|
||||
20
arduino/beken-72xx/cores/arduino/sdk_mem.h
Normal file
20
arduino/beken-72xx/cores/arduino/sdk_mem.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-18. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// Beken SDK is actually pretty good, in terms of declaring
|
||||
// stdlib functions properly! So no need for any #define hell.
|
||||
#include <mem_pub.h>
|
||||
|
||||
// All the MemMang functions are in stdlib, just wrapped
|
||||
// during linking.
|
||||
#include <stdlib.h>
|
||||
// for memcpy etc.
|
||||
#include <string.h>
|
||||
|
||||
// ...except zalloc, which is apparently not in the stdlib
|
||||
#define zalloc os_zalloc
|
||||
|
||||
#define LT_HEAP_FUNC xPortGetFreeHeapSize
|
||||
32
arduino/beken-72xx/cores/arduino/wiring.c
Normal file
32
arduino/beken-72xx/cores/arduino/wiring.c
Normal file
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <rtos_pub.h>
|
||||
#include <sys_rtos.h>
|
||||
|
||||
void delayMilliseconds(unsigned long ms) {
|
||||
rtos_delay_milliseconds(ms);
|
||||
}
|
||||
|
||||
void delayMicroseconds(unsigned int us) {
|
||||
// TODO implement this properly
|
||||
us /= 10;
|
||||
volatile uint32_t i, j;
|
||||
for (i = 0; i < us; i++) {
|
||||
for (j = 0; j < 100; j++) {}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long millis() {
|
||||
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||
}
|
||||
|
||||
unsigned long micros() {
|
||||
// TODO implement this properly
|
||||
return millis() * 1000;
|
||||
}
|
||||
|
||||
void yield() {
|
||||
vTaskDelay(1);
|
||||
taskYIELD();
|
||||
}
|
||||
113
arduino/beken-72xx/cores/arduino/wiring_analog.c
Normal file
113
arduino/beken-72xx/cores/arduino/wiring_analog.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <pwm_pub.h>
|
||||
#include <saradc_pub.h>
|
||||
|
||||
static GPIO_INDEX pwmToGpio[] = {
|
||||
GPIO6, // PWM0
|
||||
GPIO7, // PWM1
|
||||
GPIO8, // PWM2
|
||||
GPIO9, // PWM3
|
||||
GPIO24, // PWM4
|
||||
GPIO26, // PWM5
|
||||
};
|
||||
|
||||
static GPIO_INDEX adcToGpio[] = {
|
||||
-1, // ADC0 - VBAT
|
||||
GPIO4, // ADC1
|
||||
GPIO5, // ADC2
|
||||
GPIO23, // ADC3
|
||||
GPIO2, // ADC4
|
||||
GPIO3, // ADC5
|
||||
GPIO12, // ADC6
|
||||
GPIO13, // ADC7
|
||||
};
|
||||
|
||||
static uint8_t gpioToPwm(GPIO_INDEX gpio) {
|
||||
for (uint8_t i = 0; i < sizeof(pwmToGpio); i++) {
|
||||
if (pwmToGpio[i] == gpio)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t gpioToAdc(GPIO_INDEX gpio) {
|
||||
for (uint8_t i = 0; i < sizeof(adcToGpio); i++) {
|
||||
if (adcToGpio[i] == gpio)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pwm_param_t pwm;
|
||||
static uint16_t adcData[1];
|
||||
|
||||
uint16_t analogReadVoltage(pin_size_t pinNumber) {
|
||||
PinInfo *pin = pinInfo(pinNumber);
|
||||
if (!pin)
|
||||
return 0;
|
||||
if (!pinSupported(pin, PIN_ADC))
|
||||
return 0;
|
||||
|
||||
UINT32 status;
|
||||
saradc_desc_t adc;
|
||||
DD_HANDLE handle;
|
||||
saradc_config_param_init(&adc);
|
||||
adc.channel = gpioToAdc(pin->gpio);
|
||||
adc.mode = ADC_CONFIG_MODE_CONTINUE;
|
||||
adc.pData = adcData;
|
||||
adc.data_buff_size = 1;
|
||||
handle = ddev_open(SARADC_DEV_NAME, &status, (uint32_t)&adc);
|
||||
if (status)
|
||||
return 0;
|
||||
// wait for data
|
||||
while (!adc.has_data || adc.current_sample_data_cnt < 1) {
|
||||
delay(1);
|
||||
}
|
||||
ddev_control(handle, SARADC_CMD_RUN_OR_STOP_ADC, (void *)false);
|
||||
ddev_close(handle);
|
||||
return adcData[0];
|
||||
}
|
||||
|
||||
uint16_t analogReadMaxVoltage(pin_size_t pinNumber) {
|
||||
return 3300;
|
||||
}
|
||||
|
||||
void analogWrite(pin_size_t pinNumber, int value) {
|
||||
PinInfo *pin = pinInfo(pinNumber);
|
||||
if (!pin)
|
||||
return;
|
||||
if (!pinSupported(pin, PIN_PWM))
|
||||
return;
|
||||
|
||||
float percent = value * 1.0 / (1 << _analogWriteResolution);
|
||||
uint32_t dutyCycle = percent * _analogWritePeriod * 26 - 1;
|
||||
pwm.channel = gpioToPwm(pin->gpio);
|
||||
pwm.duty_cycle = dutyCycle;
|
||||
|
||||
if (!pinEnabled(pin, PIN_PWM)) {
|
||||
// enable PWM and set its value
|
||||
pwm.cfg.bits.en = PWM_ENABLE;
|
||||
pwm.cfg.bits.int_en = PWM_INT_DIS;
|
||||
pwm.cfg.bits.mode = PWM_PWM_MODE;
|
||||
pwm.cfg.bits.clk = PWM_CLK_26M;
|
||||
pwm.end_value = 26 * _analogWritePeriod - 1;
|
||||
pwm.p_Int_Handler = NULL;
|
||||
__wrap_bk_printf_disable();
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, &pwm);
|
||||
__wrap_bk_printf_enable();
|
||||
pin->enabled &= ~PIN_GPIO;
|
||||
pin->enabled |= PIN_PWM;
|
||||
} else if (value == 0) {
|
||||
// disable PWM
|
||||
pwm.cfg.bits.en = PWM_DISABLE;
|
||||
__wrap_bk_printf_disable();
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, &pwm);
|
||||
__wrap_bk_printf_enable();
|
||||
pin->enabled &= ~PIN_PWM;
|
||||
} else {
|
||||
// update duty cycle
|
||||
sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, &pwm);
|
||||
}
|
||||
}
|
||||
62
arduino/beken-72xx/cores/arduino/wiring_digital.c
Normal file
62
arduino/beken-72xx/cores/arduino/wiring_digital.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void pinMode(pin_size_t pinNumber, PinMode pinMode) {
|
||||
PinInfo *pin = pinInfo(pinNumber);
|
||||
if (!pin)
|
||||
return;
|
||||
if (!pinSupported(pin, PIN_GPIO))
|
||||
return;
|
||||
if (pinEnabled(pin, PIN_PWM))
|
||||
// disable PWM before using the pin
|
||||
analogWrite(pinNumber, 0);
|
||||
if (pinEnabled(pin, PIN_GPIO) && pin->mode == pinMode)
|
||||
return;
|
||||
switch (pinMode) {
|
||||
case INPUT:
|
||||
gpio_config(pin->gpio, GMODE_INPUT);
|
||||
break;
|
||||
case OUTPUT:
|
||||
gpio_config(pin->gpio, GMODE_OUTPUT);
|
||||
break;
|
||||
case INPUT_PULLUP:
|
||||
gpio_config(pin->gpio, GMODE_INPUT_PULLUP);
|
||||
break;
|
||||
case INPUT_PULLDOWN:
|
||||
gpio_config(pin->gpio, GMODE_INPUT_PULLDOWN);
|
||||
break;
|
||||
case OUTPUT_OPENDRAIN:
|
||||
gpio_config(pin->gpio, GMODE_SET_HIGH_IMPENDANCE);
|
||||
break;
|
||||
}
|
||||
pin->enabled |= PIN_GPIO;
|
||||
pin->mode = pinMode;
|
||||
}
|
||||
|
||||
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
|
||||
// verify level is 0 or 1
|
||||
if (status > HIGH)
|
||||
return;
|
||||
PinInfo *pin = pinInfo(pinNumber);
|
||||
if (!pin)
|
||||
return;
|
||||
// pin is not GPIO yet or not OUTPUT; enable or disable input pullup
|
||||
if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin)) {
|
||||
pinMode(pinNumber, status * INPUT_PULLUP);
|
||||
return;
|
||||
}
|
||||
// write the new state
|
||||
gpio_output(pin->gpio, status);
|
||||
}
|
||||
|
||||
PinStatus digitalRead(pin_size_t pinNumber) {
|
||||
PinInfo *pin = pinInfo(pinNumber);
|
||||
if (!pin)
|
||||
return 0;
|
||||
// pin is not GPIO yet or not INPUT; change the mode
|
||||
if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin))
|
||||
pinMode(pinNumber, INPUT);
|
||||
// read the value
|
||||
return gpio_input(pin->gpio);
|
||||
}
|
||||
56
arduino/beken-72xx/libraries/WiFi/WiFi.cpp
Normal file
56
arduino/beken-72xx/libraries/WiFi/WiFi.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-26. */
|
||||
|
||||
#include "WiFiPriv.h"
|
||||
|
||||
WiFiClass::WiFiClass() {
|
||||
data.scanSem = xSemaphoreCreateBinary();
|
||||
}
|
||||
|
||||
WiFiClass::~WiFiClass() {
|
||||
vSemaphoreDelete(data.scanSem);
|
||||
}
|
||||
|
||||
WiFiStatus eventTypeToStatus(uint8_t type) {
|
||||
// rw_msg_pub.h:9
|
||||
switch (type) {
|
||||
case RW_EVT_STA_IDLE:
|
||||
return WL_IDLE_STATUS;
|
||||
return WL_NO_SSID_AVAIL;
|
||||
case RW_EVT_STA_CONNECTING:
|
||||
case RW_EVT_STA_CONNECTED:
|
||||
return WL_SCAN_COMPLETED;
|
||||
case RW_EVT_STA_GOT_IP:
|
||||
return WL_CONNECTED;
|
||||
case RW_EVT_STA_PASSWORD_WRONG:
|
||||
case RW_EVT_STA_NO_AP_FOUND:
|
||||
case RW_EVT_STA_ASSOC_FULL:
|
||||
case RW_EVT_STA_CONNECT_FAILED:
|
||||
return WL_CONNECT_FAILED;
|
||||
case RW_EVT_STA_BEACON_LOSE:
|
||||
return WL_CONNECTION_LOST;
|
||||
case RW_EVT_STA_DISCONNECTED:
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
WiFiAuthMode securityTypeToAuthMode(uint8_t type) {
|
||||
// wlan_ui_pub.h:62
|
||||
switch (type) {
|
||||
case BK_SECURITY_TYPE_NONE:
|
||||
return WIFI_AUTH_OPEN;
|
||||
case BK_SECURITY_TYPE_WEP:
|
||||
return WIFI_AUTH_WEP;
|
||||
case BK_SECURITY_TYPE_WPA_TKIP:
|
||||
case BK_SECURITY_TYPE_WPA_AES:
|
||||
return WIFI_AUTH_WPA_PSK;
|
||||
case BK_SECURITY_TYPE_WPA2_TKIP:
|
||||
case BK_SECURITY_TYPE_WPA2_AES:
|
||||
case BK_SECURITY_TYPE_WPA2_MIXED:
|
||||
return WIFI_AUTH_WPA2_PSK;
|
||||
case BK_SECURITY_TYPE_WPA3_SAE:
|
||||
return WIFI_AUTH_WPA3_PSK;
|
||||
case BK_SECURITY_TYPE_WPA3_WPA2_MIXED:
|
||||
return WIFI_AUTH_WPA2_WPA3_PSK;
|
||||
}
|
||||
return WIFI_AUTH_INVALID;
|
||||
}
|
||||
10
arduino/beken-72xx/libraries/WiFi/WiFi.h
Normal file
10
arduino/beken-72xx/libraries/WiFi/WiFi.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-26. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/WiFi/WiFi.h>
|
||||
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiClientSecure.h"
|
||||
#include "WiFiServer.h"
|
||||
8
arduino/beken-72xx/libraries/WiFi/WiFiClient.h
Normal file
8
arduino/beken-72xx/libraries/WiFi/WiFiClient.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/WiFi/WiFi.h>
|
||||
#include <lwip/LwIPClient.h>
|
||||
|
||||
typedef LwIPClient WiFiClient;
|
||||
8
arduino/beken-72xx/libraries/WiFi/WiFiClientSecure.h
Normal file
8
arduino/beken-72xx/libraries/WiFi/WiFiClientSecure.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-04. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/WiFi/WiFi.h>
|
||||
#include <ssl/MbedTLSClient.h>
|
||||
|
||||
typedef MbedTLSClient WiFiClientSecure;
|
||||
23
arduino/beken-72xx/libraries/WiFi/WiFiData.h
Normal file
23
arduino/beken-72xx/libraries/WiFi/WiFiData.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-26. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
} // extern "C"
|
||||
|
||||
typedef struct {
|
||||
char ssid[32 + 1];
|
||||
char pass[64 + 1];
|
||||
unsigned long scannedAt;
|
||||
uint32_t ipSta[4];
|
||||
uint32_t ipAp[4];
|
||||
SemaphoreHandle_t scanSem;
|
||||
void *statusIp;
|
||||
void *statusLink;
|
||||
} WiFiData;
|
||||
71
arduino/beken-72xx/libraries/WiFi/WiFiGeneric.cpp
Normal file
71
arduino/beken-72xx/libraries/WiFi/WiFiGeneric.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-26. */
|
||||
|
||||
#include "WiFiPriv.h"
|
||||
|
||||
bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
|
||||
__wrap_bk_printf_disable();
|
||||
|
||||
if (mode && !data.statusIp) {
|
||||
data.statusIp = (IPStatusTypedef *)malloc(sizeof(IPStatusTypedef));
|
||||
data.statusLink = (LinkStatusTypeDef *)malloc(sizeof(LinkStatusTypeDef));
|
||||
}
|
||||
|
||||
if (!__bk_rf_is_init) {
|
||||
LT_D_WG("Initializing func&app");
|
||||
func_init_extended();
|
||||
app_pre_start();
|
||||
__bk_rf_is_init = true;
|
||||
}
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
if (sta == WLMODE_ENABLE) {
|
||||
LT_D_WG("Enabling STA");
|
||||
bk_wlan_sta_init(NULL);
|
||||
} else if (sta == WLMODE_DISABLE) {
|
||||
LT_D_WG("Disabling STA");
|
||||
bk_wlan_stop(BK_STATION);
|
||||
}
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
if (ap == WLMODE_ENABLE) {
|
||||
LT_D_WG("Enabling AP");
|
||||
bk_wlan_ap_init(NULL);
|
||||
} else if (ap == WLMODE_DISABLE) {
|
||||
LT_D_WG("Disabling AP");
|
||||
bk_wlan_stop(BK_SOFT_AP);
|
||||
}
|
||||
|
||||
if (!mode) {
|
||||
free(data.statusIp);
|
||||
free(data.statusLink);
|
||||
data.statusIp = NULL;
|
||||
data.statusLink = NULL;
|
||||
}
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
__wrap_bk_printf_enable();
|
||||
}
|
||||
|
||||
WiFiMode WiFiClass::getMode() {
|
||||
if (!g_wlan_general_param)
|
||||
return WIFI_MODE_NULL;
|
||||
uint8_t role = g_wlan_general_param->role;
|
||||
// change 1->2, 2->1
|
||||
return (WiFiMode)(role + (role == 1) - (role == 2));
|
||||
}
|
||||
|
||||
WiFiStatus WiFiClass::status() {
|
||||
return eventTypeToStatus(mhdr_get_station_status());
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::hostByName(const char *hostname) {
|
||||
ip_addr_t ip;
|
||||
int ret = netconn_gethostbyname(hostname, &ip);
|
||||
if (ret == ERR_OK) {
|
||||
return ip.addr;
|
||||
}
|
||||
return IPAddress();
|
||||
}
|
||||
57
arduino/beken-72xx/libraries/WiFi/WiFiPriv.h
Normal file
57
arduino/beken-72xx/libraries/WiFi/WiFiPriv.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-26. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/WiFi/WiFi.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include <lwip/api.h>
|
||||
#include <lwip/ip_addr.h>
|
||||
#include <lwip/netif.h>
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
#include <common.h>
|
||||
#include <config.h>
|
||||
#include <main_none.h>
|
||||
#include <param_config.h>
|
||||
#include <rw_msg_rx.h>
|
||||
#include <wlan_ui_pub.h>
|
||||
#include <wpa_supplicant_i.h>
|
||||
|
||||
extern void func_init_extended();
|
||||
extern void app_pre_start();
|
||||
extern void bk_wlan_ap_init(network_InitTypeDef_st *inNetworkInitPara);
|
||||
|
||||
// func/hostapd-2.5/wpa_supplicant/main_supplicant.c
|
||||
extern struct wpa_ssid_value *wpas_connect_ssid;
|
||||
|
||||
// func/lwip_intf/lwip-2.0.2/port/net.c
|
||||
extern struct netif *net_get_sta_handle(void);
|
||||
extern struct netif *net_get_uap_handle(void);
|
||||
|
||||
// app/param_config.c
|
||||
extern general_param_t *g_wlan_general_param;
|
||||
extern ap_param_t *g_ap_param_ptr;
|
||||
extern sta_param_t *g_sta_param_ptr;
|
||||
extern uint8_t system_mac[6];
|
||||
|
||||
// WiFi.cpp
|
||||
WiFiStatus eventTypeToStatus(uint8_t type);
|
||||
WiFiAuthMode securityTypeToAuthMode(uint8_t type);
|
||||
|
||||
#define ADDR_STA_IP data.ipSta[0]
|
||||
#define ADDR_STA_MASK data.ipSta[1]
|
||||
#define ADDR_STA_GW data.ipSta[2]
|
||||
#define ADDR_STA_DNS data.ipSta[3]
|
||||
#define ADDR_AP_IP data.ipAp[0]
|
||||
#define ADDR_AP_MASK data.ipAp[1]
|
||||
#define ADDR_AP_GW data.ipAp[2]
|
||||
#define ADDR_AP_DNS data.ipAp[3]
|
||||
|
||||
#define IP_STATUS ((IPStatusTypedef *)data.statusIp)
|
||||
#define LINK_STATUS ((LinkStatusTypeDef *)data.statusLink)
|
||||
|
||||
} // extern "C"
|
||||
219
arduino/beken-72xx/libraries/WiFi/WiFiSTA.cpp
Normal file
219
arduino/beken-72xx/libraries/WiFi/WiFiSTA.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
|
||||
|
||||
#include "WiFiPriv.h"
|
||||
|
||||
WiFiStatus
|
||||
WiFiClass::begin(const char *ssid, const char *passphrase, int32_t channel, const uint8_t *bssid, bool connect) {
|
||||
enableSTA(true);
|
||||
|
||||
if (!ssid || *ssid == 0x00 || strlen(ssid) > 32) {
|
||||
LT_W("SSID not specified or too long");
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
if (passphrase && strlen(passphrase) > 64) {
|
||||
LT_W("Passphrase too long");
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
// store the network data for later
|
||||
strcpy(data.ssid, ssid);
|
||||
if (passphrase)
|
||||
strcpy(data.pass, passphrase);
|
||||
else
|
||||
data.pass[0] = 0;
|
||||
|
||||
if (reconnect(bssid))
|
||||
return WL_CONNECTED;
|
||||
|
||||
return WL_CONNECT_FAILED;
|
||||
}
|
||||
|
||||
bool WiFiClass::config(IPAddress localIP, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2) {
|
||||
ADDR_STA_IP = (uint32_t)localIP;
|
||||
ADDR_STA_GW = (uint32_t)gateway;
|
||||
ADDR_STA_MASK = (uint32_t)subnet;
|
||||
ADDR_STA_DNS = (uint32_t)dns1;
|
||||
|
||||
if (status() == WL_CONNECTED) {
|
||||
IPStatusTypedef config;
|
||||
config.dhcp = !localIP[0];
|
||||
if (localIP) {
|
||||
sprintf(config.ip, "%u.%u.%u.%u", ADDR_STA_IP);
|
||||
sprintf(config.mask, "%u.%u.%u.%u", ADDR_STA_MASK);
|
||||
sprintf(config.gate, "%u.%u.%u.%u", ADDR_STA_GW);
|
||||
}
|
||||
if (dns1)
|
||||
sprintf(config.dns, "%u.%u.%u.%u", ADDR_STA_DNS);
|
||||
bk_wlan_set_ip_status(&config, BK_STATION);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::reconnect(const uint8_t *bssid) {
|
||||
if (!bssid && !data.ssid[0]) {
|
||||
LT_E("(B)SSID not specified");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bssid) {
|
||||
LT_D_WG("Connecting to " MACSTR, MAC2STR(bssid));
|
||||
} else {
|
||||
LT_D_WG("Connecting to %s", data.ssid);
|
||||
}
|
||||
|
||||
network_InitTypeDef_st config;
|
||||
memset(&config, 0, sizeof(network_InitTypeDef_st));
|
||||
// network_InitTypeDef_adv_st config;
|
||||
// memset(&config, 0, sizeof(network_InitTypeDef_adv_st));
|
||||
|
||||
config.wifi_mode = BK_STATION;
|
||||
config.wifi_retry_interval = 100;
|
||||
// config.ap_info.security = BK_SECURITY_TYPE_WPA2_MIXED;
|
||||
// config.ap_info.channel = 6;
|
||||
strcpy(config.wifi_ssid, data.ssid);
|
||||
// strcpy(config.ap_info.ssid, data.ssid);
|
||||
strcpy(config.wifi_key, data.pass);
|
||||
// strcpy(config.key, data.pass);
|
||||
// config.key_len = strlen(data.pass);
|
||||
if (bssid)
|
||||
memcpy(config.wifi_bssid, bssid, 6);
|
||||
// memcpy(config.ap_info.bssid, bssid, 6);
|
||||
|
||||
if (ADDR_STA_IP && ADDR_STA_MASK && ADDR_STA_GW) {
|
||||
config.dhcp_mode = DHCP_DISABLE;
|
||||
sprintf(config.local_ip_addr, "%u.%u.%u.%u", ADDR_STA_IP);
|
||||
sprintf(config.net_mask, "%u.%u.%u.%u", ADDR_STA_MASK);
|
||||
sprintf(config.gateway_ip_addr, "%u.%u.%u.%u", ADDR_STA_GW);
|
||||
LT_D_WG("Static IP: %s / %s / %s", config.local_ip_addr, config.net_mask, config.gateway_ip_addr);
|
||||
} else {
|
||||
config.dhcp_mode = DHCP_CLIENT;
|
||||
LT_D_WG("Using DHCP");
|
||||
}
|
||||
|
||||
if (ADDR_STA_DNS) {
|
||||
sprintf(config.dns_server_ip_addr, "%u.%u.%u.%u", ADDR_STA_DNS);
|
||||
LT_D_WG("Static DNS: %s", config.dns_server_ip_addr);
|
||||
}
|
||||
|
||||
if (!data.scannedAt || millis() - data.scannedAt > 10000) {
|
||||
LT_D_WG("Scan needed");
|
||||
// apparently a scan must be performed first,
|
||||
// else it hangs at "[sa_sta]MM_START_REQ"
|
||||
scanNetworks(false);
|
||||
}
|
||||
|
||||
LT_D_WG("Starting WiFi...");
|
||||
__wrap_bk_printf_disable();
|
||||
bk_wlan_start_sta(&config);
|
||||
__wrap_bk_printf_enable();
|
||||
LT_D_WG("bk_wlan_start() OK");
|
||||
return true;
|
||||
|
||||
error:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WiFiClass::disconnect(bool wifiOff) {
|
||||
bk_wlan_connection_loss();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::setAutoReconnect(bool autoReconnect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WiFiClass::getAutoReconnect() {
|
||||
return false;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::localIP() {
|
||||
IPStatusTypedef config;
|
||||
bk_wlan_get_ip_status(&config, BK_STATION);
|
||||
IPAddress ip;
|
||||
ip.fromString(config.ip);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::subnetMask() {
|
||||
IPStatusTypedef config;
|
||||
bk_wlan_get_ip_status(&config, BK_STATION);
|
||||
IPAddress ip;
|
||||
ip.fromString(config.mask);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::gatewayIP() {
|
||||
IPStatusTypedef config;
|
||||
bk_wlan_get_ip_status(&config, BK_STATION);
|
||||
IPAddress ip;
|
||||
ip.fromString(config.gate);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::dnsIP(uint8_t dns_no) {
|
||||
IPStatusTypedef config;
|
||||
bk_wlan_get_ip_status(&config, BK_STATION);
|
||||
IPAddress ip;
|
||||
ip.fromString(config.dns);
|
||||
return ip;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::broadcastIP() {
|
||||
return calculateBroadcast(localIP(), subnetMask());
|
||||
}
|
||||
|
||||
const char *WiFiClass::getHostname() {
|
||||
struct netif *ifs = net_get_sta_handle();
|
||||
return netif_get_hostname(ifs);
|
||||
}
|
||||
|
||||
bool WiFiClass::setHostname(const char *hostname) {
|
||||
struct netif *ifs = net_get_sta_handle();
|
||||
netif_set_hostname(ifs, (char *)hostname);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t *WiFiClass::macAddress(uint8_t *mac) {
|
||||
wifi_get_mac_address((char *)mac, CONFIG_ROLE_STA);
|
||||
return mac;
|
||||
}
|
||||
|
||||
bool WiFiClass::setMacAddress(const uint8_t *mac) {
|
||||
wifi_set_mac_address((char *)mac);
|
||||
return true;
|
||||
}
|
||||
|
||||
const String WiFiClass::SSID() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
return (char *)LINK_STATUS->ssid;
|
||||
}
|
||||
|
||||
const String WiFiClass::psk() {
|
||||
if (!isConnected())
|
||||
return "";
|
||||
struct wpa_supplicant *wpas = wpa_suppliant_ctrl_get_wpas();
|
||||
if (!wpas || !wpas->conf || !wpas->conf->ssid)
|
||||
return "";
|
||||
return (char *)wpas->conf->ssid->passphrase;
|
||||
}
|
||||
|
||||
uint8_t *WiFiClass::BSSID() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
return LINK_STATUS->bssid;
|
||||
}
|
||||
|
||||
int32_t WiFiClass::channel() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
return LINK_STATUS->channel;
|
||||
}
|
||||
|
||||
int8_t WiFiClass::RSSI() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
return LINK_STATUS->wifi_strength;
|
||||
}
|
||||
|
||||
WiFiAuthMode WiFiClass::getEncryption() {
|
||||
bk_wlan_get_link_status(LINK_STATUS);
|
||||
return securityTypeToAuthMode(LINK_STATUS->security);
|
||||
}
|
||||
73
arduino/beken-72xx/libraries/WiFi/WiFiScan.cpp
Normal file
73
arduino/beken-72xx/libraries/WiFi/WiFiScan.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
|
||||
|
||||
#include "WiFiPriv.h"
|
||||
|
||||
static void scanHandler(void *ctx, uint8_t param) {
|
||||
LT_HEAP_I();
|
||||
WiFiClass *cls = (WiFiClass *)ctx;
|
||||
if (!cls) {
|
||||
LT_W("Called without ctx");
|
||||
return;
|
||||
}
|
||||
WiFiScanData *scan = cls->scan;
|
||||
if (!scan) {
|
||||
LT_W("Called without cls->scan");
|
||||
return;
|
||||
}
|
||||
|
||||
ScanResult_adv result;
|
||||
if (wlan_sta_scan_result(&result)) {
|
||||
LT_E("Failed to get scan result");
|
||||
goto end;
|
||||
}
|
||||
LT_D_WG("Found %d APs", result.ApNum);
|
||||
|
||||
cls->scanAlloc(result.ApNum);
|
||||
if (!scan->ap) {
|
||||
LT_W("scan->ap alloc failed");
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < result.ApNum; i++) {
|
||||
scan->ap[i].ssid = strdup(result.ApList[i].ssid);
|
||||
scan->ap[i].auth = securityTypeToAuthMode(result.ApList[i].security);
|
||||
scan->ap[i].rssi = result.ApList[i].ApPower;
|
||||
scan->ap[i].channel = result.ApList[i].channel;
|
||||
memcpy(scan->ap[i].bssid.addr, result.ApList[i].bssid, 6);
|
||||
}
|
||||
|
||||
cls->data.scannedAt = millis();
|
||||
|
||||
end:
|
||||
scan->running = false;
|
||||
xSemaphoreGive(cls->data.scanSem);
|
||||
LT_HEAP_I();
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t WiFiClass::scanNetworks(bool async, bool showHidden, bool passive, uint32_t maxMsPerChannel, uint8_t channel) {
|
||||
if (scan && scan->running)
|
||||
return WIFI_SCAN_RUNNING;
|
||||
enableSTA(true);
|
||||
scanDelete();
|
||||
scanInit();
|
||||
|
||||
LT_I("Starting WiFi scan");
|
||||
|
||||
__wrap_bk_printf_disable();
|
||||
mhdr_scanu_reg_cb(scanHandler, this);
|
||||
bk_wlan_start_scan();
|
||||
__wrap_bk_printf_enable();
|
||||
|
||||
LT_HEAP_I();
|
||||
|
||||
scan->running = true;
|
||||
|
||||
if (!async) {
|
||||
LT_I("Waiting for results");
|
||||
xSemaphoreTake(data.scanSem, 1); // reset the semaphore quickly
|
||||
xSemaphoreTake(data.scanSem, pdMS_TO_TICKS(maxMsPerChannel * 20));
|
||||
return scan->count;
|
||||
}
|
||||
return WIFI_SCAN_RUNNING;
|
||||
}
|
||||
8
arduino/beken-72xx/libraries/WiFi/WiFiServer.h
Normal file
8
arduino/beken-72xx/libraries/WiFi/WiFiServer.h
Normal file
@@ -0,0 +1,8 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/WiFi/WiFi.h>
|
||||
#include <lwip/LwIPServer.h>
|
||||
|
||||
typedef LwIPServer WiFiServer;
|
||||
45
arduino/beken-72xx/port/flashdb/fal_flash_bk72xx_port.c
Normal file
45
arduino/beken-72xx/port/flashdb/fal_flash_bk72xx_port.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <sdk_extern.h>
|
||||
|
||||
#include <fal.h>
|
||||
#include <flash_pub.h>
|
||||
|
||||
#define FLASH_ERASE_MIN_SIZE (4 * 1024)
|
||||
|
||||
extern uint32_t flash_ctrl(uint32_t cmd, void *param);
|
||||
|
||||
static int init() {
|
||||
__wrap_bk_printf_disable();
|
||||
flash_init();
|
||||
__wrap_bk_printf_enable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read(long offset, uint8_t *buf, size_t size) {
|
||||
flash_read((char *)buf, size, offset);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int write(long offset, const uint8_t *buf, size_t size) {
|
||||
flash_write((char *)buf, size, offset);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int erase(long offset, size_t size) {
|
||||
size = ((size - 1) / FLASH_ERASE_MIN_SIZE) + 1;
|
||||
for (uint16_t i = 0; i < size; i++) {
|
||||
uint32_t addr = offset + i * FLASH_ERASE_MIN_SIZE;
|
||||
flash_ctrl(CMD_FLASH_ERASE_SECTOR, &addr);
|
||||
}
|
||||
return size * FLASH_ERASE_MIN_SIZE;
|
||||
}
|
||||
|
||||
const struct fal_flash_dev flash0 = {
|
||||
.name = FAL_FLASH_DEV_NAME,
|
||||
.addr = 0x0,
|
||||
.len = FLASH_LENGTH,
|
||||
.blk_size = FLASH_ERASE_MIN_SIZE,
|
||||
.ops = {init, read, write, erase},
|
||||
.write_gran = 1,
|
||||
};
|
||||
17
arduino/beken-72xx/port/printf/printf.c
Normal file
17
arduino/beken-72xx/port/printf/printf.c
Normal file
@@ -0,0 +1,17 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <printf_config.h>
|
||||
|
||||
#include <printf/printf.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
extern void bk_send_byte(uint8_t uport, uint8_t data);
|
||||
extern int uart_print_port;
|
||||
|
||||
void putchar_(char c) {
|
||||
bk_send_byte(uart_print_port, c);
|
||||
}
|
||||
|
||||
WRAP_PRINTF(bk_printf);
|
||||
7
arduino/beken-72xx/port/printf/printf_port.h
Normal file
7
arduino/beken-72xx/port/printf/printf_port.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <printf_config.h>
|
||||
|
||||
WRAP_DISABLE_DEF(bk_printf);
|
||||
@@ -1,2 +0,0 @@
|
||||
realtek-ambz Realtek AmebaZ Arduino Core
|
||||
libretuya Interfaces for LibreTuya Arduino cores
|
||||
5
arduino/libretuya/api/Events.cpp
Normal file
5
arduino/libretuya/api/Events.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-17. */
|
||||
|
||||
#include "Events.h"
|
||||
|
||||
uint16_t EventHandler_s::lastId = 1;
|
||||
117
arduino/libretuya/api/Events.h
Normal file
117
arduino/libretuya/api/Events.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
ESP8266WiFiGeneric.h - esp8266 Wifi support.
|
||||
Based on WiFi.h from Ardiono WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/WiFi/WiFiEvents.h>
|
||||
#include <functional>
|
||||
|
||||
typedef enum {
|
||||
ARDUINO_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
|
||||
ARDUINO_EVENT_WIFI_SCAN_DONE, /**< ESP32 finish scanning AP */
|
||||
ARDUINO_EVENT_WIFI_STA_START, /**< ESP32 station start */
|
||||
ARDUINO_EVENT_WIFI_STA_STOP, /**< ESP32 station stop */
|
||||
ARDUINO_EVENT_WIFI_STA_CONNECTED, /**< ESP32 station connected to AP */
|
||||
ARDUINO_EVENT_WIFI_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
|
||||
ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
|
||||
ARDUINO_EVENT_WIFI_STA_GOT_IP,
|
||||
ARDUINO_EVENT_WIFI_STA_GOT_IP6,
|
||||
ARDUINO_EVENT_WIFI_STA_LOST_IP,
|
||||
ARDUINO_EVENT_WIFI_AP_START, /**< ESP32 soft-AP start */
|
||||
ARDUINO_EVENT_WIFI_AP_STOP, /**< ESP32 soft-AP stop */
|
||||
ARDUINO_EVENT_WIFI_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
|
||||
ARDUINO_EVENT_WIFI_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
|
||||
ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED,
|
||||
ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
|
||||
ARDUINO_EVENT_WIFI_AP_GOT_IP6,
|
||||
ARDUINO_EVENT_WIFI_FTM_REPORT, /**< Receive report of FTM procedure */
|
||||
ARDUINO_EVENT_ETH_START,
|
||||
ARDUINO_EVENT_ETH_STOP,
|
||||
ARDUINO_EVENT_ETH_CONNECTED,
|
||||
ARDUINO_EVENT_ETH_DISCONNECTED,
|
||||
ARDUINO_EVENT_ETH_GOT_IP,
|
||||
ARDUINO_EVENT_ETH_GOT_IP6,
|
||||
ARDUINO_EVENT_WPS_ER_SUCCESS, /**< ESP32 station wps succeeds in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_FAILED, /**< ESP32 station wps fails in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_TIMEOUT, /**< ESP32 station wps timeout in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_PIN, /**< ESP32 station wps pin code in enrollee mode */
|
||||
ARDUINO_EVENT_WPS_ER_PBC_OVERLAP, /**< ESP32 station wps overlap in enrollee mode */
|
||||
ARDUINO_EVENT_SC_SCAN_DONE,
|
||||
ARDUINO_EVENT_SC_FOUND_CHANNEL,
|
||||
ARDUINO_EVENT_SC_GOT_SSID_PSWD,
|
||||
ARDUINO_EVENT_SC_SEND_ACK_DONE,
|
||||
ARDUINO_EVENT_PROV_INIT,
|
||||
ARDUINO_EVENT_PROV_DEINIT,
|
||||
ARDUINO_EVENT_PROV_START,
|
||||
ARDUINO_EVENT_PROV_END,
|
||||
ARDUINO_EVENT_PROV_CRED_RECV,
|
||||
ARDUINO_EVENT_PROV_CRED_FAIL,
|
||||
ARDUINO_EVENT_PROV_CRED_SUCCESS,
|
||||
ARDUINO_EVENT_MAX
|
||||
} arduino_event_id_t;
|
||||
|
||||
typedef union {
|
||||
wifi_event_sta_scan_done_t wifi_scan_done;
|
||||
wifi_event_sta_authmode_change_t wifi_sta_authmode_change;
|
||||
wifi_event_sta_connected_t wifi_sta_connected;
|
||||
wifi_event_sta_disconnected_t wifi_sta_disconnected;
|
||||
wifi_event_sta_wps_er_pin_t wps_er_pin;
|
||||
wifi_event_sta_wps_fail_reason_t wps_fail_reason;
|
||||
wifi_event_ap_probe_req_rx_t wifi_ap_probereqrecved;
|
||||
wifi_event_ap_staconnected_t wifi_ap_staconnected;
|
||||
wifi_event_ap_stadisconnected_t wifi_ap_stadisconnected;
|
||||
wifi_event_ftm_report_t wifi_ftm_report;
|
||||
ip_event_ap_staipassigned_t wifi_ap_staipassigned;
|
||||
ip_event_got_ip_t got_ip;
|
||||
ip_event_got_ip6_t got_ip6;
|
||||
// smartconfig_event_got_ssid_pswd_t sc_got_ssid_pswd;
|
||||
// esp_eth_handle_t eth_connected;
|
||||
// wifi_sta_config_t prov_cred_recv;
|
||||
// wifi_prov_sta_fail_reason_t prov_fail_reason;
|
||||
} arduino_event_info_t;
|
||||
|
||||
typedef struct {
|
||||
arduino_event_id_t event_id;
|
||||
arduino_event_info_t event_info;
|
||||
} arduino_event_t;
|
||||
|
||||
#define EventId arduino_event_id_t
|
||||
#define EventId_t arduino_event_id_t
|
||||
#define EventInfo arduino_event_info_t
|
||||
#define EventInfo_t arduino_event_info_t
|
||||
#define Event_t arduino_event_t
|
||||
|
||||
typedef void (*EventCb)(EventId event);
|
||||
typedef std::function<void(EventId event, EventInfo info)> EventFuncCb;
|
||||
typedef void (*EventSysCb)(Event_t *event);
|
||||
|
||||
typedef struct EventHandler_s {
|
||||
static uint16_t lastId;
|
||||
uint16_t id;
|
||||
EventCb cb;
|
||||
EventFuncCb fcb;
|
||||
EventSysCb scb;
|
||||
EventId eventId;
|
||||
|
||||
EventHandler_s() : id(lastId++), cb(NULL), fcb(NULL), scb(NULL) {}
|
||||
} EventHandler;
|
||||
228
arduino/libretuya/api/FS.cpp
Normal file
228
arduino/libretuya/api/FS.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
FS.cpp - file system wrapper
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "FS.h"
|
||||
|
||||
using namespace fs;
|
||||
|
||||
size_t File::write(uint8_t c) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return _p->write(&c, 1);
|
||||
}
|
||||
|
||||
time_t File::getLastWrite() {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return _p->getLastWrite();
|
||||
}
|
||||
|
||||
size_t File::write(const uint8_t *buf, size_t size) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return _p->write(buf, size);
|
||||
}
|
||||
|
||||
int File::available() {
|
||||
if (!*this) {
|
||||
return false;
|
||||
}
|
||||
return _p->size() - _p->position();
|
||||
}
|
||||
|
||||
int File::read() {
|
||||
if (!*this) {
|
||||
return -1;
|
||||
}
|
||||
uint8_t result;
|
||||
if (_p->read(&result, 1) != 1) {
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t File::read(uint8_t *buf, size_t size) {
|
||||
if (!*this) {
|
||||
return -1;
|
||||
}
|
||||
return _p->read(buf, size);
|
||||
}
|
||||
|
||||
int File::peek() {
|
||||
if (!*this) {
|
||||
return -1;
|
||||
}
|
||||
size_t curPos = _p->position();
|
||||
int result = read();
|
||||
seek(curPos, SeekSet);
|
||||
return result;
|
||||
}
|
||||
|
||||
void File::flush() {
|
||||
if (!*this) {
|
||||
return;
|
||||
}
|
||||
_p->flush();
|
||||
}
|
||||
|
||||
bool File::seek(uint32_t pos, SeekMode mode) {
|
||||
if (!*this) {
|
||||
return false;
|
||||
}
|
||||
return _p->seek(pos, mode);
|
||||
}
|
||||
|
||||
size_t File::position() const {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return _p->position();
|
||||
}
|
||||
|
||||
size_t File::size() const {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return _p->size();
|
||||
}
|
||||
|
||||
bool File::setBufferSize(size_t size) {
|
||||
if (!*this) {
|
||||
return 0;
|
||||
}
|
||||
return _p->setBufferSize(size);
|
||||
}
|
||||
|
||||
void File::close() {
|
||||
if (_p) {
|
||||
_p->close();
|
||||
_p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
File::operator bool() const {
|
||||
return _p != nullptr && *_p != false;
|
||||
}
|
||||
|
||||
const char *File::path() const {
|
||||
if (!*this) {
|
||||
return nullptr;
|
||||
}
|
||||
return _p->path();
|
||||
}
|
||||
|
||||
const char *File::name() const {
|
||||
if (!*this) {
|
||||
return nullptr;
|
||||
}
|
||||
return _p->name();
|
||||
}
|
||||
|
||||
// to implement
|
||||
boolean File::isDirectory(void) {
|
||||
if (!*this) {
|
||||
return false;
|
||||
}
|
||||
return _p->isDirectory();
|
||||
}
|
||||
|
||||
File File::openNextFile(const char *mode) {
|
||||
if (!*this) {
|
||||
return File();
|
||||
}
|
||||
return _p->openNextFile(mode);
|
||||
}
|
||||
|
||||
void File::rewindDirectory(void) {
|
||||
if (!*this) {
|
||||
return;
|
||||
}
|
||||
_p->rewindDirectory();
|
||||
}
|
||||
|
||||
File FS::open(const String &path, const char *mode, const bool create) {
|
||||
return open(path.c_str(), mode, create);
|
||||
}
|
||||
|
||||
File FS::open(const char *path, const char *mode, const bool create) {
|
||||
if (!_impl) {
|
||||
return File();
|
||||
}
|
||||
|
||||
return File(_impl->open(path, mode, create));
|
||||
}
|
||||
|
||||
bool FS::exists(const char *path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->exists(path);
|
||||
}
|
||||
|
||||
bool FS::exists(const String &path) {
|
||||
return exists(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::remove(const char *path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->remove(path);
|
||||
}
|
||||
|
||||
bool FS::remove(const String &path) {
|
||||
return remove(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::rename(const char *pathFrom, const char *pathTo) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->rename(pathFrom, pathTo);
|
||||
}
|
||||
|
||||
bool FS::rename(const String &pathFrom, const String &pathTo) {
|
||||
return rename(pathFrom.c_str(), pathTo.c_str());
|
||||
}
|
||||
|
||||
bool FS::mkdir(const char *path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->mkdir(path);
|
||||
}
|
||||
|
||||
bool FS::mkdir(const String &path) {
|
||||
return mkdir(path.c_str());
|
||||
}
|
||||
|
||||
bool FS::rmdir(const char *path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->rmdir(path);
|
||||
}
|
||||
|
||||
bool FS::rmdir(const String &path) {
|
||||
return rmdir(path.c_str());
|
||||
}
|
||||
152
arduino/libretuya/api/FS.h
Normal file
152
arduino/libretuya/api/FS.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
FS.h - file system wrapper
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <memory>
|
||||
|
||||
namespace fs {
|
||||
|
||||
#define FILE_READ "r"
|
||||
#define FILE_WRITE "w"
|
||||
#define FILE_APPEND "a"
|
||||
|
||||
class File;
|
||||
|
||||
class FileImpl;
|
||||
typedef std::shared_ptr<FileImpl> FileImplPtr;
|
||||
class FSImpl;
|
||||
typedef std::shared_ptr<FSImpl> FSImplPtr;
|
||||
|
||||
enum SeekMode { SeekSet = 0, SeekCur = 1, SeekEnd = 2 };
|
||||
|
||||
class File : public Stream {
|
||||
public:
|
||||
File(FileImplPtr p = FileImplPtr()) : _p(p) {
|
||||
_timeout = 0;
|
||||
}
|
||||
|
||||
size_t write(uint8_t) override;
|
||||
size_t write(const uint8_t *buf, size_t size) override;
|
||||
int available() override;
|
||||
int read() override;
|
||||
int peek() override;
|
||||
void flush() override;
|
||||
size_t read(uint8_t *buf, size_t size);
|
||||
|
||||
size_t readBytes(char *buffer, size_t length) {
|
||||
return read((uint8_t *)buffer, length);
|
||||
}
|
||||
|
||||
bool seek(uint32_t pos, SeekMode mode);
|
||||
|
||||
bool seek(uint32_t pos) {
|
||||
return seek(pos, SeekSet);
|
||||
}
|
||||
|
||||
size_t position() const;
|
||||
size_t size() const;
|
||||
bool setBufferSize(size_t size);
|
||||
void close();
|
||||
operator bool() const;
|
||||
time_t getLastWrite();
|
||||
const char *path() const;
|
||||
const char *name() const;
|
||||
|
||||
boolean isDirectory(void);
|
||||
File openNextFile(const char *mode = FILE_READ);
|
||||
void rewindDirectory(void);
|
||||
|
||||
protected:
|
||||
FileImplPtr _p;
|
||||
};
|
||||
|
||||
class FileImpl {
|
||||
public:
|
||||
virtual ~FileImpl() {}
|
||||
|
||||
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
||||
virtual size_t read(uint8_t *buf, size_t size) = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual bool seek(uint32_t pos, SeekMode mode) = 0;
|
||||
virtual size_t position() const = 0;
|
||||
virtual size_t size() const = 0;
|
||||
virtual bool setBufferSize(size_t size) = 0;
|
||||
virtual void close() = 0;
|
||||
virtual time_t getLastWrite() = 0;
|
||||
virtual const char *path() const = 0;
|
||||
virtual const char *name() const = 0;
|
||||
virtual boolean isDirectory(void) = 0;
|
||||
virtual FileImplPtr openNextFile(const char *mode) = 0;
|
||||
virtual void rewindDirectory(void) = 0;
|
||||
virtual operator bool() = 0;
|
||||
};
|
||||
|
||||
class FS {
|
||||
public:
|
||||
FS(FSImplPtr impl) : _impl(impl) {}
|
||||
|
||||
File open(const char *path, const char *mode = FILE_READ, const bool create = false);
|
||||
File open(const String &path, const char *mode = FILE_READ, const bool create = false);
|
||||
|
||||
bool exists(const char *path);
|
||||
bool exists(const String &path);
|
||||
|
||||
bool remove(const char *path);
|
||||
bool remove(const String &path);
|
||||
|
||||
bool rename(const char *pathFrom, const char *pathTo);
|
||||
bool rename(const String &pathFrom, const String &pathTo);
|
||||
|
||||
bool mkdir(const char *path);
|
||||
bool mkdir(const String &path);
|
||||
|
||||
bool rmdir(const char *path);
|
||||
bool rmdir(const String &path);
|
||||
|
||||
protected:
|
||||
FSImplPtr _impl;
|
||||
};
|
||||
|
||||
class FSImpl {
|
||||
public:
|
||||
FSImpl() {}
|
||||
|
||||
virtual ~FSImpl() {}
|
||||
|
||||
virtual FileImplPtr open(const char *path, const char *mode, const bool create) = 0;
|
||||
virtual bool exists(const char *path) = 0;
|
||||
virtual bool rename(const char *pathFrom, const char *pathTo) = 0;
|
||||
virtual bool remove(const char *path) = 0;
|
||||
virtual bool mkdir(const char *path) = 0;
|
||||
virtual bool rmdir(const char *path) = 0;
|
||||
};
|
||||
|
||||
} // namespace fs
|
||||
|
||||
#ifndef FS_NO_GLOBALS
|
||||
using fs::File;
|
||||
using fs::FS;
|
||||
using fs::SeekCur;
|
||||
using fs::SeekEnd;
|
||||
using fs::SeekMode;
|
||||
using fs::SeekSet;
|
||||
#endif // FS_NO_GLOBALS
|
||||
@@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t manufacturerId;
|
||||
uint8_t chipId;
|
||||
uint8_t chipSizeId;
|
||||
} FlashId;
|
||||
|
||||
class IFlashClass {
|
||||
public:
|
||||
IFlashClass() {}
|
||||
|
||||
~IFlashClass() {}
|
||||
|
||||
virtual FlashId getChipId() = 0;
|
||||
virtual uint32_t getSize() = 0;
|
||||
|
||||
virtual bool eraseSector(uint32_t sector) = 0;
|
||||
virtual bool readBlock(uint32_t offset, uint8_t *data, size_t size) = 0;
|
||||
virtual bool writeBlock(uint32_t offset, uint8_t *data, size_t size) = 0;
|
||||
};
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
IPv6Address.cpp - Base class that provides IPv6Address
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/Print.h>
|
||||
|
||||
#include "IPv6Address.h"
|
||||
|
||||
IPv6Address::IPv6Address()
|
||||
{
|
||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address(const uint32_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, (const uint8_t *)address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address& IPv6Address::operator=(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPv6Address::operator==(const uint8_t* addr) const
|
||||
{
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
}
|
||||
|
||||
size_t IPv6Address::printTo(Print& p) const
|
||||
{
|
||||
/* size_t n = 0;
|
||||
for(int i = 0; i < 16; i+=2) {
|
||||
if(i){
|
||||
n += p.print(':');
|
||||
}
|
||||
n += p.printf("%02x", _address.bytes[i]);
|
||||
n += p.printf("%02x", _address.bytes[i+1]);
|
||||
|
||||
}
|
||||
return n; */
|
||||
}
|
||||
|
||||
String IPv6Address::toString() const
|
||||
{
|
||||
char szRet[40];
|
||||
sprintf(szRet,"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
_address.bytes[0], _address.bytes[1], _address.bytes[2], _address.bytes[3],
|
||||
_address.bytes[4], _address.bytes[5], _address.bytes[6], _address.bytes[7],
|
||||
_address.bytes[8], _address.bytes[9], _address.bytes[10], _address.bytes[11],
|
||||
_address.bytes[12], _address.bytes[13], _address.bytes[14], _address.bytes[15]);
|
||||
return String(szRet);
|
||||
}
|
||||
|
||||
bool IPv6Address::fromString(const char *address)
|
||||
{
|
||||
//format 0011:2233:4455:6677:8899:aabb:ccdd:eeff
|
||||
if(strlen(address) != 39){
|
||||
return false;
|
||||
}
|
||||
char * pos = (char *)address;
|
||||
size_t i = 0;
|
||||
for(i = 0; i < 16; i+=2) {
|
||||
if(!sscanf(pos, "%2hhx", &_address.bytes[i]) || !sscanf(pos+2, "%2hhx", &_address.bytes[i+1])){
|
||||
return false;
|
||||
}
|
||||
pos += 5;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
IPv6Address.h - Base class that provides IPv6Address
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <api/String.h>
|
||||
#include <api/Print.h>
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class IPv6Address: public Printable
|
||||
{
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[16]; // IPv4 address
|
||||
uint32_t dword[4];
|
||||
} _address;
|
||||
|
||||
// Access the raw byte array containing the address. Because this returns a pointer
|
||||
// to the internal structure rather than a copy of the address this function should only
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address()
|
||||
{
|
||||
return _address.bytes;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPv6Address();
|
||||
IPv6Address(const uint8_t *address);
|
||||
IPv6Address(const uint32_t *address);
|
||||
virtual ~IPv6Address() {}
|
||||
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
operator const uint8_t*() const
|
||||
{
|
||||
return _address.bytes;
|
||||
}
|
||||
operator const uint32_t*() const
|
||||
{
|
||||
return _address.dword;
|
||||
}
|
||||
bool operator==(const IPv6Address& addr) const
|
||||
{
|
||||
return (_address.dword[0] == addr._address.dword[0])
|
||||
&& (_address.dword[1] == addr._address.dword[1])
|
||||
&& (_address.dword[2] == addr._address.dword[2])
|
||||
&& (_address.dword[3] == addr._address.dword[3]);
|
||||
}
|
||||
bool operator==(const uint8_t* addr) const;
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
uint8_t& operator[](int index)
|
||||
{
|
||||
return _address.bytes[index];
|
||||
}
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPv6Address objects from other types
|
||||
IPv6Address& operator=(const uint8_t *address);
|
||||
|
||||
// TODO implement printTo()
|
||||
virtual size_t printTo(Print& p) const;
|
||||
String toString() const;
|
||||
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using arduino::IPv6Address;
|
||||
@@ -17,7 +17,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "api/String.h"
|
||||
#include <api/String.h>
|
||||
|
||||
typedef enum {
|
||||
PT_I8,
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
WiFi.h - esp32 Wifi support.
|
||||
Based on WiFi.h from Arduino WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <api/IPAddress.h>
|
||||
#include <api/IPv6Address.h>
|
||||
#include <api/Print.h>
|
||||
|
||||
#include "WiFiType.h"
|
||||
|
||||
// TODO wifi events
|
||||
// TODO WiFiMulti library
|
||||
|
||||
class IWiFiClass {
|
||||
public:
|
||||
virtual void printDiag(Print &dest) = 0;
|
||||
};
|
||||
|
||||
class IWiFiGenericClass {
|
||||
public:
|
||||
virtual int32_t channel(void) = 0;
|
||||
virtual bool mode(WiFiMode mode) = 0;
|
||||
virtual WiFiMode getMode() = 0;
|
||||
virtual WiFiStatus status() = 0;
|
||||
|
||||
virtual bool enableSTA(bool enable) = 0;
|
||||
virtual bool enableAP(bool enable) = 0;
|
||||
|
||||
virtual bool setSleep(bool enable) = 0;
|
||||
virtual bool getSleep() = 0;
|
||||
|
||||
virtual bool setTxPower(int power) = 0;
|
||||
virtual int getTxPower() = 0;
|
||||
|
||||
virtual int hostByName(const char *hostname, IPAddress &aResult) {
|
||||
aResult = hostByName(hostname);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual IPAddress hostByName(const char *hostname) = 0;
|
||||
|
||||
static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet);
|
||||
static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet);
|
||||
static uint8_t calculateSubnetCIDR(IPAddress subnetMask);
|
||||
static String macToString(uint8_t *mac);
|
||||
};
|
||||
|
||||
class IWiFiSTAClass {
|
||||
public:
|
||||
virtual WiFiStatus begin(
|
||||
const char *ssid,
|
||||
const char *passphrase = NULL,
|
||||
int32_t channel = 0,
|
||||
const uint8_t *bssid = NULL,
|
||||
bool connect = true
|
||||
) = 0;
|
||||
virtual WiFiStatus begin(
|
||||
char *ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool connect = true
|
||||
) = 0;
|
||||
|
||||
virtual bool config(
|
||||
IPAddress localIP,
|
||||
IPAddress gateway,
|
||||
IPAddress subnet,
|
||||
IPAddress dns1 = (uint32_t)0x00000000,
|
||||
IPAddress dns2 = (uint32_t)0x00000000
|
||||
) = 0;
|
||||
|
||||
virtual bool reconnect() = 0;
|
||||
virtual bool disconnect(bool wifiOff = false) = 0;
|
||||
|
||||
virtual bool isConnected();
|
||||
|
||||
virtual bool setAutoReconnect(bool autoReconnect) = 0;
|
||||
virtual bool getAutoReconnect() = 0;
|
||||
|
||||
virtual WiFiStatus waitForConnectResult(unsigned long timeout) = 0;
|
||||
|
||||
virtual IPAddress localIP() = 0;
|
||||
virtual uint8_t *macAddress(uint8_t *mac) = 0;
|
||||
virtual String macAddress() = 0;
|
||||
virtual IPAddress subnetMask() = 0;
|
||||
virtual IPAddress gatewayIP() = 0;
|
||||
virtual IPAddress dnsIP(uint8_t dns_no = 0) = 0;
|
||||
virtual IPAddress broadcastIP() = 0;
|
||||
virtual IPAddress networkID() = 0;
|
||||
virtual uint8_t subnetCIDR() = 0;
|
||||
virtual bool enableIpV6() = 0;
|
||||
virtual IPv6Address localIPv6() = 0;
|
||||
virtual const char *getHostname() = 0;
|
||||
virtual bool setHostname(const char *hostname) = 0;
|
||||
virtual bool setMacAddress(const uint8_t *mac) = 0;
|
||||
|
||||
inline bool hostname(const String &aHostname) {
|
||||
return setHostname(aHostname.c_str());
|
||||
}
|
||||
|
||||
virtual const String SSID() = 0;
|
||||
virtual const String psk() = 0;
|
||||
virtual uint8_t *BSSID() = 0;
|
||||
virtual String BSSIDstr() = 0;
|
||||
virtual int8_t RSSI() = 0;
|
||||
virtual WiFiAuthMode getEncryption() = 0;
|
||||
};
|
||||
|
||||
class IWiFiScanClass {
|
||||
public:
|
||||
virtual int16_t scanNetworks(
|
||||
bool async = false,
|
||||
bool showHidden = false,
|
||||
bool passive = false,
|
||||
uint32_t maxMsPerChannel = 300,
|
||||
uint8_t channel = 0
|
||||
) = 0;
|
||||
virtual bool getNetworkInfo(
|
||||
uint8_t networkItem,
|
||||
String &ssid,
|
||||
WiFiAuthMode &encryptionType,
|
||||
int32_t &RSSI,
|
||||
uint8_t *&BSSID,
|
||||
int32_t &channel
|
||||
) = 0;
|
||||
|
||||
virtual int16_t scanComplete() = 0;
|
||||
virtual void scanDelete() = 0;
|
||||
|
||||
virtual String SSID(uint8_t networkItem) = 0;
|
||||
virtual WiFiAuthMode encryptionType(uint8_t networkItem) = 0;
|
||||
virtual int32_t RSSI(uint8_t networkItem) = 0;
|
||||
virtual uint8_t *BSSID(uint8_t networkItem) = 0;
|
||||
virtual String BSSIDstr(uint8_t networkItem) = 0;
|
||||
virtual int32_t channel(uint8_t networkItem) = 0;
|
||||
};
|
||||
|
||||
class IWiFiAPClass {
|
||||
public:
|
||||
virtual bool softAP(
|
||||
const char *ssid, const char *passphrase = NULL, int channel = 1, bool ssidHidden = false, int maxClients = 4
|
||||
) = 0;
|
||||
virtual bool softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet) = 0;
|
||||
virtual bool softAPdisconnect(bool wifiOff = false) = 0;
|
||||
|
||||
virtual uint8_t softAPgetStationNum() = 0;
|
||||
|
||||
virtual IPAddress softAPIP() = 0;
|
||||
virtual IPAddress softAPBroadcastIP() = 0;
|
||||
virtual IPAddress softAPNetworkID() = 0;
|
||||
virtual uint8_t softAPSubnetCIDR() = 0;
|
||||
virtual bool softAPenableIpV6() = 0;
|
||||
virtual IPv6Address softAPIPv6() = 0;
|
||||
virtual const char *softAPgetHostname() = 0;
|
||||
virtual bool softAPsetHostname(const char *hostname) = 0;
|
||||
virtual uint8_t *softAPmacAddress(uint8_t *mac) = 0;
|
||||
virtual String softAPmacAddress(void) = 0;
|
||||
virtual const String softAPSSID(void) = 0;
|
||||
};
|
||||
46
arduino/libretuya/api/WiFi/WiFi.cpp
Normal file
46
arduino/libretuya/api/WiFi/WiFi.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
void WiFiClass::printDiag(Print &dest) {
|
||||
const char *modes[] = {"NULL", "STA", "AP", "STA+AP"};
|
||||
const char *enc[] = {"Open", "WEP", "WPA PSK", "WPA2 PSK", "WPA/WPA2", "WPA", "WPA2"};
|
||||
|
||||
dest.print("Mode: ");
|
||||
dest.println(modes[getMode()]);
|
||||
|
||||
if (getMode() & WIFI_MODE_STA) {
|
||||
dest.println("-- Station --");
|
||||
dest.print("SSID: ");
|
||||
dest.println(SSID());
|
||||
if (isConnected()) {
|
||||
dest.print("BSSID: ");
|
||||
dest.println(BSSIDstr());
|
||||
dest.print("RSSI: ");
|
||||
dest.println(RSSI());
|
||||
dest.print("Encryption: ");
|
||||
dest.println(enc[getEncryption()]);
|
||||
dest.print("IP: ");
|
||||
dest.println(localIP());
|
||||
dest.print("MAC: ");
|
||||
dest.println(macAddress());
|
||||
dest.print("Hostname: ");
|
||||
dest.println(getHostname());
|
||||
}
|
||||
}
|
||||
|
||||
if (getMode() & WIFI_MODE_AP) {
|
||||
dest.println("-- Access Point --");
|
||||
dest.print("SSID: ");
|
||||
dest.println(softAPSSID());
|
||||
dest.print("IP: ");
|
||||
dest.println(softAPIP());
|
||||
dest.print("MAC: ");
|
||||
dest.println(softAPmacAddress());
|
||||
dest.print("Hostname: ");
|
||||
dest.println(softAPgetHostname());
|
||||
}
|
||||
}
|
||||
|
||||
WiFiClass WiFi;
|
||||
WiFiClass *pWiFi = NULL;
|
||||
194
arduino/libretuya/api/WiFi/WiFi.h
Normal file
194
arduino/libretuya/api/WiFi/WiFi.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
WiFi.h - esp32 Wifi support.
|
||||
Based on WiFi.h from Arduino WiFi shield library.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/Events.h>
|
||||
#include <api/IPAddress.h>
|
||||
#include <api/IPv6Address.h>
|
||||
#include <vector>
|
||||
|
||||
#include "WiFiType.h"
|
||||
|
||||
#ifdef LT_ARD_HAS_WIFI
|
||||
// family's data structure
|
||||
#include <WiFiData.h>
|
||||
#endif
|
||||
|
||||
class WiFiClass {
|
||||
public:
|
||||
#ifdef LT_ARD_HAS_WIFI
|
||||
// must be public for WiFiEvents & WiFiScan static handlers
|
||||
WiFiData data;
|
||||
#endif
|
||||
WiFiScanData *scan = NULL;
|
||||
|
||||
public: /* WiFi.cpp */
|
||||
WiFiClass();
|
||||
~WiFiClass();
|
||||
void printDiag(Print &dest);
|
||||
|
||||
public: /* WiFiGeneric.cpp */
|
||||
bool mode(WiFiMode mode);
|
||||
bool modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap);
|
||||
WiFiMode getMode();
|
||||
WiFiStatus status();
|
||||
|
||||
bool enableSTA(bool enable);
|
||||
bool enableAP(bool enable);
|
||||
|
||||
bool setSleep(bool enable);
|
||||
bool getSleep();
|
||||
|
||||
bool setTxPower(int power);
|
||||
int getTxPower();
|
||||
|
||||
int hostByName(const char *hostname, IPAddress &aResult);
|
||||
IPAddress hostByName(const char *hostname);
|
||||
|
||||
static IPAddress calculateNetworkID(IPAddress ip, IPAddress subnet);
|
||||
static IPAddress calculateBroadcast(IPAddress ip, IPAddress subnet);
|
||||
static uint8_t calculateSubnetCIDR(IPAddress subnetMask);
|
||||
static String macToString(uint8_t *mac);
|
||||
|
||||
protected: /* WiFiEvents.cpp */
|
||||
static std::vector<EventHandler> handlers;
|
||||
|
||||
public: /* WiFiEvents.cpp */
|
||||
uint16_t onEvent(EventCb callback, EventId eventId = ARDUINO_EVENT_MAX);
|
||||
uint16_t onEvent(EventFuncCb callback, EventId eventId = ARDUINO_EVENT_MAX);
|
||||
uint16_t onEvent(EventSysCb callback, EventId eventId = ARDUINO_EVENT_MAX);
|
||||
void removeEvent(EventCb callback, EventId eventId);
|
||||
void removeEvent(EventSysCb callback, EventId eventId);
|
||||
void removeEvent(uint16_t id);
|
||||
static void postEvent(EventId eventId, EventInfo eventInfo);
|
||||
|
||||
public: /* WiFiSTA.cpp */
|
||||
WiFiStatus begin(
|
||||
const char *ssid,
|
||||
const char *passphrase = NULL,
|
||||
int32_t channel = 0,
|
||||
const uint8_t *bssid = NULL,
|
||||
bool connect = true
|
||||
);
|
||||
WiFiStatus
|
||||
begin(char *ssid, char *passphrase = NULL, int32_t channel = 0, const uint8_t *bssid = NULL, bool connect = true);
|
||||
|
||||
bool config(
|
||||
IPAddress localIP,
|
||||
IPAddress gateway,
|
||||
IPAddress subnet,
|
||||
IPAddress dns1 = (uint32_t)0x00000000,
|
||||
IPAddress dns2 = (uint32_t)0x00000000
|
||||
);
|
||||
|
||||
bool reconnect(const uint8_t *bssid = NULL);
|
||||
bool disconnect(bool wifiOff = false);
|
||||
|
||||
bool isConnected();
|
||||
|
||||
bool setAutoReconnect(bool autoReconnect);
|
||||
bool getAutoReconnect();
|
||||
|
||||
WiFiStatus waitForConnectResult(unsigned long timeout);
|
||||
|
||||
IPAddress localIP();
|
||||
uint8_t *macAddress(uint8_t *mac);
|
||||
String macAddress();
|
||||
IPAddress subnetMask();
|
||||
IPAddress gatewayIP();
|
||||
IPAddress dnsIP(uint8_t dns_no = 0);
|
||||
IPAddress broadcastIP();
|
||||
IPAddress networkID();
|
||||
uint8_t subnetCIDR();
|
||||
bool enableIpV6();
|
||||
IPv6Address localIPv6();
|
||||
const char *getHostname();
|
||||
bool setHostname(const char *hostname);
|
||||
bool setMacAddress(const uint8_t *mac);
|
||||
|
||||
inline bool hostname(const String &aHostname) {
|
||||
return setHostname(aHostname.c_str());
|
||||
}
|
||||
|
||||
const String SSID();
|
||||
const String psk();
|
||||
uint8_t *BSSID();
|
||||
String BSSIDstr();
|
||||
int32_t channel();
|
||||
int8_t RSSI();
|
||||
WiFiAuthMode getEncryption();
|
||||
|
||||
public: /* WiFiScan.cpp */
|
||||
int16_t scanNetworks(
|
||||
bool async = false,
|
||||
bool showHidden = false,
|
||||
bool passive = false,
|
||||
uint32_t maxMsPerChannel = 300,
|
||||
uint8_t channel = 0
|
||||
);
|
||||
bool getNetworkInfo(
|
||||
uint8_t networkItem,
|
||||
String &ssid,
|
||||
WiFiAuthMode &encryptionType,
|
||||
int32_t &RSSI,
|
||||
uint8_t *&BSSID,
|
||||
int32_t &channel
|
||||
);
|
||||
|
||||
int16_t scanComplete();
|
||||
uint8_t scanAlloc(uint8_t count);
|
||||
void scanInit();
|
||||
void scanDelete();
|
||||
|
||||
String SSID(uint8_t networkItem);
|
||||
WiFiAuthMode encryptionType(uint8_t networkItem);
|
||||
int32_t RSSI(uint8_t networkItem);
|
||||
uint8_t *BSSID(uint8_t networkItem);
|
||||
String BSSIDstr(uint8_t networkItem);
|
||||
int32_t channel(uint8_t networkItem);
|
||||
|
||||
public: /* WiFiAP.cpp */
|
||||
bool softAP(
|
||||
const char *ssid, const char *passphrase = NULL, int channel = 1, bool ssidHidden = false, int maxClients = 4
|
||||
);
|
||||
bool softAPConfig(IPAddress localIP, IPAddress gateway, IPAddress subnet);
|
||||
bool softAPdisconnect(bool wifiOff = false);
|
||||
|
||||
uint8_t softAPgetStationNum();
|
||||
|
||||
IPAddress softAPIP();
|
||||
IPAddress softAPBroadcastIP();
|
||||
IPAddress softAPNetworkID();
|
||||
uint8_t softAPSubnetCIDR();
|
||||
IPAddress softAPSubnetMask();
|
||||
bool softAPenableIpV6();
|
||||
IPv6Address softAPIPv6();
|
||||
const char *softAPgetHostname();
|
||||
bool softAPsetHostname(const char *hostname);
|
||||
uint8_t *softAPmacAddress(uint8_t *mac);
|
||||
String softAPmacAddress(void);
|
||||
const String softAPSSID(void);
|
||||
};
|
||||
|
||||
extern WiFiClass WiFi;
|
||||
extern WiFiClass *pWiFi;
|
||||
23
arduino/libretuya/api/WiFi/WiFiAP.cpp
Normal file
23
arduino/libretuya/api/WiFi/WiFiAP.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
IPAddress WiFiClass::softAPBroadcastIP() {
|
||||
return calculateBroadcast(softAPIP(), softAPSubnetMask());
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::softAPNetworkID() {
|
||||
return calculateNetworkID(softAPIP(), softAPSubnetMask());
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::softAPSubnetCIDR() {
|
||||
return calculateSubnetCIDR(softAPSubnetMask());
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool WiFiClass::softAPenableIpV6() {
|
||||
return false;
|
||||
}
|
||||
|
||||
__attribute__((weak)) IPv6Address WiFiClass::softAPIPv6() {
|
||||
return IPv6Address();
|
||||
}
|
||||
84
arduino/libretuya/api/WiFi/WiFiEvents.cpp
Normal file
84
arduino/libretuya/api/WiFi/WiFiEvents.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-17. */
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
std::vector<EventHandler> WiFiClass::handlers;
|
||||
|
||||
uint16_t WiFiClass::onEvent(EventCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return 0;
|
||||
EventHandler handler;
|
||||
handler.cb = callback;
|
||||
handler.eventId = eventId;
|
||||
handlers.push_back(handler);
|
||||
return handler.id;
|
||||
}
|
||||
|
||||
uint16_t WiFiClass::onEvent(EventFuncCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return 0;
|
||||
EventHandler handler;
|
||||
handler.fcb = callback;
|
||||
handler.eventId = eventId;
|
||||
handlers.push_back(handler);
|
||||
return handler.id;
|
||||
}
|
||||
|
||||
uint16_t WiFiClass::onEvent(EventSysCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return 0;
|
||||
EventHandler handler;
|
||||
handler.scb = callback;
|
||||
handler.eventId = eventId;
|
||||
handlers.push_back(handler);
|
||||
return handler.id;
|
||||
}
|
||||
|
||||
void WiFiClass::removeEvent(EventCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return;
|
||||
for (uint16_t i = 0; i < handlers.size(); i++) {
|
||||
EventHandler handler = handlers[i];
|
||||
if (handler.cb == callback && handler.eventId == eventId) {
|
||||
handlers.erase(handlers.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiClass::removeEvent(EventSysCb callback, EventId eventId) {
|
||||
if (!callback)
|
||||
return;
|
||||
for (uint16_t i = 0; i < handlers.size(); i++) {
|
||||
EventHandler handler = handlers[i];
|
||||
if (handler.scb == callback && handler.eventId == eventId) {
|
||||
handlers.erase(handlers.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiClass::removeEvent(uint16_t id) {
|
||||
for (uint16_t i = 0; i < handlers.size(); i++) {
|
||||
EventHandler handler = handlers[i];
|
||||
if (handler.id == id) {
|
||||
handlers.erase(handlers.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WiFiClass::postEvent(EventId eventId, EventInfo eventInfo) {
|
||||
for (auto handler : handlers) {
|
||||
if (handler.eventId != ARDUINO_EVENT_MAX && handler.eventId != eventId)
|
||||
continue;
|
||||
if (handler.cb) {
|
||||
handler.cb(eventId);
|
||||
} else if (handler.fcb) {
|
||||
handler.fcb(eventId, eventInfo);
|
||||
} else if (handler.scb) {
|
||||
Event_t event = {
|
||||
.event_id = eventId,
|
||||
.event_info = eventInfo,
|
||||
};
|
||||
handler.scb(&event);
|
||||
}
|
||||
}
|
||||
}
|
||||
173
arduino/libretuya/api/WiFi/WiFiEvents.h
Normal file
173
arduino/libretuya/api/WiFi/WiFiEvents.h
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "WiFiType.h"
|
||||
|
||||
/** Argument structure for WIFI_EVENT_SCAN_DONE event */
|
||||
typedef struct {
|
||||
uint32_t status; /**< status of scanning APs: 0 - success, 1 - failure */
|
||||
uint8_t number; /**< number of scan results */
|
||||
uint8_t scan_id; /**< scan sequence number, used for block scan */
|
||||
} wifi_event_sta_scan_done_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_CONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t ssid[32]; /**< SSID of connected AP */
|
||||
uint8_t ssid_len; /**< SSID length of connected AP */
|
||||
uint8_t bssid[6]; /**< BSSID of connected AP*/
|
||||
uint8_t channel; /**< channel of connected AP*/
|
||||
wifi_auth_mode_t authmode; /**< authentication mode used by AP*/
|
||||
} wifi_event_sta_connected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_DISCONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t ssid[32]; /**< SSID of disconnected AP */
|
||||
uint8_t ssid_len; /**< SSID length of disconnected AP */
|
||||
uint8_t bssid[6]; /**< BSSID of disconnected AP */
|
||||
uint8_t reason; /**< reason of disconnection */
|
||||
} wifi_event_sta_disconnected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_AUTHMODE_CHANGE event */
|
||||
typedef struct {
|
||||
wifi_auth_mode_t old_mode; /**< the old auth mode of AP */
|
||||
wifi_auth_mode_t new_mode; /**< the new auth mode of AP */
|
||||
} wifi_event_sta_authmode_change_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_PIN event */
|
||||
typedef struct {
|
||||
uint8_t pin_code[8]; /**< PIN code of station in enrollee mode */
|
||||
} wifi_event_sta_wps_er_pin_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_FAILED event */
|
||||
typedef enum {
|
||||
WPS_FAIL_REASON_NORMAL = 0, /**< ESP32 WPS normal fail reason */
|
||||
WPS_FAIL_REASON_RECV_M2D, /**< ESP32 WPS receive M2D frame */
|
||||
WPS_FAIL_REASON_MAX
|
||||
} wifi_event_sta_wps_fail_reason_t;
|
||||
|
||||
#define MAX_SSID_LEN 32
|
||||
#define MAX_PASSPHRASE_LEN 64
|
||||
#define MAX_WPS_AP_CRED 3
|
||||
|
||||
/** Argument structure for WIFI_EVENT_STA_WPS_ER_SUCCESS event */
|
||||
typedef struct {
|
||||
uint8_t ap_cred_cnt; /**< Number of AP credentials received */
|
||||
|
||||
struct {
|
||||
uint8_t ssid[MAX_SSID_LEN]; /**< SSID of AP */
|
||||
uint8_t passphrase[MAX_PASSPHRASE_LEN]; /**< Passphrase for the AP */
|
||||
} ap_cred[MAX_WPS_AP_CRED]; /**< All AP credentials received from WPS handshake */
|
||||
} wifi_event_sta_wps_er_success_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_AP_STACONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t mac[6]; /**< MAC address of the station connected to ESP32 soft-AP */
|
||||
uint8_t aid; /**< the aid that ESP32 soft-AP gives to the station connected to */
|
||||
bool is_mesh_child; /**< flag to identify mesh child */
|
||||
} wifi_event_ap_staconnected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_AP_STADISCONNECTED event */
|
||||
typedef struct {
|
||||
uint8_t mac[6]; /**< MAC address of the station disconnects to ESP32 soft-AP */
|
||||
uint8_t aid; /**< the aid that ESP32 soft-AP gave to the station disconnects to */
|
||||
bool is_mesh_child; /**< flag to identify mesh child */
|
||||
} wifi_event_ap_stadisconnected_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_AP_PROBEREQRECVED event */
|
||||
typedef struct {
|
||||
int rssi; /**< Received probe request signal strength */
|
||||
uint8_t mac[6]; /**< MAC address of the station which send probe request */
|
||||
} wifi_event_ap_probe_req_rx_t;
|
||||
|
||||
/**
|
||||
* @brief FTM operation status types
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
FTM_STATUS_SUCCESS = 0, /**< FTM exchange is successful */
|
||||
FTM_STATUS_UNSUPPORTED, /**< Peer does not support FTM */
|
||||
FTM_STATUS_CONF_REJECTED, /**< Peer rejected FTM configuration in FTM Request */
|
||||
FTM_STATUS_NO_RESPONSE, /**< Peer did not respond to FTM Requests */
|
||||
FTM_STATUS_FAIL, /**< Unknown error during FTM exchange */
|
||||
} wifi_ftm_status_t;
|
||||
|
||||
/** Argument structure for */
|
||||
typedef struct {
|
||||
uint8_t dlog_token; /**< Dialog Token of the FTM frame */
|
||||
int8_t rssi; /**< RSSI of the FTM frame received */
|
||||
uint32_t rtt; /**< Round Trip Time in pSec with a peer */
|
||||
uint64_t t1; /**< Time of departure of FTM frame from FTM Responder in pSec */
|
||||
uint64_t t2; /**< Time of arrival of FTM frame at FTM Initiator in pSec */
|
||||
uint64_t t3; /**< Time of departure of ACK from FTM Initiator in pSec */
|
||||
uint64_t t4; /**< Time of arrival of ACK at FTM Responder in pSec */
|
||||
} wifi_ftm_report_entry_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_FTM_REPORT event */
|
||||
typedef struct {
|
||||
uint8_t peer_mac[6]; /**< MAC address of the FTM Peer */
|
||||
wifi_ftm_status_t status; /**< Status of the FTM operation */
|
||||
uint32_t rtt_raw; /**< Raw average Round-Trip-Time with peer in Nano-Seconds */
|
||||
uint32_t rtt_est; /**< Estimated Round-Trip-Time with peer in Nano-Seconds */
|
||||
uint32_t dist_est; /**< Estimated one-way distance in Centi-Meters */
|
||||
wifi_ftm_report_entry_t
|
||||
*ftm_report_data; /**< Pointer to FTM Report with multiple entries, should be freed after use */
|
||||
uint8_t ftm_report_num_entries; /**< Number of entries in the FTM Report data */
|
||||
} wifi_event_ftm_report_t;
|
||||
|
||||
#define WIFI_STATIS_BUFFER (1 << 0)
|
||||
#define WIFI_STATIS_RXTX (1 << 1)
|
||||
#define WIFI_STATIS_HW (1 << 2)
|
||||
#define WIFI_STATIS_DIAG (1 << 3)
|
||||
#define WIFI_STATIS_PS (1 << 4)
|
||||
#define WIFI_STATIS_ALL (-1)
|
||||
|
||||
/** Argument structure for WIFI_EVENT_ACTION_TX_STATUS event */
|
||||
typedef struct {
|
||||
int ifx; /**< WiFi interface to send request to */
|
||||
uint32_t context; /**< Context to identify the request */
|
||||
uint8_t da[6]; /**< Destination MAC address */
|
||||
uint8_t status; /**< Status of the operation */
|
||||
} wifi_event_action_tx_status_t;
|
||||
|
||||
/** Argument structure for WIFI_EVENT_ROC_DONE event */
|
||||
typedef struct {
|
||||
uint32_t context; /**< Context to identify the request */
|
||||
} wifi_event_roc_done_t;
|
||||
|
||||
/** Event structure for IP_EVENT_STA_GOT_IP, IP_EVENT_ETH_GOT_IP events */
|
||||
typedef struct {
|
||||
esp_ip4_addr_t ip; /**< Interface IPV4 address */
|
||||
esp_ip4_addr_t netmask; /**< Interface IPV4 netmask */
|
||||
esp_ip4_addr_t gw; /**< Interface IPV4 gateway address */
|
||||
} esp_netif_ip_info_t;
|
||||
|
||||
/** @brief IPV6 IP address information
|
||||
*/
|
||||
typedef struct {
|
||||
esp_ip6_addr_t ip; /**< Interface IPV6 address */
|
||||
} esp_netif_ip6_info_t;
|
||||
|
||||
typedef struct {
|
||||
int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */
|
||||
void *esp_netif; /*!< Pointer to corresponding esp-netif object */
|
||||
esp_netif_ip_info_t ip_info; /*!< IP address, netmask, gatway IP address */
|
||||
bool ip_changed; /*!< Whether the assigned IP has changed or not */
|
||||
} ip_event_got_ip_t;
|
||||
|
||||
/** Event structure for IP_EVENT_GOT_IP6 event */
|
||||
typedef struct {
|
||||
int if_index; /*!< Interface index for which the event is received (left for legacy compilation) */
|
||||
void *esp_netif; /*!< Pointer to corresponding esp-netif object */
|
||||
esp_netif_ip6_info_t ip6_info; /*!< IPv6 address of the interface */
|
||||
int ip_index; /*!< IPv6 address index */
|
||||
} ip_event_got_ip6_t;
|
||||
|
||||
/** Event structure for IP_EVENT_AP_STAIPASSIGNED event */
|
||||
typedef struct {
|
||||
esp_ip4_addr_t ip; /*!< IP address which was assigned to the station */
|
||||
} ip_event_ap_staipassigned_t;
|
||||
93
arduino/libretuya/api/WiFi/WiFiGeneric.cpp
Normal file
93
arduino/libretuya/api/WiFi/WiFiGeneric.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
bool WiFiClass::mode(WiFiMode mode) {
|
||||
// store a pointer to WiFi for WiFiEvents.cpp
|
||||
pWiFi = this;
|
||||
|
||||
WiFiMode currentMode = getMode();
|
||||
LT_D_WG("Mode changing %u -> %u", currentMode, mode);
|
||||
if (mode == currentMode)
|
||||
return true;
|
||||
|
||||
// get mode changes as 0/1
|
||||
WiFiModeAction sta = WiFiModeAction((mode & WIFI_MODE_STA) != (currentMode & WIFI_MODE_STA));
|
||||
WiFiModeAction ap = WiFiModeAction((mode & WIFI_MODE_AP) != (currentMode & WIFI_MODE_AP));
|
||||
// change 0/1 to 1/2
|
||||
sta = WiFiModeAction(sta + sta * (mode & WIFI_MODE_STA));
|
||||
ap = WiFiModeAction(ap + ap * (mode & WIFI_MODE_AP));
|
||||
// actually change the mode
|
||||
LT_HEAP_I();
|
||||
return modePriv(mode, sta, ap);
|
||||
}
|
||||
|
||||
bool WiFiClass::enableSTA(bool enable) {
|
||||
WiFiMode currentMode = getMode();
|
||||
if (((currentMode & WIFI_MODE_STA) != 0) != enable) {
|
||||
return mode((WiFiMode)(currentMode ^ WIFI_MODE_STA));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiFiClass::enableAP(bool enable) {
|
||||
WiFiMode currentMode = getMode();
|
||||
if (((currentMode & WIFI_MODE_AP) != 0) != enable) {
|
||||
return mode((WiFiMode)(currentMode ^ WIFI_MODE_AP));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int WiFiClass::hostByName(const char *hostname, IPAddress &aResult) {
|
||||
aResult = hostByName(hostname);
|
||||
return true;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::calculateNetworkID(IPAddress ip, IPAddress subnet) {
|
||||
IPAddress networkID;
|
||||
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
networkID[i] = subnet[i] & ip[i];
|
||||
|
||||
return networkID;
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::calculateBroadcast(IPAddress ip, IPAddress subnet) {
|
||||
IPAddress broadcastIp;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
broadcastIp[i] = ~subnet[i] | ip[i];
|
||||
|
||||
return broadcastIp;
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::calculateSubnetCIDR(IPAddress subnetMask) {
|
||||
uint8_t CIDR = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
if (subnetMask[i] == 0x80) // 128
|
||||
CIDR += 1;
|
||||
else if (subnetMask[i] == 0xC0) // 192
|
||||
CIDR += 2;
|
||||
else if (subnetMask[i] == 0xE0) // 224
|
||||
CIDR += 3;
|
||||
else if (subnetMask[i] == 0xF0) // 242
|
||||
CIDR += 4;
|
||||
else if (subnetMask[i] == 0xF8) // 248
|
||||
CIDR += 5;
|
||||
else if (subnetMask[i] == 0xFC) // 252
|
||||
CIDR += 6;
|
||||
else if (subnetMask[i] == 0xFE) // 254
|
||||
CIDR += 7;
|
||||
else if (subnetMask[i] == 0xFF) // 255
|
||||
CIDR += 8;
|
||||
}
|
||||
|
||||
return CIDR;
|
||||
}
|
||||
|
||||
String WiFiClass::macToString(uint8_t *mac) {
|
||||
char macStr[18]; // 6*2 + 5*':' + '\0'
|
||||
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
return macStr;
|
||||
}
|
||||
48
arduino/libretuya/api/WiFi/WiFiSTA.cpp
Normal file
48
arduino/libretuya/api/WiFi/WiFiSTA.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
WiFiStatus WiFiClass::begin(char *ssid, char *passphrase, int32_t channel, const uint8_t *bssid, bool connect) {
|
||||
return begin((const char *)ssid, (const char *)passphrase, channel, bssid, connect);
|
||||
}
|
||||
|
||||
bool WiFiClass::isConnected() {
|
||||
return status() == WL_CONNECTED;
|
||||
}
|
||||
|
||||
WiFiStatus WiFiClass::waitForConnectResult(unsigned long timeout) {
|
||||
if ((getMode() & WIFI_MODE_STA) == 0) {
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
unsigned long start = millis();
|
||||
while ((!status() || status() >= WL_DISCONNECTED) && (millis() - start) < timeout) {
|
||||
delay(100);
|
||||
}
|
||||
return status();
|
||||
}
|
||||
|
||||
String WiFiClass::macAddress(void) {
|
||||
uint8_t mac[6];
|
||||
macAddress(mac);
|
||||
return macToString(mac);
|
||||
}
|
||||
|
||||
IPAddress WiFiClass::networkID() {
|
||||
return calculateNetworkID(gatewayIP(), subnetMask());
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::subnetCIDR() {
|
||||
return calculateSubnetCIDR(subnetMask());
|
||||
}
|
||||
|
||||
String WiFiClass::BSSIDstr() {
|
||||
return macToString(BSSID());
|
||||
}
|
||||
|
||||
__attribute__((weak)) bool WiFiClass::enableIpV6() {
|
||||
return false;
|
||||
}
|
||||
|
||||
__attribute__((weak)) IPv6Address WiFiClass::localIPv6() {
|
||||
return IPv6Address();
|
||||
}
|
||||
83
arduino/libretuya/api/WiFi/WiFiScan.cpp
Normal file
83
arduino/libretuya/api/WiFi/WiFiScan.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
|
||||
|
||||
#include "WiFi.h"
|
||||
|
||||
bool WiFiClass::getNetworkInfo(
|
||||
uint8_t networkItem, String &ssid, WiFiAuthMode &encType, int32_t &rssi, uint8_t *&bssid, int32_t &channel
|
||||
) {
|
||||
ssid = SSID(networkItem);
|
||||
encType = encryptionType(networkItem);
|
||||
rssi = RSSI(networkItem);
|
||||
bssid = BSSID(networkItem);
|
||||
channel = this->channel(networkItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
int16_t WiFiClass::scanComplete() {
|
||||
if (!scan)
|
||||
return 0;
|
||||
if (scan->running)
|
||||
return WIFI_SCAN_RUNNING;
|
||||
return scan->count;
|
||||
}
|
||||
|
||||
void WiFiClass::scanInit() {
|
||||
if (scan)
|
||||
return;
|
||||
scan = (WiFiScanData *)zalloc(sizeof(WiFiScanData));
|
||||
}
|
||||
|
||||
void WiFiClass::scanDelete() {
|
||||
if (!scan)
|
||||
return;
|
||||
for (uint8_t i = 0; i < scan->count; i++) {
|
||||
free(scan->ap[i].ssid);
|
||||
}
|
||||
free(scan->ap);
|
||||
free(scan);
|
||||
scan = NULL;
|
||||
}
|
||||
|
||||
uint8_t WiFiClass::scanAlloc(uint8_t count) {
|
||||
uint8_t last = scan->count;
|
||||
scan->count = count;
|
||||
scan->ap = (WiFiScanAP *)realloc(scan->ap, count * sizeof(WiFiScanAP));
|
||||
if (!scan->ap)
|
||||
return 255;
|
||||
memset(scan->ap + last, 0, sizeof(WiFiScanAP));
|
||||
return last;
|
||||
}
|
||||
|
||||
String WiFiClass::SSID(uint8_t networkItem) {
|
||||
if (!scan || networkItem >= scan->count)
|
||||
return "";
|
||||
return scan->ap[networkItem].ssid;
|
||||
}
|
||||
|
||||
WiFiAuthMode WiFiClass::encryptionType(uint8_t networkItem) {
|
||||
if (!scan || networkItem >= scan->count)
|
||||
return WIFI_AUTH_INVALID;
|
||||
return scan->ap[networkItem].auth;
|
||||
}
|
||||
|
||||
int32_t WiFiClass::RSSI(uint8_t networkItem) {
|
||||
if (!scan || networkItem >= scan->count)
|
||||
return 0;
|
||||
return scan->ap[networkItem].rssi;
|
||||
}
|
||||
|
||||
uint8_t *WiFiClass::BSSID(uint8_t networkItem) {
|
||||
if (!scan || networkItem >= scan->count)
|
||||
return NULL;
|
||||
return scan->ap[networkItem].bssid.addr;
|
||||
}
|
||||
|
||||
String WiFiClass::BSSIDstr(uint8_t networkItem) {
|
||||
return macToString(BSSID(networkItem));
|
||||
}
|
||||
|
||||
int32_t WiFiClass::channel(uint8_t networkItem) {
|
||||
if (!scan || networkItem >= scan->count)
|
||||
return 0;
|
||||
return scan->ap[networkItem].channel;
|
||||
}
|
||||
149
arduino/libretuya/api/WiFi/WiFiType.h
Normal file
149
arduino/libretuya/api/WiFi/WiFiType.h
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
ESP8266WiFiType.h - esp8266 Wifi support.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define WIFI_SCAN_RUNNING (-1)
|
||||
#define WIFI_SCAN_FAILED (-2)
|
||||
|
||||
#define WiFiMode_t wifi_mode_t
|
||||
#define WiFiMode wifi_mode_t
|
||||
#define WiFiStatus wl_status_t
|
||||
#define WiFiAuthMode wifi_auth_mode_t
|
||||
|
||||
#define WIFI_OFF WIFI_MODE_NULL
|
||||
#define WIFI_STA WIFI_MODE_STA
|
||||
#define WIFI_AP WIFI_MODE_AP
|
||||
#define WIFI_AP_STA WIFI_MODE_APSTA
|
||||
|
||||
#define WiFiEvent_t arduino_event_id_t
|
||||
#define WiFiEventInfo_t arduino_event_info_t
|
||||
#define WiFiEventId_t uint16_t
|
||||
|
||||
typedef struct {
|
||||
uint8_t addr[6];
|
||||
} WiFiMacAddr;
|
||||
|
||||
struct esp_ip6_addr {
|
||||
uint32_t addr[4];
|
||||
uint8_t zone;
|
||||
};
|
||||
|
||||
struct esp_ip4_addr {
|
||||
uint32_t addr;
|
||||
};
|
||||
|
||||
typedef struct esp_ip4_addr esp_ip4_addr_t;
|
||||
typedef struct esp_ip6_addr esp_ip6_addr_t;
|
||||
|
||||
typedef enum {
|
||||
WIFI_MODE_NULL = 0, /**< null mode */
|
||||
WIFI_MODE_STA, /**< WiFi station mode */
|
||||
WIFI_MODE_AP, /**< WiFi soft-AP mode */
|
||||
WIFI_MODE_APSTA, /**< WiFi station + soft-AP mode */
|
||||
WIFI_MODE_MAX
|
||||
} wifi_mode_t;
|
||||
|
||||
typedef enum {
|
||||
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
|
||||
WL_IDLE_STATUS = 0,
|
||||
WL_NO_SSID_AVAIL = 1,
|
||||
WL_SCAN_COMPLETED = 2,
|
||||
WL_CONNECTED = 3,
|
||||
WL_CONNECT_FAILED = 4,
|
||||
WL_CONNECTION_LOST = 5,
|
||||
WL_DISCONNECTED = 6,
|
||||
} wl_status_t;
|
||||
|
||||
typedef enum {
|
||||
WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */
|
||||
WIFI_AUTH_WEP, /**< authenticate mode : WEP */
|
||||
WIFI_AUTH_WPA_PSK, /**< authenticate mode : WPA_PSK */
|
||||
WIFI_AUTH_WPA2_PSK, /**< authenticate mode : WPA2_PSK */
|
||||
WIFI_AUTH_WPA_WPA2_PSK, /**< authenticate mode : WPA_WPA2_PSK */
|
||||
WIFI_AUTH_WPA2_ENTERPRISE, /**< authenticate mode : WPA2_ENTERPRISE */
|
||||
WIFI_AUTH_WPA3_PSK, /**< authenticate mode : WPA3_PSK */
|
||||
WIFI_AUTH_WPA2_WPA3_PSK, /**< authenticate mode : WPA2_WPA3_PSK */
|
||||
WIFI_AUTH_WAPI_PSK, /**< authenticate mode : WAPI_PSK */
|
||||
WIFI_AUTH_WPA,
|
||||
WIFI_AUTH_WPA2,
|
||||
WIFI_AUTH_AUTO = 200,
|
||||
WIFI_AUTH_INVALID = 255,
|
||||
WIFI_AUTH_MAX
|
||||
} wifi_auth_mode_t;
|
||||
|
||||
typedef enum {
|
||||
WIFI_REASON_UNSPECIFIED = 1,
|
||||
WIFI_REASON_AUTH_EXPIRE = 2,
|
||||
WIFI_REASON_AUTH_LEAVE = 3,
|
||||
WIFI_REASON_ASSOC_EXPIRE = 4,
|
||||
WIFI_REASON_ASSOC_TOOMANY = 5,
|
||||
WIFI_REASON_NOT_AUTHED = 6,
|
||||
WIFI_REASON_NOT_ASSOCED = 7,
|
||||
WIFI_REASON_ASSOC_LEAVE = 8,
|
||||
WIFI_REASON_ASSOC_NOT_AUTHED = 9,
|
||||
WIFI_REASON_DISASSOC_PWRCAP_BAD = 10,
|
||||
WIFI_REASON_DISASSOC_SUPCHAN_BAD = 11,
|
||||
WIFI_REASON_BSS_TRANSITION_DISASSOC = 12,
|
||||
WIFI_REASON_IE_INVALID = 13,
|
||||
WIFI_REASON_MIC_FAILURE = 14,
|
||||
WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT = 15,
|
||||
WIFI_REASON_GROUP_KEY_UPDATE_TIMEOUT = 16,
|
||||
WIFI_REASON_IE_IN_4WAY_DIFFERS = 17,
|
||||
WIFI_REASON_GROUP_CIPHER_INVALID = 18,
|
||||
WIFI_REASON_PAIRWISE_CIPHER_INVALID = 19,
|
||||
WIFI_REASON_AKMP_INVALID = 20,
|
||||
WIFI_REASON_UNSUPP_RSN_IE_VERSION = 21,
|
||||
WIFI_REASON_INVALID_RSN_IE_CAP = 22,
|
||||
WIFI_REASON_802_1X_AUTH_FAILED = 23,
|
||||
WIFI_REASON_CIPHER_SUITE_REJECTED = 24,
|
||||
WIFI_REASON_INVALID_PMKID = 53,
|
||||
WIFI_REASON_BEACON_TIMEOUT = 200,
|
||||
WIFI_REASON_NO_AP_FOUND = 201,
|
||||
WIFI_REASON_AUTH_FAIL = 202,
|
||||
WIFI_REASON_ASSOC_FAIL = 203,
|
||||
WIFI_REASON_HANDSHAKE_TIMEOUT = 204,
|
||||
WIFI_REASON_CONNECTION_FAIL = 205,
|
||||
WIFI_REASON_AP_TSF_RESET = 206,
|
||||
WIFI_REASON_ROAMING = 207,
|
||||
} wifi_err_reason_t;
|
||||
|
||||
typedef struct {
|
||||
char *ssid;
|
||||
WiFiAuthMode auth;
|
||||
int32_t rssi;
|
||||
WiFiMacAddr bssid;
|
||||
int32_t channel;
|
||||
} WiFiScanAP;
|
||||
|
||||
typedef struct {
|
||||
bool running = false;
|
||||
uint8_t count = 0;
|
||||
WiFiScanAP *ap = NULL;
|
||||
} WiFiScanData;
|
||||
|
||||
typedef enum {
|
||||
WLMODE_NONE = 0,
|
||||
WLMODE_DISABLE = 1,
|
||||
WLMODE_ENABLE = 2,
|
||||
} WiFiModeAction;
|
||||
@@ -35,12 +35,15 @@ class IWiFiClient : public Client {
|
||||
|
||||
virtual size_t write(Stream &stream) = 0;
|
||||
|
||||
size_t write_P(PGM_P buffer, size_t size) {
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
virtual int fd() const = 0;
|
||||
virtual int socket() = 0;
|
||||
virtual int setTimeout(uint32_t seconds) = 0;
|
||||
|
||||
virtual IWiFiClient &operator=(const IWiFiClient &other) = 0;
|
||||
virtual bool operator==(const IWiFiClient &other) const = 0;
|
||||
bool operator==(const IWiFiClient &other) const;
|
||||
|
||||
operator bool() {
|
||||
return connected();
|
||||
|
||||
@@ -22,42 +22,28 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "WiFi.h"
|
||||
#include "WiFiClient.h"
|
||||
|
||||
class IWiFiClientSecure : public IWiFiClient {
|
||||
class IWiFiClientSecure {
|
||||
public:
|
||||
int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey);
|
||||
int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey);
|
||||
virtual int
|
||||
connect(IPAddress ip, uint16_t port, const char *rootCABuf, const char *clientCert, const char *clientKey) = 0;
|
||||
virtual int
|
||||
connect(const char *host, uint16_t port, const char *rootCABuf, const char *clientCert, const char *clientKey) = 0;
|
||||
virtual int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psk) = 0;
|
||||
virtual int connect(const char *host, uint16_t port, const char *pskIdent, const char *psk) = 0;
|
||||
|
||||
int lastError(char *buf, const size_t size);
|
||||
void setInsecure(); // Don't validate the chain, just accept whatever is given. VERY INSECURE!
|
||||
void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex
|
||||
void setCACert(const char *rootCA);
|
||||
void setCertificate(const char *client_ca);
|
||||
void setPrivateKey(const char *private_key);
|
||||
bool loadCACert(Stream &stream, size_t size);
|
||||
bool loadCertificate(Stream &stream, size_t size);
|
||||
bool loadPrivateKey(Stream &stream, size_t size);
|
||||
bool verify(const char *fingerprint, const char *domain_name);
|
||||
void setHandshakeTimeout(unsigned long handshake_timeout);
|
||||
|
||||
WiFiClientSecure &operator=(const WiFiClientSecure &other);
|
||||
|
||||
bool operator==(const bool value) {
|
||||
return bool() == value;
|
||||
}
|
||||
|
||||
bool operator!=(const bool value) {
|
||||
return bool() != value;
|
||||
}
|
||||
|
||||
bool operator==(const WiFiClientSecure &);
|
||||
|
||||
bool operator!=(const WiFiClientSecure &rhs) {
|
||||
return !this->operator==(rhs);
|
||||
};
|
||||
|
||||
using Print::write;
|
||||
virtual int lastError(char *buf, const size_t size) = 0;
|
||||
virtual void setInsecure() = 0; // Don't validate the chain, just accept whatever is given. VERY INSECURE!
|
||||
virtual void setPreSharedKey(const char *pskIdent, const char *psk) = 0; // psk in hex
|
||||
virtual void setCACert(const char *rootCA) = 0;
|
||||
virtual void setCertificate(const char *clientCA) = 0;
|
||||
virtual void setPrivateKey(const char *privateKey) = 0;
|
||||
virtual bool loadCACert(Stream &stream, size_t size) = 0;
|
||||
virtual bool loadCertificate(Stream &stream, size_t size) = 0;
|
||||
virtual bool loadPrivateKey(Stream &stream, size_t size) = 0;
|
||||
virtual bool verify(const char *fingerprint, const char *domainName) = 0;
|
||||
virtual void setHandshakeTimeout(unsigned long handshakeTimeout) = 0;
|
||||
virtual void setAlpnProtocols(const char **alpnProtocols) = 0;
|
||||
virtual bool getFingerprintSHA256(uint8_t result[32]) = 0;
|
||||
};
|
||||
|
||||
@@ -34,6 +34,8 @@ class IWiFiServer : public Print { // arduino::Server is useless anyway
|
||||
|
||||
IWiFiServer(uint16_t port = 80, uint8_t maxClients = 4) {}
|
||||
|
||||
IWiFiServer(const IPAddress &addr, uint16_t port = 80, uint8_t maxClients = 4) {}
|
||||
|
||||
~IWiFiServer() {
|
||||
stop();
|
||||
}
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
ESP8266WiFiType.h - esp8266 Wifi support.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
Modified by Ivan Grokhotkov, December 2014
|
||||
Reworked by Markus Sattler, December 2015
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define WIFI_SCAN_RUNNING (-1)
|
||||
#define WIFI_SCAN_FAILED (-2)
|
||||
|
||||
#define WiFiMode_t wifi_mode_t
|
||||
#define WiFiMode wifi_mode_t
|
||||
#define WiFiStatus wl_status_t
|
||||
#define WiFiAuthMode wifi_auth_mode_t
|
||||
|
||||
#define WIFI_OFF WIFI_MODE_NULL
|
||||
#define WIFI_STA WIFI_MODE_STA
|
||||
#define WIFI_AP WIFI_MODE_AP
|
||||
#define WIFI_AP_STA WIFI_MODE_APSTA
|
||||
|
||||
typedef enum {
|
||||
WIFI_MODE_NULL = 0,
|
||||
WIFI_MODE_STA,
|
||||
WIFI_MODE_AP,
|
||||
WIFI_MODE_APSTA,
|
||||
WIFI_MODE_MAX,
|
||||
} wifi_mode_t;
|
||||
|
||||
typedef enum {
|
||||
WL_NO_SHIELD = 255, // for compatibility with WiFi Shield library
|
||||
WL_IDLE_STATUS = 0,
|
||||
WL_NO_SSID_AVAIL = 1,
|
||||
WL_SCAN_COMPLETED = 2,
|
||||
WL_CONNECTED = 3,
|
||||
WL_CONNECT_FAILED = 4,
|
||||
WL_CONNECTION_LOST = 5,
|
||||
WL_DISCONNECTED = 6,
|
||||
} wl_status_t;
|
||||
|
||||
typedef enum {
|
||||
WIFI_AUTH_INVALID = 255,
|
||||
WIFI_AUTH_AUTO = 200,
|
||||
WIFI_AUTH_OPEN = 0,
|
||||
WIFI_AUTH_WEP = 1,
|
||||
WIFI_AUTH_WPA = 5,
|
||||
WIFI_AUTH_WPA2 = 6,
|
||||
WIFI_AUTH_WPA_PSK = 2,
|
||||
WIFI_AUTH_WPA2_PSK = 3,
|
||||
WIFI_AUTH_WPA_WPA2_PSK = 4,
|
||||
} wifi_auth_mode_t;
|
||||
66
arduino/libretuya/api/Wire.h
Normal file
66
arduino/libretuya/api/Wire.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-09. */
|
||||
|
||||
#include <api/Stream.h>
|
||||
|
||||
class ITwoWire : public Stream {
|
||||
protected:
|
||||
int8_t _sda = -1;
|
||||
int8_t _scl = -1;
|
||||
uint32_t _freq = 0;
|
||||
|
||||
void (*onRequestCallback)(void);
|
||||
void (*onReceiveCallback)(int);
|
||||
|
||||
public:
|
||||
bool begin() {
|
||||
return begin(_sda, _scl, _freq);
|
||||
}
|
||||
|
||||
bool begin(uint8_t address) {
|
||||
return begin(address, _sda, _scl, _freq);
|
||||
}
|
||||
|
||||
virtual bool setPins(int8_t sda, int8_t scl) = 0;
|
||||
|
||||
virtual bool begin(int8_t sda, int8_t scl, uint32_t frequency = 0) = 0;
|
||||
virtual bool begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency = 0) = 0;
|
||||
virtual bool end() = 0;
|
||||
|
||||
virtual bool setClock(uint32_t freq) = 0;
|
||||
|
||||
virtual void beginTransmission(uint8_t address) = 0;
|
||||
virtual uint8_t endTransmission(bool stopBit) = 0;
|
||||
|
||||
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
|
||||
|
||||
virtual size_t write(const uint8_t *data, size_t len) = 0;
|
||||
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
uint32_t getClock() {
|
||||
return _freq;
|
||||
}
|
||||
|
||||
uint8_t endTransmission() {
|
||||
return endTransmission(true);
|
||||
}
|
||||
|
||||
size_t requestFrom(uint8_t address, size_t len) {
|
||||
return requestFrom(address, len, true);
|
||||
}
|
||||
|
||||
virtual size_t write(uint8_t data) {
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
void onReceive(void (*cb)(int)) {
|
||||
onReceiveCallback = cb;
|
||||
}
|
||||
|
||||
void onRequest(void (*cb)(void)) {
|
||||
onRequestCallback = cb;
|
||||
}
|
||||
};
|
||||
@@ -1,89 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "LibreTuyaConfig.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#if LT_LOGGER_FILE
|
||||
#define LT_LOG(level, file, line, ...) lt_log(level, file, line, __VA_ARGS__)
|
||||
void lt_log(const uint8_t level, const char *filename, const unsigned short line, const char *format, ...);
|
||||
#else
|
||||
#define LT_LOG(level, file, line, ...) lt_log(level, __VA_ARGS__)
|
||||
void lt_log(const uint8_t level, const char *format, ...);
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_TRACE >= LT_LOGLEVEL
|
||||
#define LT_T(...) LT_LOG(LT_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LT_V(...) LT_LOG(LT_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_T(...)
|
||||
#define LT_V(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_DEBUG >= LT_LOGLEVEL
|
||||
#define LT_D(...) LT_LOG(LT_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_D(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_INFO >= LT_LOGLEVEL
|
||||
#define LT_I(...) LT_LOG(LT_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_I(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_WARN >= LT_LOGLEVEL
|
||||
#define LT_W(...) LT_LOG(LT_LEVEL_WARN, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_W(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_ERROR >= LT_LOGLEVEL
|
||||
#define LT_E(...) LT_LOG(LT_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_E(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_FATAL >= LT_LOGLEVEL
|
||||
#define LT_F(...) LT_LOG(LT_LEVEL_FATAL, __FILE__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_F(...)
|
||||
#endif
|
||||
|
||||
#define LT_T_MOD(module, ...) \
|
||||
do { \
|
||||
if (module) { \
|
||||
LT_T(__VA_ARGS__) \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LT_D_MOD(module, ...) \
|
||||
do { \
|
||||
if (module) { \
|
||||
LT_D(__VA_ARGS__) \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// WiFi.cpp
|
||||
#define LT_T_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
#define LT_V_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
#define LT_D_WG(...) LT_D_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
|
||||
// WiFiClient.cpp
|
||||
#define LT_T_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
#define LT_V_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
#define LT_D_WC(...) LT_D_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
|
||||
// WiFiServer.cpp
|
||||
#define LT_T_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
#define LT_V_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
#define LT_D_WS(...) LT_D_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
|
||||
// WiFiSTA.cpp
|
||||
#define LT_T_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
#define LT_V_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
#define LT_D_WSTA(...) LT_D_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
|
||||
// WiFiAP.cpp
|
||||
#define LT_T_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
#define LT_V_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
#define LT_D_WAP(...) LT_D_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
55
arduino/libretuya/common/WMath.cpp
Normal file
55
arduino/libretuya/common/WMath.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright (c) 2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void randomSeed(uint32_t dwSeed) {
|
||||
if (dwSeed != 0) {
|
||||
srand(dwSeed);
|
||||
}
|
||||
}
|
||||
|
||||
long random(long howbig) {
|
||||
if (howbig == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rand() % howbig;
|
||||
}
|
||||
|
||||
long random(long howsmall, long howbig) {
|
||||
if (howsmall >= howbig) {
|
||||
return howsmall;
|
||||
}
|
||||
|
||||
long diff = howbig - howsmall;
|
||||
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
|
||||
extern long map(long x, long in_min, long in_max, long out_min, long out_max) {
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
extern uint16_t makeWord(uint16_t w) {
|
||||
return w;
|
||||
}
|
||||
|
||||
extern uint16_t makeWord(uint8_t h, uint8_t l) {
|
||||
return (h << 8) | l;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2012 Arduino. All right reserved.
|
||||
Copyright (c) 2014 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -16,19 +16,21 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef RESET_H
|
||||
#define RESET_H
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern "C" void __cxa_pure_virtual(void) __attribute__((__noreturn__));
|
||||
extern "C" void __cxa_deleted_virtual(void) __attribute__((__noreturn__));
|
||||
|
||||
void initiateReset(int ms);
|
||||
void tickReset();
|
||||
void cancelReset();
|
||||
|
||||
#ifdef __cplusplus
|
||||
void __cxa_pure_virtual(void) {
|
||||
// We might want to write some diagnostics to uart in this case
|
||||
// std::terminate();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
void __cxa_deleted_virtual(void) {
|
||||
// We might want to write some diagnostics to uart in this case
|
||||
// std::terminate();
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
@@ -18,16 +18,11 @@
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_AMEBA
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
|
||||
char fmt[20];
|
||||
sprintf(fmt, "%%%d.%df", width, prec);
|
||||
sprintf(sout, fmt, val);
|
||||
return sout;
|
||||
char *dtostrf(double val, signed char width, unsigned char prec, char *sout) {
|
||||
char fmt[20];
|
||||
sprintf(fmt, "%%%d.%df", width, prec);
|
||||
sprintf(sout, fmt, val);
|
||||
return sout;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (c) 2012 Arduino. All right reserved.
|
||||
Copyright (c) 2015 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -29,12 +29,7 @@ static void __empty() {
|
||||
// Empty
|
||||
}
|
||||
|
||||
#include "cmsis_os.h"
|
||||
|
||||
void yield(void) {
|
||||
vTaskDelay(1);
|
||||
taskYIELD();
|
||||
}
|
||||
void yield(void) __attribute__((weak, alias("__empty")));
|
||||
|
||||
/**
|
||||
* SysTick hook
|
||||
@@ -46,7 +41,8 @@ static int __false() {
|
||||
// Return false
|
||||
return 0;
|
||||
}
|
||||
int sysTickHook(void) __attribute__ ((weak, alias("__false")));
|
||||
|
||||
int sysTickHook(void) __attribute__((weak, alias("__false")));
|
||||
|
||||
/**
|
||||
* SVC hook
|
||||
@@ -60,5 +56,6 @@ static void __halt() {
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
void svcHook(void) __attribute__ ((weak, alias("__halt")));
|
||||
void pendSVHook(void) __attribute__ ((weak, alias("__halt")));
|
||||
|
||||
void svcHook(void) __attribute__((weak, alias("__halt")));
|
||||
void pendSVHook(void) __attribute__((weak, alias("__halt")));
|
||||
111
arduino/libretuya/common/itoa.c
Normal file
111
arduino/libretuya/common/itoa.c
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright (c) 2014 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *ltoa(long value, char *string, int radix) {
|
||||
char tmp[33];
|
||||
char *tp = tmp;
|
||||
long i;
|
||||
unsigned long v;
|
||||
int sign;
|
||||
char *sp;
|
||||
|
||||
if (string == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (radix > 36 || radix <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
sign = (radix == 10 && value < 0);
|
||||
if (sign) {
|
||||
v = -value;
|
||||
} else {
|
||||
v = (unsigned long)value;
|
||||
}
|
||||
|
||||
while (v || tp == tmp) {
|
||||
i = v % radix;
|
||||
v = v / radix;
|
||||
if (i < 10)
|
||||
*tp++ = i + '0';
|
||||
else
|
||||
*tp++ = i + 'a' - 10;
|
||||
}
|
||||
|
||||
sp = string;
|
||||
|
||||
if (sign)
|
||||
*sp++ = '-';
|
||||
while (tp > tmp)
|
||||
*sp++ = *--tp;
|
||||
*sp = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char *ultoa(unsigned long value, char *string, int radix) {
|
||||
char tmp[33];
|
||||
char *tp = tmp;
|
||||
long i;
|
||||
unsigned long v = value;
|
||||
char *sp;
|
||||
|
||||
if (string == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (radix > 36 || radix <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (v || tp == tmp) {
|
||||
i = v % radix;
|
||||
v = v / radix;
|
||||
if (i < 10)
|
||||
*tp++ = i + '0';
|
||||
else
|
||||
*tp++ = i + 'a' - 10;
|
||||
}
|
||||
|
||||
sp = string;
|
||||
|
||||
while (tp > tmp)
|
||||
*sp++ = *--tp;
|
||||
*sp = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
char *itoa(int value, char *string, int radix) {
|
||||
return ltoa(value, string, radix);
|
||||
}
|
||||
|
||||
char *utoa(unsigned int value, char *string, int radix) {
|
||||
return ultoa(value, string, radix);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
53
arduino/libretuya/common/main.cpp
Normal file
53
arduino/libretuya/common/main.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/HardwareSerial.h>
|
||||
|
||||
using namespace arduino;
|
||||
|
||||
extern "C" {
|
||||
#include <fal.h>
|
||||
fal_partition_t fal_root_part = NULL;
|
||||
}
|
||||
|
||||
// Arduino framework initialization.
|
||||
// May be redefined by family files.
|
||||
void init() __attribute__((weak));
|
||||
|
||||
// Weak empty variant initialization function.
|
||||
// May be redefined by variant files.
|
||||
void initVariant() __attribute__((weak));
|
||||
|
||||
// Initialize C library
|
||||
extern "C" void __libc_init_array(void);
|
||||
|
||||
void main_task(const void *arg) {
|
||||
setup();
|
||||
|
||||
for (;;) {
|
||||
loop();
|
||||
if (serialEventRun)
|
||||
serialEventRun();
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
// print a startup banner
|
||||
LT_BANNER();
|
||||
// initialize Arduino framework
|
||||
init();
|
||||
// initialize C library
|
||||
__libc_init_array();
|
||||
// optionally initialize per-variant code
|
||||
initVariant();
|
||||
// initialize FAL
|
||||
fal_init();
|
||||
// provide root partition
|
||||
fal_root_part = (fal_partition_t)fal_partition_find("root");
|
||||
// start the main task and OS kernel
|
||||
startMainTask();
|
||||
|
||||
while (1) {}
|
||||
return 0;
|
||||
}
|
||||
11
arduino/libretuya/common/serial_event.cpp
Normal file
11
arduino/libretuya/common/serial_event.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
void serialEvent() __attribute__((weak));
|
||||
bool Serial_available() __attribute__((weak));
|
||||
|
||||
void serialEventRun(void) {
|
||||
if (Serial_available && serialEvent && Serial_available())
|
||||
serialEvent();
|
||||
}
|
||||
54
arduino/libretuya/common/wiring_shift.c
Normal file
54
arduino/libretuya/common/wiring_shift.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright (c) 2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t shiftIn(pin_size_t ulDataPin, pin_size_t ulClockPin, BitOrder ulBitOrder) {
|
||||
uint8_t value = 0;
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
digitalWrite(ulClockPin, HIGH);
|
||||
|
||||
if (ulBitOrder == LSBFIRST) {
|
||||
value |= digitalRead(ulDataPin) << i;
|
||||
} else {
|
||||
value |= digitalRead(ulDataPin) << (7 - i);
|
||||
}
|
||||
|
||||
digitalWrite(ulClockPin, LOW);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void shiftOut(pin_size_t ulDataPin, pin_size_t ulClockPin, BitOrder ulBitOrder, uint8_t ulVal) {
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (ulBitOrder == LSBFIRST) {
|
||||
digitalWrite(ulDataPin, !!(ulVal & (1 << i)));
|
||||
} else {
|
||||
digitalWrite(ulDataPin, !!(ulVal & (1 << (7 - i))));
|
||||
}
|
||||
|
||||
digitalWrite(ulClockPin, HIGH);
|
||||
digitalWrite(ulClockPin, LOW);
|
||||
}
|
||||
}
|
||||
5
arduino/libretuya/compat/FS.h
Normal file
5
arduino/libretuya/compat/FS.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-30. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/FS.h>
|
||||
3
arduino/libretuya/compat/FSImpl.h
Normal file
3
arduino/libretuya/compat/FSImpl.h
Normal file
@@ -0,0 +1,3 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-30. */
|
||||
|
||||
// nop
|
||||
@@ -1,3 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-26. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// ESP32 WiFi examples use WiFiAP.h include
|
||||
|
||||
6
arduino/libretuya/compat/md5.h
Normal file
6
arduino/libretuya/compat/md5.h
Normal file
@@ -0,0 +1,6 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-04. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// lowercase "md5.h" to allow including actual MD5.h on case-sensitive OSes
|
||||
#include <MD5.h>
|
||||
5
arduino/libretuya/compat/pgmspace.h
Normal file
5
arduino/libretuya/compat/pgmspace.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-30. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/deprecated-avr-comp/avr/pgmspace.h>
|
||||
3
arduino/libretuya/compat/vfs_api.h
Normal file
3
arduino/libretuya/compat/vfs_api.h
Normal file
@@ -0,0 +1,3 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-30. */
|
||||
|
||||
// nop
|
||||
29
arduino/libretuya/core/ChipType.h
Normal file
29
arduino/libretuya/core/ChipType.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
|
||||
|
||||
#define CHIP_TYPE(family, chip_id) (((family >> 24) << 8) | chip_id)
|
||||
#define CHIP_TYPE_ENUM(family, chip_id) (ChipType) CHIP_TYPE(family, chip_id)
|
||||
|
||||
enum ChipFamily {
|
||||
// used in UF2 Family ID
|
||||
F_RTL8710A = 0x9FFFD543, // Realtek Ameba1
|
||||
F_RTL8710B = 0x22E0D6FC, // Realtek AmebaZ (realtek-ambz)
|
||||
F_RTL8720C = 0xE08F7564, // Realtek AmebaZ2
|
||||
F_RTL8720D = 0x3379CFE2, // Realtek AmebaD
|
||||
F_BK7231T = 0x675A40B0, // Beken 7231T
|
||||
F_BK7231N = 0x7B3EF230, // Beken 7231N
|
||||
F_BL602 = 0xDE1270B7, // Boufallo 602
|
||||
F_XR809 = 0x51E903A8, // Xradiotech 809
|
||||
F_NATIVE = 0xDEADBEEF, // Host-native
|
||||
};
|
||||
|
||||
enum ChipType {
|
||||
// Realtek AmebaZ
|
||||
// IDs copied from rtl8710b_efuse.h
|
||||
RTL8710BL = CHIP_TYPE(F_RTL8710B, 0xE0), // ???
|
||||
RTL8710BN = CHIP_TYPE(F_RTL8710B, 0xFF), // CHIPID_8710BN / QFN32
|
||||
RTL8710BU = CHIP_TYPE(F_RTL8710B, 0xFE), // CHIPID_8710BU / QFN48
|
||||
RTL8710BX = CHIP_TYPE(F_RTL8710B, 0xF6), // found on an actual RTL8710BX
|
||||
RTL8710L0 = CHIP_TYPE(F_RTL8710B, 0xFB), // CHIPID_8710BN_L0 / QFN32
|
||||
RTL8711BN = CHIP_TYPE(F_RTL8710B, 0xFD), // CHIPID_8711BN / QFN48
|
||||
RTL8711BU = CHIP_TYPE(F_RTL8710B, 0xFC), // CHIPID_8711BG / QFN68
|
||||
};
|
||||
63
arduino/libretuya/core/LibreTuyaAPI.cpp
Normal file
63
arduino/libretuya/core/LibreTuyaAPI.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||
|
||||
#include "LibreTuyaAPI.h"
|
||||
|
||||
String ipToString(const IPAddress &ip) {
|
||||
char szRet[16];
|
||||
sprintf(szRet, "%hhu.%hhu.%hhu.%hhu", ip[0], ip[1], ip[2], ip[3]);
|
||||
return String(szRet);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate random bytes using rand().
|
||||
*
|
||||
* @param buf destination pointer
|
||||
* @param len how many bytes to generate
|
||||
*/
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len) {
|
||||
int *data = (int *)buf;
|
||||
size_t i;
|
||||
for (i = 0; len >= sizeof(int); len -= sizeof(int)) {
|
||||
data[i++] = rand();
|
||||
}
|
||||
if (len) {
|
||||
int rem = rand();
|
||||
unsigned char *pRem = (unsigned char *)&rem;
|
||||
memcpy(buf + i * sizeof(int), pRem, len);
|
||||
}
|
||||
}
|
||||
|
||||
#undef putchar
|
||||
|
||||
/**
|
||||
* @brief Print data pointed to by buf in hexdump-like format (hex+ASCII).
|
||||
*
|
||||
* @param buf source pointer
|
||||
* @param len how many bytes to print
|
||||
* @param offset increment printed offset by this value
|
||||
* @param width how many bytes on a line
|
||||
*/
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
|
||||
uint16_t pos = 0;
|
||||
while (pos < len) {
|
||||
// print hex offset
|
||||
printf("%06x ", offset + pos);
|
||||
// calculate current line width
|
||||
uint8_t lineWidth = min(width, len - pos);
|
||||
// print hexadecimal representation
|
||||
for (uint8_t i = 0; i < lineWidth; i++) {
|
||||
if (i % 8 == 0) {
|
||||
printf(" ");
|
||||
}
|
||||
printf("%02x ", buf[pos + i]);
|
||||
}
|
||||
// print ascii representation
|
||||
printf(" |");
|
||||
for (uint8_t i = 0; i < lineWidth; i++) {
|
||||
char c = buf[pos + i];
|
||||
putchar((c >= 0x20 && c <= 0x7f) ? c : '.');
|
||||
}
|
||||
puts("|\r");
|
||||
pos += lineWidth;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,57 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// C standard libraries
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// LibreTuya version macros
|
||||
#ifndef LT_VERSION
|
||||
#define LT_VERSION 1.0.0
|
||||
#endif
|
||||
|
||||
#ifndef LT_BOARD
|
||||
#define LT_BOARD unknown
|
||||
#endif
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
#define STRINGIFY_MACRO(x) STRINGIFY(x)
|
||||
#define LT_VERSION_STR STRINGIFY_MACRO(LT_VERSION)
|
||||
#define LT_BOARD_STR STRINGIFY_MACRO(LT_BOARD)
|
||||
|
||||
// Includes
|
||||
#include "LibreTuyaClass.h" // global LT class
|
||||
#include "LibreTuyaCompat.h" // compatibility methods
|
||||
#include "LibreTuyaConfig.h" // configuration macros
|
||||
#include "LibreTuyaCustom.h" // family-defined methods (Wiring custom)
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "LibreTuyaConfig.h"
|
||||
|
||||
// C includes
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "lt_logger.h"
|
||||
#include "lt_posix_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
// Functional macros
|
||||
#define LT_BANNER() \
|
||||
LT_LOG( \
|
||||
LT_LEVEL_INFO, \
|
||||
"main.cpp", \
|
||||
__FUNCTION__, \
|
||||
__LINE__, \
|
||||
"LibreTuya v" LT_VERSION_STR " on " LT_BOARD_STR ", compiled at " __DATE__ " " __TIME__ \
|
||||
)
|
||||
|
||||
void lt_rand_bytes(uint8_t *buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
String ipToString(const IPAddress &ip);
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset = 0, uint8_t width = 16);
|
||||
#else
|
||||
void hexdump(uint8_t *buf, size_t len, uint32_t offset, uint8_t width);
|
||||
#endif
|
||||
132
arduino/libretuya/core/LibreTuyaClass.cpp
Normal file
132
arduino/libretuya/core/LibreTuyaClass.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-06. */
|
||||
|
||||
#include "LibreTuyaClass.h"
|
||||
|
||||
/**
|
||||
* @brief Get LibreTuya version string.
|
||||
*/
|
||||
const char *LibreTuya::getVersion() {
|
||||
return LT_VERSION_STR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get board name.
|
||||
*/
|
||||
const char *LibreTuya::getBoard() {
|
||||
return LT_BOARD_STR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CPU family ID.
|
||||
*/
|
||||
ChipFamily LibreTuya::getChipFamily() {
|
||||
return FAMILY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CPU family name as string.
|
||||
*/
|
||||
const char *LibreTuya::getChipFamilyName() {
|
||||
return STRINGIFY_MACRO(FAMILY) + 2;
|
||||
}
|
||||
|
||||
static char *deviceName = NULL;
|
||||
|
||||
/**
|
||||
* @brief Get device friendly name in format "LT-<board>-<chip id>".
|
||||
* Can be used as hostname.
|
||||
*/
|
||||
const char *LibreTuya::getDeviceName() {
|
||||
if (deviceName)
|
||||
return deviceName;
|
||||
uint32_t chipId = getChipId();
|
||||
uint8_t *id = (uint8_t *)&chipId;
|
||||
|
||||
const char *board = getBoard();
|
||||
uint8_t boardLen = strlen(board);
|
||||
deviceName = (char *)malloc(3 + boardLen + 1 + 6 + 1);
|
||||
|
||||
sprintf(deviceName, "LT-%s-%02x%02x%02x", board, id[0], id[1], id[2]);
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get CPU frequency in MHz.
|
||||
*/
|
||||
uint32_t LibreTuya::getCpuFreqMHz() {
|
||||
return getCpuFreq() / 1000000;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get flash chip total size.
|
||||
* The default implementation uses the least significant
|
||||
* byte of the chip ID to determine the size.
|
||||
*/
|
||||
__attribute__((weak)) uint32_t LibreTuya::getFlashChipSize() {
|
||||
FlashId id = getFlashChipId();
|
||||
if (id.chipSizeId >= 0x14 && id.chipSizeId <= 0x19) {
|
||||
return (1 << id.chipSizeId);
|
||||
}
|
||||
#ifdef FLASH_LENGTH
|
||||
return FLASH_LENGTH;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t otaRunningIndex = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the currently running firmware OTA index.
|
||||
*/
|
||||
uint8_t LibreTuya::otaGetRunning() {
|
||||
if (otaRunningIndex)
|
||||
return otaRunningIndex;
|
||||
// otaRunningIndex will be correct even after switchOta()
|
||||
return otaRunningIndex = otaGetStoredIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the OTA index for updated firmware.
|
||||
*
|
||||
* Note: returns 1 for chips without dual-OTA.
|
||||
*/
|
||||
uint8_t LibreTuya::otaGetTarget() {
|
||||
if (!otaSupportsDual())
|
||||
return 1;
|
||||
return otaGetRunning() ^ 0b11;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform OTA rollback.
|
||||
*
|
||||
* @return false if no second image to run, writing failed or dual-OTA not supported
|
||||
*/
|
||||
bool LibreTuya::otaRollback() {
|
||||
if (!otaCanRollback())
|
||||
return false;
|
||||
if (otaGetRunning() != otaGetStoredIndex())
|
||||
// force switching back to current image
|
||||
return otaSwitch(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if OTA rollback is supported and available (there is another image to run).
|
||||
* @return false if no second image to run or dual-OTA not supported
|
||||
*/
|
||||
bool LibreTuya::otaCanRollback() {
|
||||
if (!otaSupportsDual())
|
||||
return false;
|
||||
if (otaGetRunning() == otaGetStoredIndex())
|
||||
return true;
|
||||
if (otaGetRunning() == 1 && otaHasImage1())
|
||||
return true;
|
||||
if (otaGetRunning() == 2 && otaHasImage2())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void LibreTuya::gpioRecover() {
|
||||
// nop by default
|
||||
}
|
||||
142
arduino/libretuya/core/LibreTuyaClass.h
Normal file
142
arduino/libretuya/core/LibreTuyaClass.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-06. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "LibreTuyaAPI.h"
|
||||
#include <core/ChipType.h>
|
||||
|
||||
/**
|
||||
* @brief Flash chip ID structure.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t manufacturerId;
|
||||
uint8_t chipId;
|
||||
uint8_t chipSizeId;
|
||||
} FlashId;
|
||||
|
||||
/**
|
||||
* @brief Main LibreTuya API class.
|
||||
*
|
||||
* This class contains all functions common amongst all families.
|
||||
* Implementations of these methods may vary between families.
|
||||
*
|
||||
* The class is accessible using the `LT` global object (defined by the family).
|
||||
*/
|
||||
class LibreTuya {
|
||||
public: /* Common methods - note: these are documented in LibreTuyaAPI.cpp */
|
||||
const char *getVersion();
|
||||
const char *getBoard();
|
||||
ChipFamily getChipFamily();
|
||||
const char *getChipFamilyName();
|
||||
const char *getDeviceName();
|
||||
uint32_t getCpuFreqMHz();
|
||||
uint32_t getFlashChipSize();
|
||||
uint8_t otaGetRunning();
|
||||
uint8_t otaGetTarget();
|
||||
bool otaRollback();
|
||||
bool otaCanRollback();
|
||||
|
||||
public: /* Family-defined methods */
|
||||
/**
|
||||
* @brief Reboot the CPU.
|
||||
*/
|
||||
void restart();
|
||||
/**
|
||||
* @brief Reconfigure GPIO pins used for debugging
|
||||
* (SWD/JTAG), so that they can be used as normal I/O.
|
||||
*/
|
||||
void gpioRecover();
|
||||
|
||||
public: /* CPU-related */
|
||||
/**
|
||||
* @brief Get CPU model ID.
|
||||
*/
|
||||
ChipType getChipType();
|
||||
/**
|
||||
* @brief Get CPU model name as string.
|
||||
*/
|
||||
const char *getChipModel();
|
||||
/**
|
||||
* @brief Get CPU unique ID. This may be based on MAC, eFuse, etc.
|
||||
* Note: the number should be 24-bit (with most significant byte being zero).
|
||||
*/
|
||||
uint32_t getChipId();
|
||||
/**
|
||||
* @brief Get CPU core count.
|
||||
*/
|
||||
uint8_t getChipCores();
|
||||
/**
|
||||
* @brief Get CPU core type name as string.
|
||||
*/
|
||||
const char *getChipCoreType();
|
||||
/**
|
||||
* @brief Get CPU frequency in Hz.
|
||||
*/
|
||||
uint32_t getCpuFreq();
|
||||
/**
|
||||
* @brief Get CPU cycle count.
|
||||
*/
|
||||
uint32_t getCycleCount();
|
||||
|
||||
public: /* Flash memory utilities */
|
||||
/**
|
||||
* @brief Read flash chip ID and return a FlashId struct.
|
||||
*/
|
||||
FlashId getFlashChipId();
|
||||
|
||||
public: /* Memory management */
|
||||
/**
|
||||
* @brief Get total RAM size.
|
||||
*/
|
||||
uint32_t getRamSize();
|
||||
/**
|
||||
* @brief Get total heap size.
|
||||
*/
|
||||
uint32_t getHeapSize();
|
||||
/**
|
||||
* @brief Get free heap size.
|
||||
*/
|
||||
uint32_t getFreeHeap();
|
||||
/**
|
||||
* @brief Get lowest level of free heap memory.
|
||||
*/
|
||||
uint32_t getMinFreeHeap();
|
||||
/**
|
||||
* @brief Get largest block of heap that can be allocated at once.
|
||||
*/
|
||||
uint32_t getMaxAllocHeap();
|
||||
|
||||
public: /* OTA-related */
|
||||
/**
|
||||
* @brief Read the currently active OTA index, i.e. the one that will boot upon restart.
|
||||
*/
|
||||
uint8_t otaGetStoredIndex();
|
||||
/**
|
||||
* @brief Check if the chip supports dual-OTA.
|
||||
*/
|
||||
bool otaSupportsDual();
|
||||
/**
|
||||
* @brief Check if OTA1 image is valid.
|
||||
*/
|
||||
bool otaHasImage1();
|
||||
/**
|
||||
* @brief Check if OTA2 image is valid.
|
||||
*/
|
||||
bool otaHasImage2();
|
||||
/**
|
||||
* @brief Try to switch OTA index to the other image.
|
||||
*
|
||||
* Note: should return true for chips without dual-OTA. Should return false if one of two images is not valid.
|
||||
*
|
||||
* @param force switch even if other image already marked as active
|
||||
* @return false if writing failed; true otherwise
|
||||
*/
|
||||
bool otaSwitch(bool force = false);
|
||||
};
|
||||
|
||||
extern LibreTuya LT;
|
||||
extern LibreTuya ESP;
|
||||
|
||||
#endif
|
||||
33
arduino/libretuya/core/LibreTuyaCompat.cpp
Normal file
33
arduino/libretuya/core/LibreTuyaCompat.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-04. */
|
||||
|
||||
#include "LibreTuyaCompat.h"
|
||||
|
||||
#if LT_HAS_FREERTOS
|
||||
BaseType_t xTaskCreateUniversal(
|
||||
TaskFunction_t pxTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t usStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pxCreatedTask,
|
||||
const BaseType_t xCoreID
|
||||
) {
|
||||
// #ifndef CONFIG_FREERTOS_UNICORE
|
||||
// if (xCoreID >= 0 && xCoreID < 2) {
|
||||
// return xTaskCreatePinnedToCore(
|
||||
// pxTaskCode,
|
||||
// pcName,
|
||||
// usStackDepth,
|
||||
// pvParameters,
|
||||
// uxPriority,
|
||||
// pxCreatedTask,
|
||||
// xCoreID
|
||||
// );
|
||||
// } else {
|
||||
// #endif
|
||||
return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
|
||||
// #ifndef CONFIG_FREERTOS_UNICORE
|
||||
// }
|
||||
// #endif
|
||||
}
|
||||
#endif
|
||||
42
arduino/libretuya/core/LibreTuyaCompat.h
Normal file
42
arduino/libretuya/core/LibreTuyaCompat.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-04. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if LT_HAS_FREERTOS
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#endif
|
||||
|
||||
// Definitions for error constants.
|
||||
#define esp_err_t int
|
||||
#define ESP_OK 0 /*!< esp_err_t value indicating success (no error) */
|
||||
#define ESP_FAIL -1 /*!< Generic esp_err_t code indicating failure */
|
||||
|
||||
// ArduinoCore-API doesn't define these anymore
|
||||
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
|
||||
#define PGM_VOID_P const void *
|
||||
#define vsnprintf_P vsnprintf
|
||||
#define OUTPUT_OPEN_DRAIN OUTPUT_OPENDRAIN
|
||||
#define attachInterruptArg attachInterruptParam
|
||||
#define voidFuncPtrArg voidFuncPtrParam
|
||||
|
||||
// FreeRTOS utilities
|
||||
#if LT_HAS_FREERTOS
|
||||
// if xCoreID < 0 or CPU is unicore, it will use xTaskCreate, else xTaskCreatePinnedToCore
|
||||
// allows to easily handle all possible situations without repetitive code
|
||||
BaseType_t xTaskCreateUniversal(
|
||||
TaskFunction_t pxTaskCode,
|
||||
const char *const pcName,
|
||||
const uint32_t usStackDepth,
|
||||
void *const pvParameters,
|
||||
UBaseType_t uxPriority,
|
||||
TaskHandle_t *const pxCreatedTask,
|
||||
const BaseType_t xCoreID
|
||||
);
|
||||
#define xTaskCreatePinnedToCore xTaskCreateUniversal
|
||||
#endif
|
||||
|
||||
// Default values from sdkconfig.h
|
||||
#define CONFIG_LWIP_MAX_ACTIVE_TCP 16
|
||||
@@ -1,3 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
// see docs/API Configuration
|
||||
@@ -21,8 +23,8 @@
|
||||
#define LT_LOGGER_TIMESTAMP 1
|
||||
#endif
|
||||
|
||||
#ifndef LT_LOGGER_FILE
|
||||
#define LT_LOGGER_FILE 0
|
||||
#ifndef LT_LOGGER_CALLER
|
||||
#define LT_LOGGER_CALLER 1
|
||||
#endif
|
||||
|
||||
#ifndef LT_LOGGER_TASK
|
||||
@@ -42,6 +44,16 @@
|
||||
#define LT_LOGLEVEL LT_LEVEL_INFO
|
||||
#endif
|
||||
|
||||
// Free heap size debugging
|
||||
#ifndef LT_LOG_HEAP
|
||||
#define LT_LOG_HEAP 0
|
||||
#endif
|
||||
|
||||
// Debug errno values using LT_ERRNO()
|
||||
#ifndef LT_LOG_ERRNO
|
||||
#define LT_LOG_ERRNO 0
|
||||
#endif
|
||||
|
||||
// Per-module debugging
|
||||
#ifndef LT_DEBUG_WIFI
|
||||
#define LT_DEBUG_WIFI 0
|
||||
@@ -62,3 +74,7 @@
|
||||
#ifndef LT_DEBUG_WIFI_AP
|
||||
#define LT_DEBUG_WIFI_AP 0
|
||||
#endif
|
||||
|
||||
#ifndef LT_DEBUG_SSL
|
||||
#define LT_DEBUG_SSL 0
|
||||
#endif
|
||||
103
arduino/libretuya/core/LibreTuyaCustom.c
Normal file
103
arduino/libretuya/core/LibreTuyaCustom.c
Normal file
@@ -0,0 +1,103 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
|
||||
|
||||
#include "LibreTuyaCustom.h"
|
||||
|
||||
int _analogReadResolution = 10; // 0-1023
|
||||
int _analogWriteResolution = 8; // 0-255
|
||||
int _analogWritePeriod = 20000; // 50 Hz
|
||||
|
||||
/**
|
||||
* @brief Check if pin is invalid (too low or too high).
|
||||
*/
|
||||
bool pinInvalid(pin_size_t pinNumber) {
|
||||
#ifdef PINS_COUNT
|
||||
return pinNumber < 0 || pinNumber >= PINS_COUNT;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get PinInfo struct for the specified number.
|
||||
* Returns NULL if pin number is invalid.
|
||||
*/
|
||||
PinInfo *pinInfo(pin_size_t pinNumber) {
|
||||
if (pinInvalid(pinNumber))
|
||||
return NULL;
|
||||
return &(pinTable[pinNumber]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if pin supports all features represented by 'mask'.
|
||||
*/
|
||||
bool pinSupported(PinInfo *pin, uint32_t mask) {
|
||||
return (pin->supported & mask) == mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if pin has all features represented by 'mask' enabled.
|
||||
*/
|
||||
bool pinEnabled(PinInfo *pin, uint32_t mask) {
|
||||
return (pin->enabled & mask) == mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if GPIO pin is configured as output.
|
||||
*/
|
||||
bool pinIsOutput(PinInfo *pin) {
|
||||
return pin->mode == OUTPUT || pin->mode == OUTPUT_OPENDRAIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if GPIO pin is configured as output.
|
||||
*/
|
||||
bool pinIsInput(PinInfo *pin) {
|
||||
return pin->mode == INPUT || pin->mode == INPUT_PULLUP || pin->mode == INPUT_PULLDOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read voltage from ADC and return a value between 0 and
|
||||
* the current reading resolution.
|
||||
*/
|
||||
int analogRead(pin_size_t pinNumber) {
|
||||
float voltage = analogReadVoltage(pinNumber);
|
||||
float maxVoltage = analogReadMaxVoltage(pinNumber);
|
||||
uint16_t ret = round((1 << _analogReadResolution) * voltage / maxVoltage);
|
||||
if (ret >= (1 << _analogReadResolution))
|
||||
ret = (1 << _analogReadResolution) - 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set resolution of values (in bits) returned by analogRead().
|
||||
* Defaults to 10 bit (0-1023).
|
||||
*/
|
||||
void analogReadResolution(int res) {
|
||||
_analogReadResolution = res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set resolution of values (in bits) expected by analogWrite().
|
||||
* Defaults to 8 bit (0-255).
|
||||
*/
|
||||
void analogWriteResolution(int res) {
|
||||
_analogWriteResolution = res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PWM output frequency (in Hz).
|
||||
* Defaults to 50 Hz (20,000 uS).
|
||||
*/
|
||||
void analogWriteFrequency(int hz) {
|
||||
_analogWritePeriod = 1E6 / hz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set PWM output frequency (cycle period) in microseconds.
|
||||
* Defaults to 20,000 uS (50 Hz).
|
||||
*/
|
||||
void analogWritePeriod(int us) {
|
||||
_analogWritePeriod = us;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void analogReference(uint8_t mode) {}
|
||||
87
arduino/libretuya/core/LibreTuyaCustom.h
Normal file
87
arduino/libretuya/core/LibreTuyaCustom.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-06. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LibreTuyaAPI.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Run main_task & start OS kernel (family-defined)
|
||||
*/
|
||||
extern bool startMainTask();
|
||||
|
||||
/**
|
||||
* @brief Main setup() and loop() task.
|
||||
* Not to be called directly.
|
||||
*/
|
||||
extern void main_task(const void *arg);
|
||||
|
||||
#define PIN_NONE (1 << 0)
|
||||
#define PIN_GPIO (1 << 1)
|
||||
#define PIN_IRQ (1 << 2)
|
||||
#define PIN_PWM (1 << 3)
|
||||
#define PIN_ADC (1 << 4)
|
||||
#define PIN_DAC (1 << 5)
|
||||
#define PIN_I2C (1 << 6)
|
||||
#define PIN_I2S (1 << 7)
|
||||
#define PIN_JTAG (1 << 8)
|
||||
#define PIN_SPI (1 << 9)
|
||||
#define PIN_SWD (1 << 10)
|
||||
#define PIN_UART (1 << 11)
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief GPIO name in the family SDK.
|
||||
*/
|
||||
uint32_t gpio;
|
||||
/**
|
||||
* @brief Supported pin functions.
|
||||
*/
|
||||
uint32_t supported;
|
||||
/**
|
||||
* @brief Enabled pin functions. Used values are family-specific.
|
||||
*/
|
||||
uint32_t enabled;
|
||||
/**
|
||||
* @brief Pin mode (direction, IRQ level, etc.).
|
||||
*/
|
||||
uint32_t mode;
|
||||
} PinInfo;
|
||||
|
||||
extern PinInfo pinTable[];
|
||||
|
||||
// Custom Wiring methods
|
||||
|
||||
bool pinInvalid(pin_size_t pinNumber);
|
||||
PinInfo *pinInfo(pin_size_t pinNumber);
|
||||
bool pinSupported(PinInfo *pin, uint32_t mask);
|
||||
bool pinEnabled(PinInfo *pin, uint32_t mask);
|
||||
bool pinIsOutput(PinInfo *pin);
|
||||
bool pinIsInput(PinInfo *pin);
|
||||
|
||||
int analogRead(pin_size_t pinNumber);
|
||||
void analogReadResolution(int res);
|
||||
void analogWriteResolution(int res);
|
||||
void analogWriteFrequency(int hz);
|
||||
void analogWritePeriod(int us);
|
||||
|
||||
extern int _analogReadResolution;
|
||||
extern int _analogWriteResolution;
|
||||
extern int _analogWritePeriod;
|
||||
|
||||
/**
|
||||
* @brief Read voltage from analog input (in millivolts).
|
||||
*/
|
||||
uint16_t analogReadVoltage(pin_size_t pinNumber);
|
||||
|
||||
/**
|
||||
* @brief Get max reading voltage for the specified pin (millivolts).
|
||||
*/
|
||||
uint16_t analogReadMaxVoltage(pin_size_t pinNumber);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
@@ -1,8 +1,10 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-28. */
|
||||
|
||||
#include "lt_logger.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#if LT_LOGGER_TASK
|
||||
#if LT_LOGGER_TASK && LT_HAS_FREERTOS
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#endif
|
||||
@@ -40,8 +42,8 @@ const uint8_t colors[] = {
|
||||
|
||||
unsigned long millis(void);
|
||||
|
||||
#if LT_LOGGER_FILE
|
||||
void lt_log(const uint8_t level, const char *filename, const unsigned short line, const char *format, ...) {
|
||||
#if LT_LOGGER_CALLER
|
||||
void lt_log(const uint8_t level, const char *caller, const unsigned short line, const char *format, ...) {
|
||||
#else
|
||||
void lt_log(const uint8_t level, const char *format, ...) {
|
||||
#endif
|
||||
@@ -55,7 +57,7 @@ void lt_log(const uint8_t level, const char *format, ...) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LT_LOGGER_TASK
|
||||
#if LT_LOGGER_TASK && LT_HAS_FREERTOS
|
||||
char task_colon = ':';
|
||||
TaskHandle_t task = xTaskGetCurrentTaskHandle();
|
||||
char *task_name = pcTaskGetTaskName(task);
|
||||
@@ -85,19 +87,18 @@ void lt_log(const uint8_t level, const char *format, ...) {
|
||||
#if LT_LOGGER_COLOR
|
||||
"\e[0m"
|
||||
#endif
|
||||
#if LT_LOGGER_FILE
|
||||
"%s:%hu: "
|
||||
#if LT_LOGGER_CALLER
|
||||
"%s():%hu: "
|
||||
#endif
|
||||
#if LT_LOGGER_TASK
|
||||
#if LT_LOGGER_TASK && LT_HAS_FREERTOS
|
||||
"%s%c "
|
||||
#endif
|
||||
,
|
||||
levels[level]
|
||||
#if LT_LOGGER_COLOR
|
||||
,
|
||||
c_bright, // whether text is bright
|
||||
c_value // text color
|
||||
c_value, // text color
|
||||
#endif
|
||||
levels[level]
|
||||
#if LT_LOGGER_TIMESTAMP
|
||||
,
|
||||
seconds // float
|
||||
@@ -106,12 +107,12 @@ void lt_log(const uint8_t level, const char *format, ...) {
|
||||
zero // append missing zeroes if printf "%11.3f" prints "0."
|
||||
#endif
|
||||
#endif
|
||||
#if LT_LOGGER_FILE
|
||||
#if LT_LOGGER_CALLER
|
||||
,
|
||||
filename,
|
||||
caller,
|
||||
line
|
||||
#endif
|
||||
#if LT_LOGGER_TASK
|
||||
#if LT_LOGGER_TASK && LT_HAS_FREERTOS
|
||||
,
|
||||
task_name,
|
||||
task_colon // printing outside of tasks
|
||||
175
arduino/libretuya/core/lt_logger.h
Normal file
175
arduino/libretuya/core/lt_logger.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-28. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LibreTuyaConfig.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#if LT_LOGGER_CALLER
|
||||
#define LT_LOG(level, caller, line, ...) lt_log(level, caller, line, __VA_ARGS__)
|
||||
void lt_log(const uint8_t level, const char *caller, const unsigned short line, const char *format, ...);
|
||||
#else
|
||||
#define LT_LOG(level, caller, line, ...) lt_log(level, __VA_ARGS__)
|
||||
void lt_log(const uint8_t level, const char *format, ...);
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_TRACE >= LT_LOGLEVEL
|
||||
#define LT_T(...) LT_LOG(LT_LEVEL_TRACE, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#define LT_V(...) LT_LOG(LT_LEVEL_TRACE, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_T(...)
|
||||
#define LT_V(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_DEBUG >= LT_LOGLEVEL
|
||||
#define LT_D(...) LT_LOG(LT_LEVEL_DEBUG, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_D(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_INFO >= LT_LOGLEVEL
|
||||
#define LT_I(...) LT_LOG(LT_LEVEL_INFO, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_I(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_WARN >= LT_LOGLEVEL
|
||||
#define LT_W(...) LT_LOG(LT_LEVEL_WARN, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_W(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_ERROR >= LT_LOGLEVEL
|
||||
#define LT_E(...) LT_LOG(LT_LEVEL_ERROR, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_E(...)
|
||||
#endif
|
||||
|
||||
#if LT_LEVEL_FATAL >= LT_LOGLEVEL
|
||||
#define LT_F(...) LT_LOG(LT_LEVEL_FATAL, __FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define LT_F(...)
|
||||
#endif
|
||||
|
||||
#if LT_LOG_HEAP
|
||||
#define LT_HEAP_I() LT_I("Free heap: %u", LT_HEAP_FUNC());
|
||||
#else
|
||||
#define LT_HEAP_I()
|
||||
#endif
|
||||
|
||||
// ESP32 compat
|
||||
#define log_printf(...) LT_I(__VA_ARGS__)
|
||||
#define log_v(...) LT_V(__VA_ARGS__)
|
||||
#define log_d(...) LT_D(__VA_ARGS__)
|
||||
#define log_i(...) LT_I(__VA_ARGS__)
|
||||
#define log_w(...) LT_W(__VA_ARGS__)
|
||||
#define log_e(...) LT_E(__VA_ARGS__)
|
||||
#define log_n(...) LT_E(__VA_ARGS__)
|
||||
#define isr_log_v(...) LT_V(__VA_ARGS__)
|
||||
#define isr_log_d(...) LT_D(__VA_ARGS__)
|
||||
#define isr_log_i(...) LT_I(__VA_ARGS__)
|
||||
#define isr_log_w(...) LT_W(__VA_ARGS__)
|
||||
#define isr_log_e(...) LT_E(__VA_ARGS__)
|
||||
#define isr_log_n(...) LT_E(__VA_ARGS__)
|
||||
#define ESP_LOGV(...) LT_V(__VA_ARGS__)
|
||||
#define ESP_LOGD(...) LT_D(__VA_ARGS__)
|
||||
#define ESP_LOGI(...) LT_I(__VA_ARGS__)
|
||||
#define ESP_LOGW(...) LT_W(__VA_ARGS__)
|
||||
#define ESP_LOGE(...) LT_E(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGV(...) LT_V(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGD(...) LT_D(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGI(...) LT_I(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGW(...) LT_W(__VA_ARGS__)
|
||||
#define ESP_EARLY_LOGE(...) LT_E(__VA_ARGS__)
|
||||
#define ets_printf(...) LT_I(__VA_ARGS__)
|
||||
#define ETS_PRINTF(...) LT_I(__VA_ARGS__)
|
||||
|
||||
#define LT_T_MOD(module, ...) \
|
||||
do { \
|
||||
if (module) { \
|
||||
LT_T(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LT_D_MOD(module, ...) \
|
||||
do { \
|
||||
if (module) { \
|
||||
LT_D(__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LT_RET(ret) \
|
||||
LT_E("ret=%d", ret); \
|
||||
return ret;
|
||||
|
||||
#define LT_RET_NZ(ret) \
|
||||
if (ret) { \
|
||||
LT_E("ret=%d", ret); \
|
||||
return ret; \
|
||||
}
|
||||
#define LT_RET_LZ(ret) \
|
||||
if (ret < 0) { \
|
||||
LT_E("ret=%d", ret); \
|
||||
return ret; \
|
||||
}
|
||||
#define LT_RET_LEZ(ret) \
|
||||
if (ret <= 0) { \
|
||||
LT_E("ret=%d", ret); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define LT_ERRNO_NZ(ret) \
|
||||
if (ret) { \
|
||||
LT_E("errno=%d, ret=%d", errno, ret); \
|
||||
return ret; \
|
||||
}
|
||||
#define LT_ERRNO_LZ(ret) \
|
||||
if (ret < 0) { \
|
||||
LT_E("errno=%d, ret=%d", errno, ret); \
|
||||
return ret; \
|
||||
}
|
||||
#define LT_ERRNO_LEZ(ret) \
|
||||
if (ret <= 0) { \
|
||||
LT_E("errno=%d, ret=%d", errno, ret); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#if LT_LOG_ERRNO
|
||||
#define LT_ERRNO() \
|
||||
if (errno) { \
|
||||
LT_E("errno=%d", errno); \
|
||||
errno = 0; \
|
||||
}
|
||||
#else
|
||||
#define LT_ERRNO()
|
||||
#endif
|
||||
|
||||
// WiFi.cpp
|
||||
#define LT_T_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
#define LT_V_WG(...) LT_T_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
#define LT_D_WG(...) LT_D_MOD(LT_DEBUG_WIFI, __VA_ARGS__)
|
||||
|
||||
// WiFiClient.cpp
|
||||
#define LT_T_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
#define LT_V_WC(...) LT_T_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
#define LT_D_WC(...) LT_D_MOD(LT_DEBUG_WIFI_CLIENT, __VA_ARGS__)
|
||||
|
||||
// WiFiServer.cpp
|
||||
#define LT_T_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
#define LT_V_WS(...) LT_T_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
#define LT_D_WS(...) LT_D_MOD(LT_DEBUG_WIFI_SERVER, __VA_ARGS__)
|
||||
|
||||
// WiFiSTA.cpp
|
||||
#define LT_T_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
#define LT_V_WSTA(...) LT_T_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
#define LT_D_WSTA(...) LT_D_MOD(LT_DEBUG_WIFI_STA, __VA_ARGS__)
|
||||
|
||||
// WiFiAP.cpp
|
||||
#define LT_T_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
#define LT_V_WAP(...) LT_T_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
#define LT_D_WAP(...) LT_D_MOD(LT_DEBUG_WIFI_AP, __VA_ARGS__)
|
||||
|
||||
// WiFiClientSecure.cpp & implementations
|
||||
#define LT_T_SSL(...) LT_T_MOD(LT_DEBUG_SSL, __VA_ARGS__)
|
||||
#define LT_V_SSL(...) LT_T_MOD(LT_DEBUG_SSL, __VA_ARGS__)
|
||||
#define LT_D_SSL(...) LT_D_MOD(LT_DEBUG_SSL, __VA_ARGS__)
|
||||
30
arduino/libretuya/libraries/Flash/Flash.cpp
Normal file
30
arduino/libretuya/libraries/Flash/Flash.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-24. */
|
||||
|
||||
#include "Flash.h"
|
||||
|
||||
extern "C" {
|
||||
#include <fal.h>
|
||||
}
|
||||
|
||||
// Global Flash object.
|
||||
FlashClass Flash;
|
||||
|
||||
FlashId FlashClass::getChipId() {
|
||||
return LT.getFlashChipId();
|
||||
}
|
||||
|
||||
uint32_t FlashClass::getSize() {
|
||||
return LT.getFlashChipSize();
|
||||
}
|
||||
|
||||
bool FlashClass::eraseSector(uint32_t offset) {
|
||||
return fal_partition_erase(fal_root_part, offset, 1) >= 0;
|
||||
}
|
||||
|
||||
bool FlashClass::readBlock(uint32_t offset, uint8_t *data, size_t size) {
|
||||
return fal_partition_read(fal_root_part, offset, data, size) >= 0;
|
||||
}
|
||||
|
||||
bool FlashClass::writeBlock(uint32_t offset, uint8_t *data, size_t size) {
|
||||
return fal_partition_write(fal_root_part, offset, data, size) >= 0;
|
||||
}
|
||||
@@ -1,19 +1,11 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-24. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "api/Flash.h"
|
||||
|
||||
struct flash_s;
|
||||
typedef struct flash_s flash_t;
|
||||
|
||||
class FlashClass : public IFlashClass {
|
||||
private:
|
||||
flash_t *flash;
|
||||
void initialize();
|
||||
#include <Arduino.h>
|
||||
|
||||
class FlashClass {
|
||||
public:
|
||||
FlashClass();
|
||||
~FlashClass();
|
||||
|
||||
FlashId getChipId();
|
||||
uint32_t getSize();
|
||||
|
||||
1629
arduino/libretuya/libraries/HTTPClient/HTTPClient.cpp
Normal file
1629
arduino/libretuya/libraries/HTTPClient/HTTPClient.cpp
Normal file
File diff suppressed because it is too large
Load Diff
305
arduino/libretuya/libraries/HTTPClient/HTTPClient.h
Normal file
305
arduino/libretuya/libraries/HTTPClient/HTTPClient.h
Normal file
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* HTTPClient.h
|
||||
*
|
||||
* Created on: 02.11.2015
|
||||
*
|
||||
* Copyright (c) 2015 Markus Sattler. All rights reserved.
|
||||
* This file is part of the HTTPClient for Arduino.
|
||||
* Port to ESP32 by Evandro Luis Copercini (2017),
|
||||
* changed fingerprints to CA verification.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HTTPClient_H_
|
||||
#define HTTPClient_H_
|
||||
|
||||
#ifndef HTTPCLIENT_1_1_COMPATIBLE
|
||||
#define HTTPCLIENT_1_1_COMPATIBLE
|
||||
#endif
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <WiFiClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <memory>
|
||||
|
||||
/// Cookie jar support
|
||||
#include <vector>
|
||||
|
||||
#define HTTPCLIENT_DEFAULT_TCP_TIMEOUT (5000)
|
||||
|
||||
/// HTTP client errors
|
||||
#define HTTPC_ERROR_CONNECTION_REFUSED (-1)
|
||||
#define HTTPC_ERROR_SEND_HEADER_FAILED (-2)
|
||||
#define HTTPC_ERROR_SEND_PAYLOAD_FAILED (-3)
|
||||
#define HTTPC_ERROR_NOT_CONNECTED (-4)
|
||||
#define HTTPC_ERROR_CONNECTION_LOST (-5)
|
||||
#define HTTPC_ERROR_NO_STREAM (-6)
|
||||
#define HTTPC_ERROR_NO_HTTP_SERVER (-7)
|
||||
#define HTTPC_ERROR_TOO_LESS_RAM (-8)
|
||||
#define HTTPC_ERROR_ENCODING (-9)
|
||||
#define HTTPC_ERROR_STREAM_WRITE (-10)
|
||||
#define HTTPC_ERROR_READ_TIMEOUT (-11)
|
||||
|
||||
/// size for the stream handling
|
||||
#define HTTP_TCP_BUFFER_SIZE (1460)
|
||||
|
||||
/// HTTP codes see RFC7231
|
||||
typedef enum {
|
||||
HTTP_CODE_CONTINUE = 100,
|
||||
HTTP_CODE_SWITCHING_PROTOCOLS = 101,
|
||||
HTTP_CODE_PROCESSING = 102,
|
||||
HTTP_CODE_OK = 200,
|
||||
HTTP_CODE_CREATED = 201,
|
||||
HTTP_CODE_ACCEPTED = 202,
|
||||
HTTP_CODE_NON_AUTHORITATIVE_INFORMATION = 203,
|
||||
HTTP_CODE_NO_CONTENT = 204,
|
||||
HTTP_CODE_RESET_CONTENT = 205,
|
||||
HTTP_CODE_PARTIAL_CONTENT = 206,
|
||||
HTTP_CODE_MULTI_STATUS = 207,
|
||||
HTTP_CODE_ALREADY_REPORTED = 208,
|
||||
HTTP_CODE_IM_USED = 226,
|
||||
HTTP_CODE_MULTIPLE_CHOICES = 300,
|
||||
HTTP_CODE_MOVED_PERMANENTLY = 301,
|
||||
HTTP_CODE_FOUND = 302,
|
||||
HTTP_CODE_SEE_OTHER = 303,
|
||||
HTTP_CODE_NOT_MODIFIED = 304,
|
||||
HTTP_CODE_USE_PROXY = 305,
|
||||
HTTP_CODE_TEMPORARY_REDIRECT = 307,
|
||||
HTTP_CODE_PERMANENT_REDIRECT = 308,
|
||||
HTTP_CODE_BAD_REQUEST = 400,
|
||||
HTTP_CODE_UNAUTHORIZED = 401,
|
||||
HTTP_CODE_PAYMENT_REQUIRED = 402,
|
||||
HTTP_CODE_FORBIDDEN = 403,
|
||||
HTTP_CODE_NOT_FOUND = 404,
|
||||
HTTP_CODE_METHOD_NOT_ALLOWED = 405,
|
||||
HTTP_CODE_NOT_ACCEPTABLE = 406,
|
||||
HTTP_CODE_PROXY_AUTHENTICATION_REQUIRED = 407,
|
||||
HTTP_CODE_REQUEST_TIMEOUT = 408,
|
||||
HTTP_CODE_CONFLICT = 409,
|
||||
HTTP_CODE_GONE = 410,
|
||||
HTTP_CODE_LENGTH_REQUIRED = 411,
|
||||
HTTP_CODE_PRECONDITION_FAILED = 412,
|
||||
HTTP_CODE_PAYLOAD_TOO_LARGE = 413,
|
||||
HTTP_CODE_URI_TOO_LONG = 414,
|
||||
HTTP_CODE_UNSUPPORTED_MEDIA_TYPE = 415,
|
||||
HTTP_CODE_RANGE_NOT_SATISFIABLE = 416,
|
||||
HTTP_CODE_EXPECTATION_FAILED = 417,
|
||||
HTTP_CODE_MISDIRECTED_REQUEST = 421,
|
||||
HTTP_CODE_UNPROCESSABLE_ENTITY = 422,
|
||||
HTTP_CODE_LOCKED = 423,
|
||||
HTTP_CODE_FAILED_DEPENDENCY = 424,
|
||||
HTTP_CODE_UPGRADE_REQUIRED = 426,
|
||||
HTTP_CODE_PRECONDITION_REQUIRED = 428,
|
||||
HTTP_CODE_TOO_MANY_REQUESTS = 429,
|
||||
HTTP_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
|
||||
HTTP_CODE_INTERNAL_SERVER_ERROR = 500,
|
||||
HTTP_CODE_NOT_IMPLEMENTED = 501,
|
||||
HTTP_CODE_BAD_GATEWAY = 502,
|
||||
HTTP_CODE_SERVICE_UNAVAILABLE = 503,
|
||||
HTTP_CODE_GATEWAY_TIMEOUT = 504,
|
||||
HTTP_CODE_HTTP_VERSION_NOT_SUPPORTED = 505,
|
||||
HTTP_CODE_VARIANT_ALSO_NEGOTIATES = 506,
|
||||
HTTP_CODE_INSUFFICIENT_STORAGE = 507,
|
||||
HTTP_CODE_LOOP_DETECTED = 508,
|
||||
HTTP_CODE_NOT_EXTENDED = 510,
|
||||
HTTP_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511
|
||||
} t_http_codes;
|
||||
|
||||
typedef enum { HTTPC_TE_IDENTITY, HTTPC_TE_CHUNKED } transferEncoding_t;
|
||||
|
||||
/**
|
||||
* redirection follow mode.
|
||||
* + `HTTPC_DISABLE_FOLLOW_REDIRECTS` - no redirection will be followed.
|
||||
* + `HTTPC_STRICT_FOLLOW_REDIRECTS` - strict RFC2616, only requests using
|
||||
* GET or HEAD methods will be redirected (using the same method),
|
||||
* since the RFC requires end-user confirmation in other cases.
|
||||
* + `HTTPC_FORCE_FOLLOW_REDIRECTS` - all redirections will be followed,
|
||||
* regardless of a used method. New request will use the same method,
|
||||
* and they will include the same body data and the same headers.
|
||||
* In the sense of the RFC, it's just like every redirection is confirmed.
|
||||
*/
|
||||
typedef enum {
|
||||
HTTPC_DISABLE_FOLLOW_REDIRECTS,
|
||||
HTTPC_STRICT_FOLLOW_REDIRECTS,
|
||||
HTTPC_FORCE_FOLLOW_REDIRECTS
|
||||
} followRedirects_t;
|
||||
|
||||
#ifdef HTTPCLIENT_1_1_COMPATIBLE
|
||||
class TransportTraits;
|
||||
typedef std::unique_ptr<TransportTraits> TransportTraitsPtr;
|
||||
#endif
|
||||
|
||||
// cookie jar support
|
||||
typedef struct {
|
||||
String host; // host which tries to set the cookie
|
||||
time_t date; // timestamp of the response that set the cookie
|
||||
String name;
|
||||
String value;
|
||||
String domain;
|
||||
String path = "";
|
||||
|
||||
struct {
|
||||
time_t date = 0;
|
||||
bool valid = false;
|
||||
} expires;
|
||||
|
||||
struct {
|
||||
time_t duration = 0;
|
||||
bool valid = false;
|
||||
} max_age;
|
||||
|
||||
bool http_only = false;
|
||||
bool secure = false;
|
||||
} Cookie;
|
||||
|
||||
typedef std::vector<Cookie> CookieJar;
|
||||
|
||||
class HTTPClient {
|
||||
public:
|
||||
HTTPClient();
|
||||
~HTTPClient();
|
||||
|
||||
/*
|
||||
* Since both begin() functions take a reference to client as a parameter, you need to
|
||||
* ensure the client object lives the entire time of the HTTPClient
|
||||
*/
|
||||
bool begin(WiFiClient &client, String url);
|
||||
bool begin(WiFiClient &client, String host, uint16_t port, String uri = "/", bool https = false);
|
||||
|
||||
#ifdef HTTPCLIENT_1_1_COMPATIBLE
|
||||
bool begin(String url);
|
||||
bool begin(String url, const char *CAcert);
|
||||
bool begin(String host, uint16_t port, String uri = "/");
|
||||
bool begin(String host, uint16_t port, String uri, const char *CAcert);
|
||||
bool begin(String host, uint16_t port, String uri, const char *CAcert, const char *cli_cert, const char *cli_key);
|
||||
#endif
|
||||
|
||||
void end(void);
|
||||
|
||||
bool connected(void);
|
||||
|
||||
void setReuse(bool reuse); /// keep-alive
|
||||
void setUserAgent(const String &userAgent);
|
||||
void setAuthorization(const char *user, const char *password);
|
||||
void setAuthorization(const char *auth);
|
||||
void setAuthorizationType(const char *authType);
|
||||
void setConnectTimeout(int32_t connectTimeout);
|
||||
void setTimeout(uint16_t timeout);
|
||||
|
||||
// Redirections
|
||||
void setFollowRedirects(followRedirects_t follow);
|
||||
void setRedirectLimit(uint16_t limit); // max redirects to follow for a single request
|
||||
|
||||
bool setURL(const String &url);
|
||||
void useHTTP10(bool usehttp10 = true);
|
||||
|
||||
/// request handling
|
||||
int GET();
|
||||
int PATCH(uint8_t *payload, size_t size);
|
||||
int PATCH(String payload);
|
||||
int POST(uint8_t *payload, size_t size);
|
||||
int POST(String payload);
|
||||
int PUT(uint8_t *payload, size_t size);
|
||||
int PUT(String payload);
|
||||
int sendRequest(const char *type, String payload);
|
||||
int sendRequest(const char *type, uint8_t *payload = NULL, size_t size = 0);
|
||||
int sendRequest(const char *type, Stream *stream, size_t size = 0);
|
||||
|
||||
void addHeader(const String &name, const String &value, bool first = false, bool replace = true);
|
||||
|
||||
/// Response handling
|
||||
void collectHeaders(const char *headerKeys[], const size_t headerKeysCount);
|
||||
String header(const char *name); // get request header value by name
|
||||
String header(size_t i); // get request header value by number
|
||||
String headerName(size_t i); // get request header name by number
|
||||
int headers(); // get header count
|
||||
bool hasHeader(const char *name); // check if header exists
|
||||
|
||||
int getSize(void);
|
||||
const String &getLocation(void);
|
||||
|
||||
WiFiClient &getStream(void);
|
||||
WiFiClient *getStreamPtr(void);
|
||||
int writeToStream(Stream *stream);
|
||||
// String getString(void);
|
||||
|
||||
static String errorToString(int error);
|
||||
|
||||
/// Cookie jar support
|
||||
void setCookieJar(CookieJar *cookieJar);
|
||||
void resetCookieJar();
|
||||
void clearAllCookies();
|
||||
|
||||
protected:
|
||||
struct RequestArgument {
|
||||
String key;
|
||||
String value;
|
||||
};
|
||||
|
||||
bool beginInternal(String url, const char *expectedProtocol);
|
||||
void disconnect(bool preserveClient = false);
|
||||
void clear();
|
||||
int returnError(int error);
|
||||
bool connect(void);
|
||||
bool sendHeader(const char *type);
|
||||
int handleHeaderResponse();
|
||||
int writeToStreamDataBlock(Stream *stream, int len);
|
||||
|
||||
/// Cookie jar support
|
||||
void setCookie(String date, String headerValue);
|
||||
bool generateCookieString(String *cookieString);
|
||||
|
||||
#ifdef HTTPCLIENT_1_1_COMPATIBLE
|
||||
TransportTraitsPtr _transportTraits;
|
||||
std::unique_ptr<WiFiClient> _tcpDeprecated;
|
||||
#endif
|
||||
|
||||
WiFiClient *_client = nullptr;
|
||||
|
||||
/// request handling
|
||||
String _host;
|
||||
uint16_t _port = 0;
|
||||
int32_t _connectTimeout = -1;
|
||||
bool _reuse = true;
|
||||
uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
|
||||
bool _useHTTP10 = false;
|
||||
bool _secure = false;
|
||||
|
||||
String _uri;
|
||||
String _protocol;
|
||||
String _headers;
|
||||
String _userAgent = "ESP32HTTPClient";
|
||||
String _base64Authorization;
|
||||
String _authorizationType = "Basic";
|
||||
|
||||
/// Response handling
|
||||
RequestArgument *_currentHeaders = nullptr;
|
||||
size_t _headerKeysCount = 0;
|
||||
|
||||
int _returnCode = 0;
|
||||
int _size = -1;
|
||||
bool _canReuse = false;
|
||||
followRedirects_t _followRedirects = HTTPC_DISABLE_FOLLOW_REDIRECTS;
|
||||
uint16_t _redirectLimit = 10;
|
||||
String _location;
|
||||
transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY;
|
||||
|
||||
/// Cookie jar support
|
||||
CookieJar *_cookieJar = nullptr;
|
||||
};
|
||||
|
||||
#endif /* HTTPClient_H_ */
|
||||
7
arduino/libretuya/libraries/HTTPClient/strptime.h
Normal file
7
arduino/libretuya/libraries/HTTPClient/strptime.h
Normal file
@@ -0,0 +1,7 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
|
||||
extern char *strptime(const char *buf, const char *fmt, struct tm *tm);
|
||||
@@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: Never
|
||||
197
arduino/libretuya/libraries/HTTPClient/strptime/strptime.c
Normal file
197
arduino/libretuya/libraries/HTTPClient/strptime/strptime.c
Normal file
@@ -0,0 +1,197 @@
|
||||
#include <stdlib.h>
|
||||
#include <langinfo.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
char *strptime(const char *restrict s, const char *restrict f, struct tm *restrict tm)
|
||||
{
|
||||
int i, w, neg, adj, min, range, *dest, dummy;
|
||||
const char *ex;
|
||||
size_t len;
|
||||
int want_century = 0, century = 0;
|
||||
while (*f) {
|
||||
if (*f != '%') {
|
||||
if (isspace(*f)) for (; *s && isspace(*s); s++);
|
||||
else if (*s != *f) return 0;
|
||||
else s++;
|
||||
f++;
|
||||
continue;
|
||||
}
|
||||
f++;
|
||||
if (*f == '+') f++;
|
||||
if (isdigit(*f)) w=strtoul(f, (void *)&f, 10);
|
||||
else w=-1;
|
||||
adj=0;
|
||||
switch (*f++) {
|
||||
case 'a': case 'A':
|
||||
dest = &tm->tm_wday;
|
||||
min = ABDAY_1;
|
||||
range = 7;
|
||||
goto symbolic_range;
|
||||
case 'b': case 'B': case 'h':
|
||||
dest = &tm->tm_mon;
|
||||
min = ABMON_1;
|
||||
range = 12;
|
||||
goto symbolic_range;
|
||||
case 'c':
|
||||
s = strptime(s, nl_langinfo(D_T_FMT), tm);
|
||||
if (!s) return 0;
|
||||
break;
|
||||
case 'C':
|
||||
dest = ¢ury;
|
||||
if (w<0) w=2;
|
||||
want_century |= 2;
|
||||
goto numeric_digits;
|
||||
case 'd': case 'e':
|
||||
dest = &tm->tm_mday;
|
||||
min = 1;
|
||||
range = 31;
|
||||
goto numeric_range;
|
||||
case 'D':
|
||||
s = strptime(s, "%m/%d/%y", tm);
|
||||
if (!s) return 0;
|
||||
break;
|
||||
case 'H':
|
||||
dest = &tm->tm_hour;
|
||||
min = 0;
|
||||
range = 24;
|
||||
goto numeric_range;
|
||||
case 'I':
|
||||
dest = &tm->tm_hour;
|
||||
min = 1;
|
||||
range = 12;
|
||||
goto numeric_range;
|
||||
case 'j':
|
||||
dest = &tm->tm_yday;
|
||||
min = 1;
|
||||
range = 366;
|
||||
goto numeric_range;
|
||||
case 'm':
|
||||
dest = &tm->tm_mon;
|
||||
min = 1;
|
||||
range = 12;
|
||||
adj = 1;
|
||||
goto numeric_range;
|
||||
case 'M':
|
||||
dest = &tm->tm_min;
|
||||
min = 0;
|
||||
range = 60;
|
||||
goto numeric_range;
|
||||
case 'n': case 't':
|
||||
for (; *s && isspace(*s); s++);
|
||||
break;
|
||||
case 'p':
|
||||
ex = nl_langinfo(AM_STR);
|
||||
len = strlen(ex);
|
||||
if (!strncasecmp(s, ex, len)) {
|
||||
tm->tm_hour %= 12;
|
||||
break;
|
||||
}
|
||||
ex = nl_langinfo(PM_STR);
|
||||
len = strlen(ex);
|
||||
if (!strncasecmp(s, ex, len)) {
|
||||
tm->tm_hour %= 12;
|
||||
tm->tm_hour += 12;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
case 'r':
|
||||
s = strptime(s, nl_langinfo(T_FMT_AMPM), tm);
|
||||
if (!s) return 0;
|
||||
break;
|
||||
case 'R':
|
||||
s = strptime(s, "%H:%M", tm);
|
||||
if (!s) return 0;
|
||||
break;
|
||||
case 'S':
|
||||
dest = &tm->tm_sec;
|
||||
min = 0;
|
||||
range = 61;
|
||||
goto numeric_range;
|
||||
case 'T':
|
||||
s = strptime(s, "%H:%M:%S", tm);
|
||||
if (!s) return 0;
|
||||
break;
|
||||
case 'U':
|
||||
case 'W':
|
||||
/* Throw away result, for now. (FIXME?) */
|
||||
dest = &dummy;
|
||||
min = 0;
|
||||
range = 54;
|
||||
goto numeric_range;
|
||||
case 'w':
|
||||
dest = &tm->tm_wday;
|
||||
min = 0;
|
||||
range = 7;
|
||||
goto numeric_range;
|
||||
case 'x':
|
||||
s = strptime(s, nl_langinfo(D_FMT), tm);
|
||||
if (!s) return 0;
|
||||
break;
|
||||
case 'X':
|
||||
s = strptime(s, nl_langinfo(T_FMT), tm);
|
||||
if (!s) return 0;
|
||||
break;
|
||||
case 'y':
|
||||
dest = &tm->tm_year;
|
||||
w = 2;
|
||||
want_century |= 1;
|
||||
goto numeric_digits;
|
||||
case 'Y':
|
||||
dest = &tm->tm_year;
|
||||
if (w<0) w=4;
|
||||
adj = 1900;
|
||||
want_century = 0;
|
||||
goto numeric_digits;
|
||||
case '%':
|
||||
if (*s++ != '%') return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
numeric_range:
|
||||
if (!isdigit(*s)) return 0;
|
||||
*dest = 0;
|
||||
for (i=1; i<=min+range && isdigit(*s); i*=10)
|
||||
*dest = *dest * 10 + *s++ - '0';
|
||||
if (*dest - min >= (unsigned)range) return 0;
|
||||
*dest -= adj;
|
||||
switch((char *)dest - (char *)tm) {
|
||||
case offsetof(struct tm, tm_yday):
|
||||
;
|
||||
}
|
||||
goto update;
|
||||
numeric_digits:
|
||||
neg = 0;
|
||||
if (*s == '+') s++;
|
||||
else if (*s == '-') neg=1, s++;
|
||||
if (!isdigit(*s)) return 0;
|
||||
for (*dest=i=0; i<w && isdigit(*s); i++)
|
||||
*dest = *dest * 10 + *s++ - '0';
|
||||
if (neg) *dest = -*dest;
|
||||
*dest -= adj;
|
||||
goto update;
|
||||
symbolic_range:
|
||||
for (i=2*range-1; i>=0; i--) {
|
||||
ex = nl_langinfo(min+i);
|
||||
len = strlen(ex);
|
||||
if (strncasecmp(s, ex, len)) continue;
|
||||
s += len;
|
||||
*dest = i % range;
|
||||
break;
|
||||
}
|
||||
if (i<0) return 0;
|
||||
goto update;
|
||||
update:
|
||||
//FIXME
|
||||
;
|
||||
}
|
||||
}
|
||||
if (want_century) {
|
||||
if (want_century & 2) tm->tm_year += century * 100 - 1900;
|
||||
else if (tm->tm_year <= 68) tm->tm_year += 100;
|
||||
}
|
||||
return (char *)s;
|
||||
}
|
||||
31
arduino/libretuya/libraries/MD5/MD5.h
Normal file
31
arduino/libretuya/libraries/MD5/MD5.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <MD5Impl.h>
|
||||
|
||||
// available built-in implementations
|
||||
#if LT_MD5_USE_POLARSSL
|
||||
#include "MD5PolarSSLImpl.h"
|
||||
#endif
|
||||
|
||||
// common API
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef LT_MD5_CTX_T
|
||||
#define LT_MD5_CTX_T void
|
||||
#endif
|
||||
|
||||
// for compatibility with ESP8266
|
||||
typedef LT_MD5_CTX_T md5_context_t;
|
||||
|
||||
void MD5Init(LT_MD5_CTX_T *context);
|
||||
void MD5Update(LT_MD5_CTX_T *context, const unsigned char *buf, unsigned len);
|
||||
void MD5Final(unsigned char digest[16], LT_MD5_CTX_T *context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
28
arduino/libretuya/libraries/MD5/MD5PolarSSLImpl.cpp
Normal file
28
arduino/libretuya/libraries/MD5/MD5PolarSSLImpl.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
|
||||
|
||||
#if LT_ARD_HAS_MD5
|
||||
|
||||
#include "MD5.h"
|
||||
|
||||
#if LT_MD5_USE_POLARSSL
|
||||
|
||||
extern "C" {
|
||||
|
||||
void MD5Init(LT_MD5_CTX_T *context) {
|
||||
md5_init(context);
|
||||
md5_starts(context);
|
||||
}
|
||||
|
||||
void MD5Update(LT_MD5_CTX_T *context, const unsigned char *buf, unsigned len) {
|
||||
md5_update(context, buf, len);
|
||||
}
|
||||
|
||||
void MD5Final(unsigned char digest[16], LT_MD5_CTX_T *context) {
|
||||
md5_finish(context, digest);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // LT_MD5_USE_POLARSSL
|
||||
|
||||
#endif // LT_ARD_HAS_MD5
|
||||
14
arduino/libretuya/libraries/MD5/MD5PolarSSLImpl.h
Normal file
14
arduino/libretuya/libraries/MD5/MD5PolarSSLImpl.h
Normal file
@@ -0,0 +1,14 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <polarssl/md5.h>
|
||||
#define LT_MD5_CTX_T md5_context
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
98
arduino/libretuya/libraries/NetUtils/IPv6Address.cpp
Normal file
98
arduino/libretuya/libraries/NetUtils/IPv6Address.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
IPv6Address.cpp - Base class that provides IPv6Address
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "IPv6Address.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <api/Print.h>
|
||||
|
||||
IPv6Address::IPv6Address() {
|
||||
memset(_address.bytes, 0, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address(const uint8_t *address) {
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address::IPv6Address(const uint32_t *address) {
|
||||
memcpy(_address.bytes, (const uint8_t *)address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPv6Address &IPv6Address::operator=(const uint8_t *address) {
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPv6Address::operator==(const uint8_t *addr) const {
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
}
|
||||
|
||||
size_t IPv6Address::printTo(Print &p) const {
|
||||
/* size_t n = 0;
|
||||
for(int i = 0; i < 16; i+=2) {
|
||||
if(i){
|
||||
n += p.print(':');
|
||||
}
|
||||
n += p.printf("%02x", _address.bytes[i]);
|
||||
n += p.printf("%02x", _address.bytes[i+1]);
|
||||
|
||||
}
|
||||
return n; */
|
||||
}
|
||||
|
||||
String IPv6Address::toString() const {
|
||||
char szRet[40];
|
||||
sprintf(
|
||||
szRet,
|
||||
"%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
|
||||
_address.bytes[0],
|
||||
_address.bytes[1],
|
||||
_address.bytes[2],
|
||||
_address.bytes[3],
|
||||
_address.bytes[4],
|
||||
_address.bytes[5],
|
||||
_address.bytes[6],
|
||||
_address.bytes[7],
|
||||
_address.bytes[8],
|
||||
_address.bytes[9],
|
||||
_address.bytes[10],
|
||||
_address.bytes[11],
|
||||
_address.bytes[12],
|
||||
_address.bytes[13],
|
||||
_address.bytes[14],
|
||||
_address.bytes[15]
|
||||
);
|
||||
return String(szRet);
|
||||
}
|
||||
|
||||
bool IPv6Address::fromString(const char *address) {
|
||||
// format 0011:2233:4455:6677:8899:aabb:ccdd:eeff
|
||||
if (strlen(address) != 39) {
|
||||
return false;
|
||||
}
|
||||
char *pos = (char *)address;
|
||||
size_t i = 0;
|
||||
for (i = 0; i < 16; i += 2) {
|
||||
if (!sscanf(pos, "%2hhx", &_address.bytes[i]) || !sscanf(pos + 2, "%2hhx", &_address.bytes[i + 1])) {
|
||||
return false;
|
||||
}
|
||||
pos += 5;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
97
arduino/libretuya/libraries/NetUtils/IPv6Address.h
Normal file
97
arduino/libretuya/libraries/NetUtils/IPv6Address.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
IPv6Address.h - Base class that provides IPv6Address
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/Print.h>
|
||||
#include <api/String.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
|
||||
namespace arduino {
|
||||
|
||||
class IPv6Address : public Printable {
|
||||
private:
|
||||
union {
|
||||
uint8_t bytes[16]; // IPv4 address
|
||||
uint32_t dword[4];
|
||||
} _address;
|
||||
|
||||
// Access the raw byte array containing the address. Because this returns a pointer
|
||||
// to the internal structure rather than a copy of the address this function should only
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t *raw_address() {
|
||||
return _address.bytes;
|
||||
}
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPv6Address();
|
||||
IPv6Address(const uint8_t *address);
|
||||
IPv6Address(const uint32_t *address);
|
||||
|
||||
virtual ~IPv6Address() {}
|
||||
|
||||
bool fromString(const char *address);
|
||||
|
||||
bool fromString(const String &address) {
|
||||
return fromString(address.c_str());
|
||||
}
|
||||
|
||||
operator const uint8_t *() const {
|
||||
return _address.bytes;
|
||||
}
|
||||
|
||||
operator const uint32_t *() const {
|
||||
return _address.dword;
|
||||
}
|
||||
|
||||
bool operator==(const IPv6Address &addr) const {
|
||||
return (_address.dword[0] == addr._address.dword[0]) && (_address.dword[1] == addr._address.dword[1]) &&
|
||||
(_address.dword[2] == addr._address.dword[2]) && (_address.dword[3] == addr._address.dword[3]);
|
||||
}
|
||||
|
||||
bool operator==(const uint8_t *addr) const;
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const {
|
||||
return _address.bytes[index];
|
||||
}
|
||||
|
||||
uint8_t &operator[](int index) {
|
||||
return _address.bytes[index];
|
||||
}
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPv6Address objects from other types
|
||||
IPv6Address &operator=(const uint8_t *address);
|
||||
|
||||
// TODO implement printTo()
|
||||
virtual size_t printTo(Print &p) const;
|
||||
String toString() const;
|
||||
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
};
|
||||
|
||||
} // namespace arduino
|
||||
|
||||
using arduino::IPv6Address;
|
||||
5
arduino/libretuya/libraries/NetUtils/api/IPv6Address.h
Normal file
5
arduino/libretuya/libraries/NetUtils/api/IPv6Address.h
Normal file
@@ -0,0 +1,5 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-30. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../IPv6Address.h"
|
||||
@@ -1,63 +1,105 @@
|
||||
#include "WiFiClient.h"
|
||||
#include "WiFiPriv.h"
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-26. */
|
||||
|
||||
WiFiClient::WiFiClient() {
|
||||
LT_V_WC("WiFiClient()");
|
||||
_sock = -1;
|
||||
#if LT_ARD_HAS_WIFI && LT_HAS_LWIP
|
||||
|
||||
#include "LwIPClient.h"
|
||||
|
||||
#define MAX_SOCK_NUM 4
|
||||
#define WIFI_CLIENT_CONNECT_TIMEOUT 3000
|
||||
#define WIFI_CLIENT_READ_TIMEOUT 3000
|
||||
#define WIFI_CLIENT_WRITE_RETRY 10
|
||||
#define WIFI_CLIENT_SELECT_TIMEOUT 1000
|
||||
#define WIFI_CLIENT_FLUSH_BUF_SIZE 1024
|
||||
|
||||
// disable #defines removing lwip_ prefix
|
||||
#undef LWIP_COMPAT_SOCKETS
|
||||
#define LWIP_COMPAT_SOCKETS 0
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include <lwip/api.h>
|
||||
#include <lwip/dns.h>
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
} // extern "C"
|
||||
|
||||
class SocketHandle {
|
||||
public:
|
||||
int fd;
|
||||
|
||||
SocketHandle(int fd) : fd(fd) {}
|
||||
|
||||
~SocketHandle() {
|
||||
lwip_close(fd);
|
||||
}
|
||||
};
|
||||
|
||||
LwIPClient::LwIPClient() {
|
||||
LT_V_WC("LwIPClient()");
|
||||
_connected = false;
|
||||
_sock = NULL;
|
||||
_rxBuffer = NULL;
|
||||
_timeout = WIFI_CLIENT_CONNECT_TIMEOUT;
|
||||
}
|
||||
|
||||
WiFiClient::WiFiClient(int sock) {
|
||||
LT_V_WC("WiFiClient(%d)", sock);
|
||||
_sock = sock;
|
||||
LwIPClient::LwIPClient(int sock) {
|
||||
LT_V_WC("LwIPClient(%d)", sock);
|
||||
_connected = true;
|
||||
_rxBuffer = new LwIPRxBuffer(sock);
|
||||
_sock = std::make_shared<SocketHandle>(sock);
|
||||
_rxBuffer = std::make_shared<LwIPRxBuffer>(sock);
|
||||
_timeout = WIFI_CLIENT_CONNECT_TIMEOUT;
|
||||
}
|
||||
|
||||
WiFiClient::~WiFiClient() {
|
||||
LT_V_WC("~WiFiClient()");
|
||||
LwIPClient::~LwIPClient() {
|
||||
LT_V_WC("~LwIPClient()");
|
||||
stop();
|
||||
}
|
||||
|
||||
WiFiClient &WiFiClient::operator=(const IWiFiClient &other) {
|
||||
LwIPClient &LwIPClient::operator=(const LwIPClient &other) {
|
||||
stop();
|
||||
WiFiClient *oth = (WiFiClient *)&other;
|
||||
_sock = oth->_sock;
|
||||
_connected = oth->_connected;
|
||||
_rxBuffer = oth->_rxBuffer;
|
||||
_connected = other._connected;
|
||||
_sock = other._sock;
|
||||
_rxBuffer = other._rxBuffer;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool WiFiClient::operator==(const IWiFiClient &other) const {
|
||||
return _sock == other.fd() && remoteIP() == other.remoteIP() && remotePort() == other.remotePort();
|
||||
bool IWiFiClient::operator==(const IWiFiClient &other) const {
|
||||
return fd() == other.fd() && remoteIP() == other.remoteIP() && remotePort() == other.remotePort();
|
||||
}
|
||||
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port) {
|
||||
int LwIPClient::connect(IPAddress ip, uint16_t port) {
|
||||
return connect(ip, port, _timeout);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const char *host, uint16_t port) {
|
||||
int LwIPClient::connect(const char *host, uint16_t port) {
|
||||
return connect(host, port, _timeout);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout) {
|
||||
int LwIPClient::connect(const char *host, uint16_t port, int32_t timeout) {
|
||||
IPAddress ip = WiFi.hostByName(host);
|
||||
if (!ip)
|
||||
return 0;
|
||||
return connect(ip, port, timeout);
|
||||
}
|
||||
|
||||
int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
int LwIPClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
if (_connected)
|
||||
stop();
|
||||
int sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (sock < 0) {
|
||||
LT_D_WC("socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (timeout <= 0)
|
||||
timeout = _timeout; // use default when -1 passed as timeout
|
||||
|
||||
lwip_fcntl(sock, F_SETFL, lwip_fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
LT_ERRNO();
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
@@ -68,7 +110,7 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(sock, &fdset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
tv.tv_usec = timeout * 1000; // millis -> micros
|
||||
|
||||
int res = lwip_connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
if (res < 0 && errno != EINPROGRESS) {
|
||||
@@ -105,22 +147,23 @@ int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout) {
|
||||
lwip_setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
|
||||
lwip_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
|
||||
|
||||
LT_ERRNO();
|
||||
|
||||
lwip_fcntl(sock, F_SETFL, lwip_fcntl(sock, F_GETFL, 0) & ~O_NONBLOCK);
|
||||
|
||||
if (_sock != -1)
|
||||
lwip_close(_sock);
|
||||
_sock = sock;
|
||||
LT_ERRNO();
|
||||
|
||||
_connected = true;
|
||||
free(_rxBuffer);
|
||||
_rxBuffer = new LwIPRxBuffer(_sock);
|
||||
_sock = std::make_shared<SocketHandle>(sock);
|
||||
_rxBuffer = std::make_shared<LwIPRxBuffer>(sock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(uint8_t data) {
|
||||
size_t LwIPClient::write(uint8_t data) {
|
||||
return write(&data, 1);
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(Stream &stream) {
|
||||
size_t LwIPClient::write(Stream &stream) {
|
||||
uint8_t *buf = (uint8_t *)malloc(1360);
|
||||
if (!buf) {
|
||||
return 0;
|
||||
@@ -137,7 +180,7 @@ size_t WiFiClient::write(Stream &stream) {
|
||||
return written;
|
||||
}
|
||||
|
||||
size_t WiFiClient::write(const uint8_t *buf, size_t size) {
|
||||
size_t LwIPClient::write(const uint8_t *buf, size_t size) {
|
||||
if (_sock < 0 || !_connected || !size) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
@@ -149,18 +192,18 @@ size_t WiFiClient::write(const uint8_t *buf, size_t size) {
|
||||
fd_set fdset;
|
||||
struct timeval tv;
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(_sock, &fdset);
|
||||
FD_SET(fd(), &fdset);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = WIFI_CLIENT_SELECT_TIMEOUT * 1000;
|
||||
retry--;
|
||||
|
||||
if (lwip_select(_sock + 1, NULL, &fdset, NULL, &tv) < 0) {
|
||||
if (lwip_select(fd() + 1, NULL, &fdset, NULL, &tv) < 0) {
|
||||
LT_W("Select failed; errno=%d", errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (FD_ISSET(_sock, &fdset)) {
|
||||
int res = lwip_send(_sock, buf, size, MSG_DONTWAIT);
|
||||
if (FD_ISSET(fd(), &fdset)) {
|
||||
int res = lwip_send(fd(), buf, size, MSG_DONTWAIT);
|
||||
if (res > 0) {
|
||||
written += res;
|
||||
if (res >= size) {
|
||||
@@ -180,34 +223,38 @@ size_t WiFiClient::write(const uint8_t *buf, size_t size) {
|
||||
}
|
||||
}
|
||||
}
|
||||
LT_D_WC("wrote %d bytes", written);
|
||||
return written;
|
||||
}
|
||||
|
||||
int WiFiClient::available() {
|
||||
if (!_connected)
|
||||
int LwIPClient::available() {
|
||||
if (!_connected || !_rxBuffer)
|
||||
return 0;
|
||||
int res = _rxBuffer->available();
|
||||
if (_rxBuffer->failed()) {
|
||||
LT_ERRNO();
|
||||
stop();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int WiFiClient::fd() const {
|
||||
return _sock;
|
||||
int LwIPClient::fd() const {
|
||||
if (!_sock)
|
||||
return -1;
|
||||
return _sock->fd;
|
||||
}
|
||||
|
||||
int WiFiClient::socket() {
|
||||
return _sock;
|
||||
int LwIPClient::socket() {
|
||||
return fd();
|
||||
}
|
||||
|
||||
int WiFiClient::setTimeout(uint32_t seconds) {
|
||||
int LwIPClient::setTimeout(uint32_t seconds) {
|
||||
Client::setTimeout(seconds * 1000);
|
||||
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &_timeout, sizeof(_timeout));
|
||||
return lwip_setsockopt(_sock, SOL_SOCKET, SO_SNDTIMEO, &_timeout, sizeof(_timeout));
|
||||
lwip_setsockopt(fd(), SOL_SOCKET, SO_RCVTIMEO, &_timeout, sizeof(_timeout));
|
||||
return lwip_setsockopt(fd(), SOL_SOCKET, SO_SNDTIMEO, &_timeout, sizeof(_timeout));
|
||||
}
|
||||
|
||||
int WiFiClient::read() {
|
||||
int LwIPClient::read() {
|
||||
uint8_t data;
|
||||
int res = read(&data, 1);
|
||||
if (res < 0)
|
||||
@@ -217,7 +264,7 @@ int WiFiClient::read() {
|
||||
return data;
|
||||
}
|
||||
|
||||
int WiFiClient::read(uint8_t *buf, size_t size) {
|
||||
int LwIPClient::read(uint8_t *buf, size_t size) {
|
||||
int res = -1;
|
||||
if (_rxBuffer) {
|
||||
res = _rxBuffer->read(buf, size);
|
||||
@@ -228,7 +275,7 @@ int WiFiClient::read(uint8_t *buf, size_t size) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int WiFiClient::peek() {
|
||||
int LwIPClient::peek() {
|
||||
int res = -1;
|
||||
if (_rxBuffer) {
|
||||
res = _rxBuffer->peek();
|
||||
@@ -239,7 +286,7 @@ int WiFiClient::peek() {
|
||||
return res;
|
||||
}
|
||||
|
||||
void WiFiClient::flush() {
|
||||
void LwIPClient::flush() {
|
||||
int res;
|
||||
size_t len = available();
|
||||
if (!len)
|
||||
@@ -248,7 +295,7 @@ void WiFiClient::flush() {
|
||||
if (!buf)
|
||||
return;
|
||||
while (len) {
|
||||
res = lwip_recv(_sock, buf, LWIP_MIN(len, WIFI_CLIENT_FLUSH_BUF_SIZE), MSG_DONTWAIT);
|
||||
res = lwip_recv(fd(), buf, LWIP_MIN(len, WIFI_CLIENT_FLUSH_BUF_SIZE), MSG_DONTWAIT);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
break;
|
||||
@@ -258,20 +305,17 @@ void WiFiClient::flush() {
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void WiFiClient::stop() {
|
||||
LT_V_WC("stop()");
|
||||
if (_sock != -1)
|
||||
lwip_close(_sock);
|
||||
_sock = -1;
|
||||
void LwIPClient::stop() {
|
||||
LT_V_WC("Stopping TCP");
|
||||
_connected = false;
|
||||
delete _rxBuffer;
|
||||
_rxBuffer = NULL;
|
||||
_sock = NULL;
|
||||
_rxBuffer = NULL;
|
||||
}
|
||||
|
||||
uint8_t WiFiClient::connected() {
|
||||
uint8_t LwIPClient::connected() {
|
||||
if (_connected) {
|
||||
uint8_t dummy;
|
||||
if (lwip_recv(_sock, &dummy, 0, MSG_DONTWAIT) <= 0) {
|
||||
if (lwip_recv(fd(), &dummy, 0, MSG_DONTWAIT) <= 0) {
|
||||
switch (errno) {
|
||||
case EWOULDBLOCK:
|
||||
case ENOENT: // caused by vfs
|
||||
@@ -312,34 +356,36 @@ uint16_t __attribute__((noinline)) getport(int sock, int (*func)(int, struct soc
|
||||
return ntohs(s->sin_port);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::remoteIP() const {
|
||||
return getaddr(_sock, lwip_getpeername);
|
||||
IPAddress LwIPClient::remoteIP() const {
|
||||
return getaddr(fd(), lwip_getpeername);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::remoteIP(int fd) const {
|
||||
IPAddress LwIPClient::remoteIP(int fd) const {
|
||||
return getaddr(fd, lwip_getpeername);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::remotePort() const {
|
||||
return getport(_sock, lwip_getpeername);
|
||||
uint16_t LwIPClient::remotePort() const {
|
||||
return getport(fd(), lwip_getpeername);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::remotePort(int fd) const {
|
||||
uint16_t LwIPClient::remotePort(int fd) const {
|
||||
return getport(fd, lwip_getpeername);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::localIP() const {
|
||||
return getaddr(_sock, lwip_getsockname);
|
||||
IPAddress LwIPClient::localIP() const {
|
||||
return getaddr(fd(), lwip_getsockname);
|
||||
}
|
||||
|
||||
IPAddress WiFiClient::localIP(int fd) const {
|
||||
IPAddress LwIPClient::localIP(int fd) const {
|
||||
return getaddr(fd, lwip_getsockname);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::localPort() const {
|
||||
return getport(_sock, lwip_getsockname);
|
||||
uint16_t LwIPClient::localPort() const {
|
||||
return getport(fd(), lwip_getsockname);
|
||||
}
|
||||
|
||||
uint16_t WiFiClient::localPort(int fd) const {
|
||||
uint16_t LwIPClient::localPort(int fd) const {
|
||||
return getport(fd, lwip_getsockname);
|
||||
}
|
||||
|
||||
#endif
|
||||
56
arduino/libretuya/libraries/NetUtils/lwip/LwIPClient.h
Normal file
56
arduino/libretuya/libraries/NetUtils/lwip/LwIPClient.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-26. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <api/WiFi/WiFi.h>
|
||||
#include <api/WiFiClient.h>
|
||||
#include <lwip/LwIPRxBuffer.h>
|
||||
#include <memory>
|
||||
|
||||
class SocketHandle;
|
||||
|
||||
class LwIPClient : public IWiFiClient {
|
||||
private:
|
||||
bool _connected;
|
||||
std::shared_ptr<SocketHandle> _sock;
|
||||
std::shared_ptr<LwIPRxBuffer> _rxBuffer;
|
||||
|
||||
public:
|
||||
LwIPClient();
|
||||
LwIPClient(int sock);
|
||||
~LwIPClient();
|
||||
|
||||
int connect(IPAddress ip, uint16_t port);
|
||||
int connect(const char *host, uint16_t port);
|
||||
int connect(IPAddress ip, uint16_t port, int32_t timeout);
|
||||
int connect(const char *host, uint16_t port, int32_t timeout);
|
||||
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
size_t write(Stream &stream);
|
||||
|
||||
int available();
|
||||
int fd() const;
|
||||
int socket();
|
||||
int setTimeout(uint32_t seconds);
|
||||
|
||||
int read();
|
||||
int read(uint8_t *buf, size_t size);
|
||||
int peek();
|
||||
void flush();
|
||||
void stop();
|
||||
uint8_t connected();
|
||||
|
||||
LwIPClient &operator=(const LwIPClient &other);
|
||||
|
||||
IPAddress remoteIP() const;
|
||||
IPAddress remoteIP(int sock) const;
|
||||
uint16_t remotePort() const;
|
||||
uint16_t remotePort(int sock) const;
|
||||
IPAddress localIP() const;
|
||||
IPAddress localIP(int sock) const;
|
||||
uint16_t localPort() const;
|
||||
uint16_t localPort(int sock) const;
|
||||
|
||||
using Print::write;
|
||||
};
|
||||
@@ -1,26 +1,26 @@
|
||||
#ifdef LT_HAS_LWIP
|
||||
#if LT_HAS_LWIP
|
||||
|
||||
#include "LwIPRxBuffer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// disable #defines removing lwip_ prefix
|
||||
#undef LWIP_COMPAT_SOCKETS
|
||||
#define LWIP_COMPAT_SOCKETS 0
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include <lwip/sockets.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
size_t LwIPRxBuffer::r_available() {
|
||||
if (_sock < 0) {
|
||||
LT_D_WC("_sock < 0");
|
||||
return 0;
|
||||
}
|
||||
uint16_t count = 0;
|
||||
int res = lwip_ioctl(_sock, FIONREAD, &count);
|
||||
int count = 0; // must be of same size as in lwip_ioctl()
|
||||
int res = lwip_ioctl(_sock, FIONREAD, &count);
|
||||
if (res < 0) {
|
||||
LT_D_WC("lwip_ioctl()=%d, errno=%d", res, errno);
|
||||
_failed = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -31,7 +31,7 @@ size_t LwIPRxBuffer::fillBuffer() {
|
||||
if (!_buffer) {
|
||||
_buffer = (uint8_t *)malloc(_size);
|
||||
if (!_buffer) {
|
||||
printf("[e] Not enough memory to allocate buffer\r\n");
|
||||
LT_E("buffer alloc failed");
|
||||
_failed = true;
|
||||
return 0;
|
||||
}
|
||||
@@ -46,6 +46,7 @@ size_t LwIPRxBuffer::fillBuffer() {
|
||||
int res = lwip_recv(_sock, _buffer + _fill, _size - _fill, MSG_DONTWAIT);
|
||||
if (res < 0) {
|
||||
if (errno != EWOULDBLOCK) {
|
||||
LT_ERRNO();
|
||||
_failed = true;
|
||||
}
|
||||
return 0;
|
||||
@@ -1,14 +1,30 @@
|
||||
#include "WiFiServer.h"
|
||||
#include "WiFiPriv.h"
|
||||
/* Copyright (c) Kuba Szczodrzyński 2022-04-26. */
|
||||
|
||||
WiFiServer::WiFiServer(uint16_t port, uint8_t maxClients)
|
||||
: _sock(-1), _sockAccepted(-1), _port(port), _maxClients(maxClients), _active(false), _noDelay(false) {}
|
||||
#if LT_ARD_HAS_WIFI && LT_HAS_LWIP
|
||||
|
||||
WiFiServer::operator bool() {
|
||||
#include "LwIPServer.h"
|
||||
|
||||
// disable #defines removing lwip_ prefix
|
||||
#undef LWIP_COMPAT_SOCKETS
|
||||
#define LWIP_COMPAT_SOCKETS 0
|
||||
|
||||
extern "C" {
|
||||
#include <lwip/api.h>
|
||||
// #include <lwip/dns.h>
|
||||
#include <lwip/err.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <sys/time.h>
|
||||
}
|
||||
|
||||
LwIPServer::LwIPServer(uint32_t addr, uint16_t port, uint8_t maxClients)
|
||||
: _sock(-1), _sockAccepted(-1), _addr(addr), _port(port), _maxClients(maxClients), _active(false), _noDelay(false) {
|
||||
}
|
||||
|
||||
LwIPServer::operator bool() {
|
||||
return _active;
|
||||
}
|
||||
|
||||
bool WiFiServer::begin(uint16_t port, bool reuseAddr) {
|
||||
bool LwIPServer::begin(uint16_t port, bool reuseAddr) {
|
||||
if (_active)
|
||||
return true;
|
||||
if (port)
|
||||
@@ -25,7 +41,7 @@ bool WiFiServer::begin(uint16_t port, bool reuseAddr) {
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_addr.s_addr = _addr;
|
||||
addr.sin_port = htons(_port);
|
||||
|
||||
if (lwip_bind(_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
@@ -38,7 +54,8 @@ bool WiFiServer::begin(uint16_t port, bool reuseAddr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LT_I("Server running on :%hu", _port);
|
||||
uint8_t *addrB = (uint8_t *)&_addr;
|
||||
LT_I("Server running on %hhu.%hhu.%hhu.%hhu:%hu", addrB[0], addrB[1], addrB[2], addrB[3], _port);
|
||||
|
||||
lwip_fcntl(_sock, F_SETFL, O_NONBLOCK);
|
||||
_active = true;
|
||||
@@ -46,7 +63,7 @@ bool WiFiServer::begin(uint16_t port, bool reuseAddr) {
|
||||
_sockAccepted = -1;
|
||||
}
|
||||
|
||||
void WiFiServer::end() {
|
||||
void LwIPServer::end() {
|
||||
if (_sock == -1)
|
||||
return;
|
||||
lwip_close(_sock);
|
||||
@@ -54,7 +71,7 @@ void WiFiServer::end() {
|
||||
_active = -1;
|
||||
}
|
||||
|
||||
WiFiClient WiFiServer::accept() {
|
||||
WiFiClient LwIPServer::accept() {
|
||||
if (!_active)
|
||||
return WiFiClient();
|
||||
|
||||
@@ -92,7 +109,7 @@ WiFiClient WiFiServer::accept() {
|
||||
return WiFiClient();
|
||||
}
|
||||
|
||||
int WiFiServer::setTimeout(uint32_t seconds) {
|
||||
int LwIPServer::setTimeout(uint32_t seconds) {
|
||||
struct timeval tv;
|
||||
tv.tv_sec = seconds;
|
||||
tv.tv_usec = 0;
|
||||
@@ -101,15 +118,15 @@ int WiFiServer::setTimeout(uint32_t seconds) {
|
||||
return lwip_setsockopt(_sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
|
||||
}
|
||||
|
||||
void WiFiServer::setNoDelay(bool noDelay) {
|
||||
void LwIPServer::setNoDelay(bool noDelay) {
|
||||
_noDelay = noDelay;
|
||||
}
|
||||
|
||||
bool WiFiServer::getNoDelay() {
|
||||
bool LwIPServer::getNoDelay() {
|
||||
return _noDelay;
|
||||
}
|
||||
|
||||
bool WiFiServer::hasClient() {
|
||||
bool LwIPServer::hasClient() {
|
||||
if (_sockAccepted >= 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -121,3 +138,5 @@ bool WiFiServer::hasClient() {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user