mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-28 05:06:32 +00:00
commit
b6ae8182ce
18
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
18
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Problem report
|
||||
about: Create a report to help us improve
|
||||
name: Problem Report
|
||||
about: Create a Report to help us improve
|
||||
---
|
||||
|
||||
<!-- Thanks for reporting a problem for this project. READ THIS FIRST:
|
||||
@ -29,36 +29,34 @@ _Make sure your have performed every step and checked the applicable boxes befor
|
||||
|
||||
- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md)
|
||||
- [ ] Searched the problem in [issues](https://github.com/arendst/Tasmota/issues)
|
||||
- [ ] Searched the problem in [discussions](https://github.com/arendst/Tasmota/discussions)
|
||||
- [ ] Searched the problem in the [docs](https://tasmota.github.io/docs/FAQ)
|
||||
- [ ] Searched the problem in the [forum](https://groups.google.com/d/forum/sonoffusers)
|
||||
- [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4)
|
||||
- [ ] Device used (e.g., Sonoff Basic): _____
|
||||
- [ ] Tasmota binary firmware version number used: _____
|
||||
- [ ] Pre-compiled
|
||||
- [ ] Self-compiled
|
||||
- [ ] IDE / Compiler used: _____
|
||||
- [ ] Flashing tools used: _____
|
||||
- [ ] Provide the output of command: `Backlog Template; Module; GPIO 255`:
|
||||
```
|
||||
```lua
|
||||
Configuration output here:
|
||||
|
||||
|
||||
```
|
||||
- [ ] If using rules, provide the output of this command: `Backlog Rule1; Rule2; Rule3`:
|
||||
```
|
||||
```lua
|
||||
Rules output here:
|
||||
|
||||
|
||||
```
|
||||
- [ ] Provide the output of this command: `Status 0`:
|
||||
```
|
||||
```lua
|
||||
STATUS 0 output here:
|
||||
|
||||
|
||||
```
|
||||
- [ ] Provide the output of the Console log output when you experience your issue; if applicable:
|
||||
_(Please use_ `weblog 4` _for more debug information)_
|
||||
```
|
||||
- [ ] Set `weblog` to 4 and then, when you experience your issue, provide the output of the Console log:
|
||||
```lua
|
||||
Console output here:
|
||||
|
||||
|
||||
|
27
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
27
.github/ISSUE_TEMPLATE/Feature_request.md
vendored
@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
---
|
||||
|
||||
<!-- Thanks for suggesting an idea for this project. READ THIS FIRST:
|
||||
|
||||
Please take a few minutes to complete the requested information below. Our ability to provide assistance is greatly hampered without it. The details requested potentially affect which options to pursue. The small amount of time you spend completing the template will also help the volunteers providing the assistance to you to reduce the time required to help you.
|
||||
|
||||
DO NOT DELETE ANY TEXT from this template! Otherwise the issue will be auto-closed.
|
||||
-->
|
||||
|
||||
**Have you looked for this feature in other issues and in the docs?**
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
_A clear and concise description of what the problem is._
|
||||
|
||||
**Describe the solution you'd like**
|
||||
_A clear and concise description of what you want to happen._
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
_A clear and concise description of any alternative solutions or features you've considered._
|
||||
|
||||
**Additional context**
|
||||
_Add any other context or screenshots about the feature request here._
|
||||
|
||||
**(Please, remember to close the issue when the problem has been addressed)**
|
7
.github/ISSUE_TEMPLATE/config.yml
vendored
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -2,7 +2,10 @@ blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Tasmota Docs
|
||||
url: https://tasmota.github.io/docs
|
||||
about: All the information related to Tasmota
|
||||
- name: Tasmota Support Chat
|
||||
about: All the information related to Tasmota.
|
||||
- name: Tasmota Discussions and Support
|
||||
url: https://github.com/arendst/Tasmota/discussions
|
||||
about: Tasmota usage Questions, Feature Requests and Projects.
|
||||
- name: Tasmota Users Chat
|
||||
url: https://discord.gg/Ks2Kzd4
|
||||
about: Chat for feedback, questions and troubleshooting.
|
||||
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -7,7 +7,7 @@
|
||||
- [ ] Only relevant files were touched
|
||||
- [ ] Only one feature/fix was added per PR and the code change compiles without warnings
|
||||
- [ ] The code change is tested and works on Tasmota core ESP8266 V.2.7.4.9
|
||||
- [ ] The code change is tested and works on Tasmota core ESP32 V.1.0.4.2
|
||||
- [ ] The code change is tested and works on Tasmota core ESP32 V.1.0.5-rc4
|
||||
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
|
||||
|
||||
_NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_
|
||||
|
16
.github/issue-close-app.yml
vendored
16
.github/issue-close-app.yml
vendored
@ -5,7 +5,7 @@
|
||||
|
||||
# Comment that will be sent if an issue is judged to be closed.
|
||||
comment: >-
|
||||
This issue has been automatically closed because the issue template is missing or incomplete.
|
||||
This issue has been automatically closed because the PROBLEM REPORT TEMPLATE is missing or incomplete.
|
||||
|
||||
Filling the template is required so standard questions don't need to be asked again each time.
|
||||
Our ability to provide assistance is greatly hampered if few minutes are not taken to complete the issue template
|
||||
@ -13,19 +13,17 @@ comment: >-
|
||||
of time you will spend completing the template will also help the volunteers, providing assistance to you, to reduce
|
||||
the time required to help you.
|
||||
|
||||
Please, could you be so kind on completing the [issue template](https://github.com/arendst/Tasmota/issues/new/choose) in order to have more information so as to properly help you?
|
||||
Please, could you be so kind on completing the [PROBLEM REPORT TEMPLATE](https://github.com/arendst/Tasmota/issues/new/choose) in order to have more information so as to properly help you?
|
||||
|
||||
Thank you for taking the time to report, hopefully it can be resolved soon.
|
||||
|
||||
[Wiki](https://tasmota.github.io/docs/) for more information.
|
||||
[Docs](https://tasmota.github.io/docs/) for more information.
|
||||
|
||||
[Chat](https://discord.gg/Ks2Kzd4) for more user experience.
|
||||
[Discussions](https://github.com/arendst/Tasmota/discussions) for Questions, Feature Requests and Projects.
|
||||
|
||||
[Community](https://groups.google.com/d/forum/sonoffusers) for forum.
|
||||
|
||||
[Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md)
|
||||
|
||||
[Contributing Guideline and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md)
|
||||
[Chat](https://discord.gg/Ks2Kzd4) for more users experience.
|
||||
|
||||
Please check the [Code of Conduct](https://github.com/arendst/Tasmota/blob/development/CODE_OF_CONDUCT.md) and the [Contributing Guideline and Policy](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md)
|
||||
|
||||
issueConfigs:
|
||||
# There can be several configs for different kind of issues.
|
||||
|
26
CHANGELOG.md
26
CHANGELOG.md
@ -3,7 +3,21 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased] - Development
|
||||
|
||||
## [9.1.0.2]
|
||||
## [9.2.0.1]
|
||||
### Added
|
||||
- Milliseconds to console output (#10152)
|
||||
- Support for P9813 RGB Led MOSFET controller (#10104)
|
||||
|
||||
### Fixed
|
||||
- Redesign syslog and mqttlog using log buffer (#10164)
|
||||
- Shelly Dimmer power on state (#10154, #10182)
|
||||
|
||||
## [Released]
|
||||
|
||||
## [9.2.0] 20201216
|
||||
- Release Julie
|
||||
|
||||
## [9.1.0.2] 20201216
|
||||
### Added
|
||||
- KNX read reply for Power (#9236, #9891)
|
||||
- Zigbee persistence of device/sensor data in EEPROM (only ZBBridge)
|
||||
@ -16,6 +30,9 @@ All notable changes to this project will be documented in this file.
|
||||
- Zigbee better support for Tuya Protocol (#10074)
|
||||
- Support for SPI connected MFRC522 13.56MHz rfid card reader (#9916)
|
||||
- Letsencrypt R3 in addition to X3 CA (#10086)
|
||||
- Zigbee add visual map of network
|
||||
- Command ``SetOption117 1`` for light fading to be fixed duration instead of fixed slew rate (#10109)
|
||||
- Support ESP32 SPIFFS for internal use
|
||||
|
||||
### Breaking Changed
|
||||
- KNX DPT9 (16-bit float) to DPT14 (32-bit float) by Adrian Scillato (#9811, #9888)
|
||||
@ -38,6 +55,11 @@ All notable changes to this project will be documented in this file.
|
||||
- Backlog timing wraparound (#9995)
|
||||
- First LED in addressable string does not fade when using scheme (#10088)
|
||||
- Improved Opentherm error handling (#10055)
|
||||
- Platformio compiler option `no target align` removed fixing hardware watchdog exceptions
|
||||
- Shutter motordelay stop issue (#10033)
|
||||
- Shutter fix overflow on runtime over 100 seconds (#9800)
|
||||
- ESP32 CC2530 heap corruption (#10121)
|
||||
- ESP32 Analog input div10 rule trigger (#10149)
|
||||
|
||||
### Removed
|
||||
- PN532 define USE_PN532_CAUSE_EVENTS replaced by generic rule trigger `on pn532#uid=`
|
||||
@ -71,8 +93,6 @@ All notable changes to this project will be documented in this file.
|
||||
### Removed
|
||||
- Version compatibility check
|
||||
|
||||
## [Released]
|
||||
|
||||
## [9.1.0] 20201105
|
||||
- Release Imogen
|
||||
|
||||
|
@ -18,7 +18,7 @@ See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/tasmota/C
|
||||
|
||||
## Development
|
||||
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](http://ota.tasmota.com/tasmota/)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22)
|
||||
|
22
README.md
22
README.md
@ -21,7 +21,7 @@ In addition to the [release webpage](https://github.com/arendst/Tasmota/releases
|
||||
|
||||
## Development
|
||||
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](http://ota.tasmota.com/tasmota/)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22)
|
||||
@ -97,24 +97,18 @@ If you're looking for support on **Tasmota** there are some options available:
|
||||
|
||||
### Support's Community
|
||||
|
||||
* [Tasmota Forum](https://groups.google.com/d/forum/sonoffusers): For usage and discussions.
|
||||
* [Tasmota Support Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community.
|
||||
* [Tasmota Discussions](https://github.com/arendst/Tasmota/discussions): For Tasmota usage questions, Feature Requests and Projects.
|
||||
* [Tasmota Users Chat](https://discord.gg/Ks2Kzd4): For support, troubleshooting and general questions. You have better chances to get fast answers from members of the Tasmota Community.
|
||||
* [Search in Issues](https://github.com/arendst/Tasmota/issues): You might find an answer to your question by searching current or closed issues.
|
||||
|
||||
### Developers' Community
|
||||
|
||||
* [Bug Report](https://github.com/arendst/Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software.
|
||||
* [Feature Request](https://github.com/arendst/Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software.
|
||||
* [Troubleshooting](https://github.com/arendst/Tasmota/issues/new?template=Custom.md): As a last resort, you can open new *Troubleshooting* issue on GitHub if the solution could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer.
|
||||
* [Issue a question](https://github.com/arendst/Tasmota/issues/new/choose): As a last resort, you can open a new *Question* issue on GitHub if the answer could not be found using the other channels. Just remember: the more info you provide the more chances you'll have to get an accurate answer.
|
||||
* [Software Problem Report](https://github.com/arendst/Tasmota/issues/new?template=Bug_report.md): For reporting problems of Tasmota Software.
|
||||
|
||||
## Contribute
|
||||
|
||||
You can contribute to Tasmota by
|
||||
- providing Pull Requests (Features, Proof of Concepts, Language files or Fixes)
|
||||
- testing new released features and report issues
|
||||
- donating to acquire hardware for testing and implementing or out of gratitude
|
||||
- contributing missing [documentation](https://tasmota.github.io/docs) for features and devices
|
||||
- Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes)
|
||||
- Testing new released features and report issues
|
||||
- Donating to acquire hardware for testing and implementing or out of gratitude
|
||||
- Contributing missing [documentation](https://tasmota.github.io/docs) for features and devices
|
||||
|
||||
[](https://paypal.me/tasmota)
|
||||
|
||||
|
@ -30,7 +30,7 @@ Support of Core versions before 2.7.1 has been removed.
|
||||
|
||||
## Support of TLS
|
||||
|
||||
To save resources when TLS is enabled mDNS needs to be disabled. In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. Read [full documentation](https://tasmota.github.io/docs/AWS-IoT)
|
||||
In addition to TLS using fingerprints now also user supplied CA certs and AWS IoT is supported. Read [full documentation](https://tasmota.github.io/docs/AWS-IoT)
|
||||
|
||||
## Initial configuration tools
|
||||
|
||||
@ -56,56 +56,11 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
|
||||
|
||||
[Complete list](BUILDS.md) of available feature and sensors.
|
||||
|
||||
## Changelog v9.1.0.2
|
||||
## Changelog v9.2.0.1
|
||||
### Added
|
||||
- Command ``SetOption115 1`` to enable ESP32 MiBle
|
||||
- Command ``SetOption116 1`` to disable auto-query of zigbee light devices (avoids network storms with large groups)
|
||||
- Command ``RfProtocol`` to control RcSwitch receive protocols by BBBits (#10063)
|
||||
- Commands ``TuyaRGB``, ``TuyaEnum`` and ``TuyaEnumList`` (#9769)
|
||||
- Zigbee command ``ZbInfo`` and prepare support for EEPROM
|
||||
- Zigbee command ``ZbLeave`` to unpair a device
|
||||
- Zigbee support for Mi Door and Contact (#9759)
|
||||
- Zigbee alarm persistence (#9785)
|
||||
- Zigbee persistence of device/sensor data in EEPROM (only ZBBridge)
|
||||
- Zigbee better support for Tuya Protocol (#10074)
|
||||
- TyuaMcu update 2/3 by Federico Leoni (#10004)
|
||||
- Support for additional EZO sensors by Christopher Tremblay
|
||||
- Support for AS608 optical and R503 capacitive fingerprint sensor
|
||||
- Support for Shelly Dimmer 1 and 2 by James Turton (#9854)
|
||||
- Support for common anode sevenseg displays by adding ``#define USE_DISPLAY_SEVENSEG_COMMON_ANODE`` by Ken Sanislo (#9963)
|
||||
- Support for multiple WeMo devices by Magic73 (#9208)
|
||||
- Support for SPI connected MFRC522 13.56MHz rfid card reader (#9916)
|
||||
- KNX read reply for Power (#9236, #9891)
|
||||
- Fallback NTP server from x.pool.ntp.org if no ntpservers are configured
|
||||
- Optional CCloader support for CC25xx Zigbee or CC26xx BLE by Christian Baars (#9970)
|
||||
- Letsencrypt R3 in addition to X3 CA (#10086)
|
||||
|
||||
### Breaking Changed
|
||||
- KNX DPT9 (16-bit float) to DPT14 (32-bit float) by Adrian Scillato (#9811, #9888)
|
||||
|
||||
### Changed
|
||||
- Core library from v2.7.4.5 to v2.7.4.9
|
||||
- IRremoteESP8266 library from v2.7.12 to v2.7.13
|
||||
- Shelly Dimmer 1 and 2 stm32 firmware from v51.4 to v51.5
|
||||
- mDNS has been disabled from all pre-compiled binaries to allow new features
|
||||
- Platformio compiler option `no target align` enabled (#9749)
|
||||
- Sonoff L1 color up scaling and color margin detection (#9545)
|
||||
- MQTT Wifi connection timeout from 5000 to 200 mSec (#9886)
|
||||
- Force bigger Thunk Stack if 4K RSA even without EC ciphers (#10075)
|
||||
- Milliseconds to console output (#10152)
|
||||
- Support for P9813 RGB Led MOSFET controller (#10104)
|
||||
|
||||
### Fixed
|
||||
- Command ``gpio`` using non-indexed functions regression from v9.1.0 (#9962)
|
||||
- NTP fallback server functionality (#9739)
|
||||
- Telegram group chatid not supported (#9831)
|
||||
- KNX buttons, switches and sensors detection regression from v9.1.0 (#9811)
|
||||
- KNX ESP32 UDP mulicastpackage (#9811)
|
||||
- GUI MqttUser and MqttPassword updates when TLS is compiled in (#9825)
|
||||
- ESP32 TasmotaClient firmware upgrade (#9218)
|
||||
- Reset to defaults after 6 hours of DeepSleep (#9993)
|
||||
- Backlog timing wraparound (#9995)
|
||||
- First LED in addressable string does not fade when using scheme (#10088)
|
||||
- Improved Opentherm error handling (#10055)
|
||||
|
||||
### Removed
|
||||
- Version compatibility check
|
||||
- PN532 define USE_PN532_CAUSE_EVENTS replaced by generic rule trigger `on pn532#uid=`
|
||||
- Redesign syslog and mqttlog using log buffer (#10164)
|
||||
- Shelly Dimmer power on state (#10154, #10182)
|
||||
|
@ -399,6 +399,7 @@ void json_unescape(char* string) {
|
||||
c = string[++i];
|
||||
switch (c) {
|
||||
case 0:
|
||||
string[outlength++] = 0;
|
||||
return; // end of stream
|
||||
case '\"':
|
||||
case '/':
|
||||
@ -427,7 +428,10 @@ void json_unescape(char* string) {
|
||||
uint32_t hexval = 0;
|
||||
for (uint32_t j = 0; j < 4; ++j) {
|
||||
char val = string[++i];
|
||||
if (0 == val) { return; } // we reached end of string
|
||||
if (0 == val) {
|
||||
string[outlength++] = 0;
|
||||
return; // we reached end of string
|
||||
}
|
||||
uint32_t uival = 0;
|
||||
if ((val >= 'a') && (val <= 'f'))
|
||||
uival = 10 + (val - 'a');
|
||||
@ -450,4 +454,5 @@ void json_unescape(char* string) {
|
||||
string[outlength++] = c;
|
||||
}
|
||||
}
|
||||
string[outlength++] = 0;
|
||||
}
|
@ -60,6 +60,15 @@
|
||||
#define ILI9341_2_HWSPI
|
||||
#endif
|
||||
|
||||
#if defined (ILI9341_2_HWSPI)
|
||||
#define SPI_BEGIN_TRANSACTION() if (_hwspi) spi2->beginTransaction(sspi2)
|
||||
#define SPI_END_TRANSACTION() if (_hwspi) spi2->endTransaction()
|
||||
#else
|
||||
#define SPI_BEGIN_TRANSACTION() (void)
|
||||
#define SPI_END_TRANSACTION() (void)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
const uint16_t ili9341_2_colors[]={ILI9341_2_BLACK,ILI9341_2_WHITE,ILI9341_2_RED,ILI9341_2_GREEN,ILI9341_2_BLUE,ILI9341_2_CYAN,ILI9341_2_MAGENTA,\
|
||||
ILI9341_2_YELLOW,ILI9341_2_NAVY,ILI9341_2_DARKGREEN,ILI9341_2_DARKCYAN,ILI9341_2_MAROON,ILI9341_2_PURPLE,ILI9341_2_OLIVE,\
|
||||
@ -99,6 +108,32 @@ static const uint8_t PROGMEM ili9341_2_initcmd[] = {
|
||||
0x00 // End of list
|
||||
};
|
||||
|
||||
static const uint8_t PROGMEM ili9342_initcmd[] = {
|
||||
0xEF, 3, 0x03, 0x80, 0x02,
|
||||
0xCF, 3, 0x00, 0xC1, 0x30,
|
||||
0xED, 4, 0x64, 0x03, 0x12, 0x81,
|
||||
0xE8, 3, 0x85, 0x00, 0x78,
|
||||
0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02,
|
||||
0xF7, 1, 0x20,
|
||||
0xEA, 2, 0x00, 0x00,
|
||||
ILI9341_2_PWCTR1 , 1, 0x23, // Power control VRH[5:0]
|
||||
ILI9341_2_PWCTR2 , 1, 0x10, // Power control SAP[2:0];BT[3:0]
|
||||
ILI9341_2_VMCTR1 , 2, 0x2B, 0x2B, // 0x3e, 0x28, // VCM control
|
||||
ILI9341_2_VMCTR2 , 1, 0xC0, // VCM control2
|
||||
ILI9341_2_MADCTL , 1, 0x48, // Memory Access Control
|
||||
ILI9341_2_VSCRSADD, 1, 0x00, // Vertical scroll zero
|
||||
ILI9341_2_PIXFMT , 1, 0x55,
|
||||
ILI9341_2_FRMCTR1 , 2, 0x00, 0x1B,
|
||||
ILI9341_2_DFUNCTR , 3, 0x08, 0x82, 0x27, // Display Function Control
|
||||
0xF2, 1, 0x00, // 3Gamma Function Disable
|
||||
ILI9341_2_GAMMASET , 1, 0x01, // Gamma curve selected
|
||||
ILI9341_2_GMCTRP1 , 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00,
|
||||
ILI9341_2_GMCTRN1 , 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F,
|
||||
ILI9341_2_INVON , 0x80,
|
||||
ILI9341_2_SLPOUT , 0x80, // Exit Sleep
|
||||
ILI9341_2_DISPON , 0x80, // Display on
|
||||
0x00 // End of list
|
||||
};
|
||||
|
||||
ILI9341_2::ILI9341_2(int8_t cs, int8_t mosi, int8_t miso, int8_t sclk, int8_t res, int8_t dc, int8_t bp) : Renderer(ILI9341_2_TFTWIDTH, ILI9341_2_TFTHEIGHT) {
|
||||
_cs = cs;
|
||||
@ -108,7 +143,16 @@ ILI9341_2::ILI9341_2(int8_t cs, int8_t mosi, int8_t miso, int8_t sclk, int8_t re
|
||||
_res = res;
|
||||
_dc = dc;
|
||||
_bp = bp;
|
||||
_hwspi = 0;
|
||||
_hwspi = 1;
|
||||
}
|
||||
|
||||
// special init for ILI9342
|
||||
ILI9341_2::ILI9341_2(int8_t cs, int8_t res, int8_t dc, int8_t bp) : Renderer(ILI9341_2_TFTWIDTH, ILI9341_2_TFTHEIGHT) {
|
||||
_cs = cs;
|
||||
_res = res;
|
||||
_dc = dc;
|
||||
_bp = bp;
|
||||
_hwspi = 2;
|
||||
}
|
||||
|
||||
#define ILI9341_2_CS_LOW digitalWrite( _cs, LOW);
|
||||
@ -128,12 +172,25 @@ void ILI9341_2::writecmd(uint8_t d) {
|
||||
void ILI9341_2::init(uint16_t width, uint16_t height) {
|
||||
//sspi2 = SPISettings(2500000, MSBFIRST, SPI_MODE3);
|
||||
|
||||
if (_hwspi==2) {
|
||||
iwidth=ILI9341_2_TFTWIDTH;
|
||||
iheight=ILI9341_2_TFTHEIGHT;
|
||||
} else {
|
||||
iwidth=ILI9341_2_TFTHEIGHT;
|
||||
iheight=ILI9341_2_TFTWIDTH;
|
||||
}
|
||||
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2 = new SPIClass(HSPI);
|
||||
spi2->setDataMode(SPI_MODE3);
|
||||
spi2->setBitOrder(MSBFIRST);
|
||||
spi2->setFrequency(40000000);
|
||||
spi2->begin(_sclk, _miso, _mosi, -1);
|
||||
|
||||
sspi2 = SPISettings(40000000, MSBFIRST, SPI_MODE0);
|
||||
|
||||
if (_hwspi==2) {
|
||||
spi2=&SPI;
|
||||
} else {
|
||||
spi2 = new SPIClass(HSPI);
|
||||
spi2->begin(_sclk, _miso, _mosi, -1);
|
||||
}
|
||||
|
||||
#else
|
||||
pinMode(_mosi, OUTPUT);
|
||||
digitalWrite(_mosi,HIGH);
|
||||
@ -144,13 +201,31 @@ void ILI9341_2::init(uint16_t width, uint16_t height) {
|
||||
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs,HIGH);
|
||||
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc,HIGH);
|
||||
pinMode(_bp, OUTPUT);
|
||||
digitalWrite(_bp,HIGH);
|
||||
pinMode(_res, OUTPUT);
|
||||
digitalWrite(_res,HIGH);
|
||||
|
||||
if (_bp>=0) {
|
||||
pinMode(_bp, OUTPUT);
|
||||
digitalWrite(_bp,HIGH);
|
||||
}
|
||||
|
||||
if (_res>=0) {
|
||||
pinMode(_res, OUTPUT);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(_res, LOW);
|
||||
delay(100);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(200);
|
||||
} else {
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_SWRESET); // software reset
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
delay(150);
|
||||
}
|
||||
|
||||
if (_bp>=0) {
|
||||
#ifdef ILI9341_2_DIMMER
|
||||
@ -162,16 +237,16 @@ void ILI9341_2::init(uint16_t width, uint16_t height) {
|
||||
#endif
|
||||
}
|
||||
|
||||
pinMode(_res, OUTPUT);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(_res, LOW);
|
||||
delay(100);
|
||||
digitalWrite(_res, HIGH);
|
||||
delay(200);
|
||||
|
||||
uint8_t cmd, x, numArgs;
|
||||
const uint8_t *addr = ili9341_2_initcmd;
|
||||
const uint8_t *addr;
|
||||
|
||||
if (_hwspi<2) {
|
||||
addr = ili9341_2_initcmd;
|
||||
} else {
|
||||
addr = ili9342_initcmd;
|
||||
}
|
||||
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
while ((cmd = pgm_read_byte(addr++)) > 0) {
|
||||
ILI9341_2_CS_LOW
|
||||
@ -188,11 +263,15 @@ void ILI9341_2::init(uint16_t width, uint16_t height) {
|
||||
ILI9341_2_CS_HIGH
|
||||
if(x & 0x80) delay(120);
|
||||
}
|
||||
SPI_END_TRANSACTION();
|
||||
|
||||
// endWrite();
|
||||
}
|
||||
|
||||
void ILI9341_2::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
// SPI_BEGIN_TRANSACTION();
|
||||
// writecmd(ILI9341_2_INVOFF);
|
||||
// SPI_END_TRANSACTION();
|
||||
setRotation(rot);
|
||||
setTextFont(font&3);
|
||||
setTextSize(size&7);
|
||||
@ -201,9 +280,37 @@ void ILI9341_2::DisplayInit(int8_t p,int8_t size,int8_t rot,int8_t font) {
|
||||
fillScreen(ILI9341_2_BLACK);
|
||||
}
|
||||
|
||||
void ILI9341_2::setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||
void ILI9341_2::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
|
||||
if (!x0 && !y0 && !x1 && !y1) {
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
} else {
|
||||
ILI9341_2_CS_LOW
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
setAddrWindow_int(x0,y0,x1-x0,y1-y0);
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341_2::pushColors(uint16_t *data, uint8_t len, boolean first) {
|
||||
uint16_t color;
|
||||
|
||||
while (len--) {
|
||||
color = *data++;
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2->write16(color);
|
||||
#else
|
||||
spiwrite16(color);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ILI9341_2::setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||
uint32_t xa = ((uint32_t)x << 16) | (x+w-1);
|
||||
uint32_t ya = ((uint32_t)y << 16) | (y+h-1);
|
||||
|
||||
|
||||
writecmd(ILI9341_2_CASET); // Column addr set
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2->write32(xa);
|
||||
@ -218,6 +325,8 @@ void ILI9341_2::setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||
spiwrite32(ya);
|
||||
#endif
|
||||
writecmd(ILI9341_2_RAMWR); // write to RAM
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ILI9341_2::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
@ -227,7 +336,10 @@ void ILI9341_2::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x,y,1,1);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x,y,1,1);
|
||||
|
||||
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
spi2->write16(color);
|
||||
@ -236,39 +348,80 @@ void ILI9341_2::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
#endif
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
|
||||
void ILI9341_2::setRotation(uint8_t m) {
|
||||
|
||||
if (_hwspi<2) {
|
||||
rotation = m % 4; // can't be higher than 3
|
||||
switch (rotation) {
|
||||
case 0:
|
||||
m = (MADCTL_2_MX | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTWIDTH;
|
||||
_height = ILI9341_2_TFTHEIGHT;
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 1:
|
||||
m = (MADCTL_2_MV | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTHEIGHT;
|
||||
_height = ILI9341_2_TFTWIDTH;
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
case 2:
|
||||
m = (MADCTL_2_MY | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTWIDTH;
|
||||
_height = ILI9341_2_TFTHEIGHT;
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 3:
|
||||
m = (MADCTL_2_MX | MADCTL_2_MY | MADCTL_2_MV | MADCTL_2_BGR);
|
||||
_width = ILI9341_2_TFTHEIGHT;
|
||||
_height = ILI9341_2_TFTWIDTH;
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
}
|
||||
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_MADCTL);
|
||||
spiwrite(m);
|
||||
ILI9341_2_CS_HIGH
|
||||
} else {
|
||||
|
||||
#define MADCTL_MY 0x80 ///< Bottom to top
|
||||
#define MADCTL_MX 0x40 ///< Right to left
|
||||
#define MADCTL_MV 0x20 ///< Reverse Mode
|
||||
#define MADCTL_ML 0x10 ///< LCD refresh Bottom to top
|
||||
#define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order
|
||||
#define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order
|
||||
#define MADCTL_MH 0x04 ///< LCD refresh right to left
|
||||
|
||||
rotation = m % 4; // can't be higher than 3
|
||||
switch (rotation) {
|
||||
case 0:
|
||||
m = (MADCTL_BGR);
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 1:
|
||||
m = (MADCTL_MV | MADCTL_BGR);
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
case 2:
|
||||
m = (MADCTL_MY | MADCTL_BGR);
|
||||
_width = iwidth;
|
||||
_height = iheight;
|
||||
break;
|
||||
case 3:
|
||||
m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_BGR);
|
||||
_width = iheight;
|
||||
_height = iwidth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_MADCTL);
|
||||
spiwrite(m);
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
|
||||
void ILI9341_2::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||
|
||||
// Rudimentary clipping
|
||||
@ -277,7 +430,10 @@ void ILI9341_2::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x, y, 1, h);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x, y, 1, h);
|
||||
|
||||
|
||||
while (h--) {
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
@ -289,6 +445,7 @@ void ILI9341_2::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void ILI9341_2::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
@ -299,7 +456,10 @@ void ILI9341_2::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x, y, w, 1);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x, y, w, 1);
|
||||
|
||||
|
||||
while (w--) {
|
||||
#ifdef ILI9341_2_HWSPI
|
||||
@ -310,6 +470,8 @@ void ILI9341_2::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
}
|
||||
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
void ILI9341_2::fillScreen(uint16_t color) {
|
||||
@ -326,7 +488,9 @@ void ILI9341_2::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t co
|
||||
|
||||
ILI9341_2_CS_LOW
|
||||
|
||||
setAddrWindow(x, y, w-1, h-1);
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
|
||||
setAddrWindow_int(x, y, w, h);
|
||||
|
||||
for (y=h; y>0; y--) {
|
||||
for (x=w; x>0; x--) {
|
||||
@ -338,11 +502,26 @@ void ILI9341_2::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t co
|
||||
}
|
||||
}
|
||||
ILI9341_2_CS_HIGH
|
||||
|
||||
SPI_END_TRANSACTION();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ili9342_bpwr(uint8_t on);
|
||||
|
||||
void ILI9341_2::DisplayOnff(int8_t on) {
|
||||
|
||||
if (_hwspi==2) {
|
||||
ili9342_bpwr(on);
|
||||
}
|
||||
|
||||
if (on) {
|
||||
writecmd(ILI9341_2_DISPON); //Display on
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_DISPON);
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
if (_bp>=0) {
|
||||
#ifdef ILI9341_2_DIMMER
|
||||
ledcWrite(ESP32_PWM_CHANNEL,dimmer);
|
||||
@ -351,7 +530,11 @@ void ILI9341_2::DisplayOnff(int8_t on) {
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
SPI_BEGIN_TRANSACTION();
|
||||
ILI9341_2_CS_LOW
|
||||
writecmd(ILI9341_2_DISPOFF);
|
||||
ILI9341_2_CS_HIGH
|
||||
SPI_END_TRANSACTION();
|
||||
if (_bp>=0) {
|
||||
#ifdef ILI9341_2_DIMMER
|
||||
ledcWrite(ESP32_PWM_CHANNEL,0);
|
||||
@ -362,13 +545,21 @@ void ILI9341_2::DisplayOnff(int8_t on) {
|
||||
}
|
||||
}
|
||||
|
||||
void ili9342_dimm(uint8_t dim);
|
||||
|
||||
// dimmer 0-100
|
||||
void ILI9341_2::dim(uint8_t dim) {
|
||||
dimmer = dim;
|
||||
if (dimmer>15) dimmer=15;
|
||||
dimmer=((float)dimmer/15.0)*255.0;
|
||||
#ifdef ESP32
|
||||
ledcWrite(ESP32_PWM_CHANNEL,dimmer);
|
||||
if (_bp>=0) {
|
||||
ledcWrite(ESP32_PWM_CHANNEL,dimmer);
|
||||
} else {
|
||||
if (_hwspi==2) {
|
||||
ili9342_dimm(dim);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <SPI.h>
|
||||
|
||||
#define ILI9341_2_TFTWIDTH 320
|
||||
#define ILI9341_2_TFTHEIGHT 480
|
||||
#define ILI9341_2_TFTHEIGHT 240
|
||||
|
||||
#define ILI9341_2_NOP 0x00 ///< No-op register
|
||||
#define ILI9341_2_SWRESET 0x01 ///< Software reset register
|
||||
@ -116,6 +116,7 @@ class ILI9341_2 : public Renderer {
|
||||
public:
|
||||
|
||||
ILI9341_2(int8_t cs, int8_t mosi, int8_t miso, int8_t sclk, int8_t res, int8_t dc, int8_t bp);
|
||||
ILI9341_2(int8_t cs, int8_t res, int8_t dc, int8_t bp);
|
||||
|
||||
void init(uint16_t width, uint16_t height);
|
||||
/*
|
||||
@ -148,7 +149,8 @@ class ILI9341_2 : public Renderer {
|
||||
SPIClass *spi2;
|
||||
SPISettings sspi2;
|
||||
void writecmd(uint8_t d);
|
||||
void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||
void setAddrWindow(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
|
||||
void setAddrWindow_int(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void DisplayOnff(int8_t on);
|
||||
void setRotation(uint8_t m);
|
||||
@ -158,7 +160,7 @@ class ILI9341_2 : public Renderer {
|
||||
void fillScreen(uint16_t color);
|
||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void dim(uint8_t dim);
|
||||
|
||||
void pushColors(uint16_t *data, uint8_t len, boolean first);
|
||||
|
||||
void spiwrite(uint8_t c);
|
||||
void spiwrite16(uint16_t c);
|
||||
@ -174,6 +176,8 @@ class ILI9341_2 : public Renderer {
|
||||
int8_t _dc;
|
||||
int8_t _bp;
|
||||
int8_t _hwspi;
|
||||
uint16_t iwidth;
|
||||
uint16_t iheight;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
614
lib/libesp32/CORE2_Library/AXP192.cpp
Executable file
614
lib/libesp32/CORE2_Library/AXP192.cpp
Executable file
@ -0,0 +1,614 @@
|
||||
#include "AXP192.h"
|
||||
|
||||
//#define AXP192_DEBUG
|
||||
|
||||
AXP192::AXP192()
|
||||
{
|
||||
}
|
||||
|
||||
void AXP192::begin(void)
|
||||
{
|
||||
|
||||
Wire1.begin(21, 22);
|
||||
Wire1.setClock(400000);
|
||||
|
||||
//AXP192 30H
|
||||
Write1Byte(0x30, (Read8bit(0x30) & 0x04) | 0X02);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: vbus limit off\n");
|
||||
#endif
|
||||
|
||||
//AXP192 GPIO1:OD OUTPUT
|
||||
Write1Byte(0x92, Read8bit(0x92) & 0xf8);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: gpio1 init\n");
|
||||
#endif
|
||||
//AXP192 GPIO2:OD OUTPUT
|
||||
Write1Byte(0x93, Read8bit(0x93) & 0xf8);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: gpio2 init\n");
|
||||
#endif
|
||||
//AXP192 RTC CHG
|
||||
Write1Byte(0x35, (Read8bit(0x35) & 0x1c) | 0xa2);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: rtc battery charging enabled\n");
|
||||
#endif
|
||||
SetESPVoltage(3350);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: esp32 power voltage was set to 3.35v\n");
|
||||
#endif
|
||||
SetLcdVoltage(2800);
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: lcd backlight voltage was set to 2.80v\n");
|
||||
#endif
|
||||
SetLDOVoltage(2, 3300); //Periph power voltage preset (LCD_logic, SD card)
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: lcd logic and sdcard voltage preset to 3.3v\n");
|
||||
#endif
|
||||
SetLDOVoltage(3, 2000); //Vibrator power voltage preset
|
||||
#ifdef AXP192_DEBUG
|
||||
Serial.printf("axp: vibrator voltage preset to 2v\n");
|
||||
#endif
|
||||
|
||||
SetLDOEnable(2, true);
|
||||
SetDCDC3(true); // LCD backlight
|
||||
SetLed(true);
|
||||
|
||||
SetCHGCurrent(kCHG_100mA);
|
||||
//SetAxpPriphPower(1);
|
||||
//Serial.printf("axp: lcd_logic and sdcard power enabled\n\n");
|
||||
|
||||
//pinMode(39, INPUT_PULLUP);
|
||||
|
||||
//AXP192 GPIO4
|
||||
Write1Byte(0X95, (Read8bit(0x95) & 0x72) | 0X84);
|
||||
|
||||
Write1Byte(0X36, 0X4C);
|
||||
|
||||
Write1Byte(0x82,0xff);
|
||||
|
||||
SetLCDRSet(0);
|
||||
delay(100);
|
||||
SetLCDRSet(1);
|
||||
delay(100);
|
||||
// I2C_WriteByteDataAt(0X15,0XFE,0XFF);
|
||||
|
||||
// bus power mode_output
|
||||
SetBusPowerMode(0);
|
||||
}
|
||||
|
||||
void AXP192::Write1Byte(uint8_t Addr, uint8_t Data)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.write(Data);
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t AXP192::Read8bit(uint8_t Addr)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 1);
|
||||
return Wire1.read();
|
||||
}
|
||||
|
||||
uint16_t AXP192::Read12Bit(uint8_t Addr)
|
||||
{
|
||||
uint16_t Data = 0;
|
||||
uint8_t buf[2];
|
||||
ReadBuff(Addr, 2, buf);
|
||||
Data = ((buf[0] << 4) + buf[1]); //
|
||||
return Data;
|
||||
}
|
||||
|
||||
uint16_t AXP192::Read13Bit(uint8_t Addr)
|
||||
{
|
||||
uint16_t Data = 0;
|
||||
uint8_t buf[2];
|
||||
ReadBuff(Addr, 2, buf);
|
||||
Data = ((buf[0] << 5) + buf[1]); //
|
||||
return Data;
|
||||
}
|
||||
|
||||
uint16_t AXP192::Read16bit(uint8_t Addr)
|
||||
{
|
||||
uint16_t ReData = 0;
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 2);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
ReData <<= 8;
|
||||
ReData |= Wire1.read();
|
||||
}
|
||||
return ReData;
|
||||
}
|
||||
|
||||
uint32_t AXP192::Read24bit(uint8_t Addr)
|
||||
{
|
||||
uint32_t ReData = 0;
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 3);
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
ReData <<= 8;
|
||||
ReData |= Wire1.read();
|
||||
}
|
||||
return ReData;
|
||||
}
|
||||
|
||||
uint32_t AXP192::Read32bit(uint8_t Addr)
|
||||
{
|
||||
uint32_t ReData = 0;
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 2);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ReData <<= 8;
|
||||
ReData |= Wire1.read();
|
||||
}
|
||||
return ReData;
|
||||
}
|
||||
|
||||
void AXP192::ReadBuff(uint8_t Addr, uint8_t Size, uint8_t *Buff)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(Addr);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, (int)Size);
|
||||
for (int i = 0; i < Size; i++)
|
||||
{
|
||||
*(Buff + i) = Wire1.read();
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::ScreenBreath(uint8_t brightness)
|
||||
{
|
||||
if (brightness > 12)
|
||||
{
|
||||
brightness = 12;
|
||||
}
|
||||
uint8_t buf = Read8bit(0x28);
|
||||
Write1Byte(0x28, ((buf & 0x0f) | (brightness << 4)));
|
||||
}
|
||||
|
||||
bool AXP192::GetBatState()
|
||||
{
|
||||
if (Read8bit(0x01) | 0x20)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
//---------coulombcounter_from_here---------
|
||||
//enable: void EnableCoulombcounter(void);
|
||||
//disable: void DisableCOulombcounter(void);
|
||||
//stop: void StopCoulombcounter(void);
|
||||
//clear: void ClearCoulombcounter(void);
|
||||
//get charge data: uint32_t GetCoulombchargeData(void);
|
||||
//get discharge data: uint32_t GetCoulombdischargeData(void);
|
||||
//get coulomb val affter calculation: float GetCoulombData(void);
|
||||
//------------------------------------------
|
||||
void AXP192::EnableCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0x80);
|
||||
}
|
||||
|
||||
void AXP192::DisableCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0x00);
|
||||
}
|
||||
|
||||
void AXP192::StopCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0xC0);
|
||||
}
|
||||
|
||||
void AXP192::ClearCoulombcounter(void)
|
||||
{
|
||||
Write1Byte(0xB8, 0xA0);
|
||||
}
|
||||
|
||||
uint32_t AXP192::GetCoulombchargeData(void)
|
||||
{
|
||||
return Read32bit(0xB0);
|
||||
}
|
||||
|
||||
uint32_t AXP192::GetCoulombdischargeData(void)
|
||||
{
|
||||
return Read32bit(0xB4);
|
||||
}
|
||||
|
||||
float AXP192::GetCoulombData(void)
|
||||
{
|
||||
|
||||
uint32_t coin = 0;
|
||||
uint32_t coout = 0;
|
||||
|
||||
coin = GetCoulombchargeData();
|
||||
coout = GetCoulombdischargeData();
|
||||
|
||||
//c = 65536 * current_LSB * (coin - coout) / 3600 / ADC rate
|
||||
//Adc rate can be read from 84H ,change this variable if you change the ADC reate
|
||||
float ccc = 65536 * 0.5 * (coin - coout) / 3600.0 / 25.0;
|
||||
return ccc;
|
||||
}
|
||||
|
||||
// Cut all power, except for LDO1 (RTC)
|
||||
void AXP192::PowerOff(void)
|
||||
{
|
||||
Write1Byte(0x32, Read8bit(0x32) | 0b10000000);
|
||||
}
|
||||
|
||||
void AXP192::SetAdcState(bool state)
|
||||
{
|
||||
// Enable / Disable all ADCs
|
||||
Write1Byte(0x82, state ? 0xff : 0x00);
|
||||
}
|
||||
|
||||
void AXP192::PrepareToSleep(void)
|
||||
{
|
||||
// Disable ADCs
|
||||
SetAdcState(false);
|
||||
|
||||
// Turn LED off
|
||||
SetLed(false);
|
||||
|
||||
// Turn LCD backlight off
|
||||
SetDCDC3(false);
|
||||
}
|
||||
|
||||
void AXP192::RestoreFromLightSleep(void)
|
||||
{
|
||||
// Turn LCD backlight on
|
||||
SetDCDC3(true);
|
||||
|
||||
// Turn LED on
|
||||
SetLed(true);
|
||||
|
||||
// Enable ADCs
|
||||
SetAdcState(true);
|
||||
}
|
||||
|
||||
uint8_t AXP192::GetWarningLeve(void)
|
||||
{
|
||||
Wire1.beginTransmission(0x34);
|
||||
Wire1.write(0x47);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x34, 1);
|
||||
uint8_t buf = Wire1.read();
|
||||
return (buf & 0x01);
|
||||
}
|
||||
|
||||
// -- sleep
|
||||
void AXP192::DeepSleep(uint64_t time_in_us)
|
||||
{
|
||||
PrepareToSleep();
|
||||
|
||||
if (time_in_us > 0)
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(time_in_us);
|
||||
}
|
||||
else
|
||||
{
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
|
||||
}
|
||||
(time_in_us == 0) ? esp_deep_sleep_start() : esp_deep_sleep(time_in_us);
|
||||
|
||||
// Never reached - after deep sleep ESP32 restarts
|
||||
}
|
||||
|
||||
void AXP192::LightSleep(uint64_t time_in_us)
|
||||
{
|
||||
PrepareToSleep();
|
||||
|
||||
if (time_in_us > 0)
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(time_in_us);
|
||||
}
|
||||
else
|
||||
{
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
|
||||
}
|
||||
esp_light_sleep_start();
|
||||
|
||||
RestoreFromLightSleep();
|
||||
}
|
||||
|
||||
uint8_t AXP192::GetWarningLevel(void)
|
||||
{
|
||||
return Read8bit(0x47) & 0x01;
|
||||
}
|
||||
|
||||
float AXP192::GetBatVoltage()
|
||||
{
|
||||
float ADCLSB = 1.1 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x78);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetBatCurrent()
|
||||
{
|
||||
float ADCLSB = 0.5;
|
||||
uint16_t CurrentIn = Read13Bit(0x7A);
|
||||
uint16_t CurrentOut = Read13Bit(0x7C);
|
||||
return (CurrentIn - CurrentOut) * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVinVoltage()
|
||||
{
|
||||
float ADCLSB = 1.7 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x56);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVinCurrent()
|
||||
{
|
||||
float ADCLSB = 0.625;
|
||||
uint16_t ReData = Read12Bit(0x58);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVBusVoltage()
|
||||
{
|
||||
float ADCLSB = 1.7 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x5A);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetVBusCurrent()
|
||||
{
|
||||
float ADCLSB = 0.375;
|
||||
uint16_t ReData = Read12Bit(0x5C);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetTempInAXP192()
|
||||
{
|
||||
float ADCLSB = 0.1;
|
||||
const float OFFSET_DEG_C = -144.7;
|
||||
uint16_t ReData = Read12Bit(0x5E);
|
||||
return OFFSET_DEG_C + ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetBatPower()
|
||||
{
|
||||
float VoltageLSB = 1.1;
|
||||
float CurrentLCS = 0.5;
|
||||
uint32_t ReData = Read24bit(0x70);
|
||||
return VoltageLSB * CurrentLCS * ReData / 1000.0;
|
||||
}
|
||||
|
||||
float AXP192::GetBatChargeCurrent()
|
||||
{
|
||||
float ADCLSB = 0.5;
|
||||
uint16_t ReData = Read12Bit(0x7A);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
float AXP192::GetAPSVoltage()
|
||||
{
|
||||
float ADCLSB = 1.4 / 1000.0;
|
||||
uint16_t ReData = Read12Bit(0x7E);
|
||||
return ReData * ADCLSB;
|
||||
}
|
||||
|
||||
float AXP192::GetBatCoulombInput()
|
||||
{
|
||||
uint32_t ReData = Read32bit(0xB0);
|
||||
return ReData * 65536 * 0.5 / 3600 / 25.0;
|
||||
}
|
||||
|
||||
float AXP192::GetBatCoulombOut()
|
||||
{
|
||||
uint32_t ReData = Read32bit(0xB4);
|
||||
return ReData * 65536 * 0.5 / 3600 / 25.0;
|
||||
}
|
||||
|
||||
void AXP192::SetCoulombClear()
|
||||
{
|
||||
Write1Byte(0xB8, 0x20);
|
||||
}
|
||||
|
||||
void AXP192::SetLDO2(bool State)
|
||||
{
|
||||
uint8_t buf = Read8bit(0x12);
|
||||
if (State == true)
|
||||
buf = (1 << 2) | buf;
|
||||
else
|
||||
buf = ~(1 << 2) & buf;
|
||||
Write1Byte(0x12, buf);
|
||||
}
|
||||
|
||||
void AXP192::SetDCDC3(bool State)
|
||||
{
|
||||
uint8_t buf = Read8bit(0x12);
|
||||
if (State == true)
|
||||
buf = (1 << 1) | buf;
|
||||
else
|
||||
buf = ~(1 << 1) & buf;
|
||||
Write1Byte(0x12, buf);
|
||||
}
|
||||
|
||||
uint8_t AXP192::AXPInState()
|
||||
{
|
||||
return Read8bit(0x00);
|
||||
}
|
||||
bool AXP192::isACIN()
|
||||
{
|
||||
return ( Read8bit(0x00) & 0x80 ) ? true : false;
|
||||
}
|
||||
bool AXP192::isCharging()
|
||||
{
|
||||
return ( Read8bit(0x00) & 0x04 ) ? true : false;
|
||||
}
|
||||
bool AXP192::isVBUS()
|
||||
{
|
||||
return ( Read8bit(0x00) & 0x20 ) ? true : false;
|
||||
}
|
||||
|
||||
void AXP192::SetLDOVoltage(uint8_t number, uint16_t voltage)
|
||||
{
|
||||
voltage = (voltage > 3300) ? 15 : (voltage / 100) - 18;
|
||||
switch (number)
|
||||
{
|
||||
//uint8_t reg, data;
|
||||
case 2:
|
||||
Write1Byte(0x28, (Read8bit(0x28) & 0X0F) | (voltage << 4));
|
||||
break;
|
||||
case 3:
|
||||
Write1Byte(0x28, (Read8bit(0x28) & 0XF0) | voltage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetDCVoltage(uint8_t number, uint16_t voltage)
|
||||
{
|
||||
uint8_t addr;
|
||||
if (number > 2)
|
||||
return;
|
||||
voltage = (voltage < 700) ? 0 : (voltage - 700) / 25;
|
||||
switch (number)
|
||||
{
|
||||
case 0:
|
||||
addr = 0x26;
|
||||
break;
|
||||
case 1:
|
||||
addr = 0x25;
|
||||
break;
|
||||
case 2:
|
||||
addr = 0x27;
|
||||
break;
|
||||
}
|
||||
Write1Byte(addr, (Read8bit(addr) & 0X80) | (voltage & 0X7F));
|
||||
}
|
||||
|
||||
void AXP192::SetESPVoltage(uint16_t voltage)
|
||||
{
|
||||
if (voltage >= 3000 && voltage <= 3400)
|
||||
{
|
||||
SetDCVoltage(0, voltage);
|
||||
}
|
||||
}
|
||||
void AXP192::SetLcdVoltage(uint16_t voltage)
|
||||
{
|
||||
if (voltage >= 2500 && voltage <= 3300)
|
||||
{
|
||||
SetDCVoltage(2, voltage);
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetLDOEnable(uint8_t number, bool state)
|
||||
{
|
||||
uint8_t mark = 0x01;
|
||||
if ((number < 2) || (number > 3))
|
||||
return;
|
||||
|
||||
mark <<= number;
|
||||
if (state)
|
||||
{
|
||||
Write1Byte(0x12, (Read8bit(0x12) | mark));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write1Byte(0x12, (Read8bit(0x12) & (~mark)));
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetLCDRSet(bool state)
|
||||
{
|
||||
uint8_t reg_addr = 0x96;
|
||||
uint8_t gpio_bit = 0x02;
|
||||
uint8_t data;
|
||||
data = Read8bit(reg_addr);
|
||||
|
||||
if (state)
|
||||
{
|
||||
data |= gpio_bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
data &= ~gpio_bit;
|
||||
}
|
||||
|
||||
Write1Byte(reg_addr, data);
|
||||
}
|
||||
|
||||
void AXP192::SetBusPowerMode(uint8_t state)
|
||||
{
|
||||
uint8_t data;
|
||||
if (state == 0)
|
||||
{
|
||||
data = Read8bit(0x91);
|
||||
Write1Byte(0x91, (data & 0X0F) | 0XF0);
|
||||
|
||||
data = Read8bit(0x90);
|
||||
Write1Byte(0x90, (data & 0XF8) | 0X02); //set GPIO0 to LDO OUTPUT , pullup N_VBUSEN to disable supply from BUS_5V
|
||||
|
||||
data = Read8bit(0x91);
|
||||
|
||||
data = Read8bit(0x12); //read reg 0x12
|
||||
Write1Byte(0x12, data | 0x40); //set EXTEN to enable 5v boost
|
||||
}
|
||||
else
|
||||
{
|
||||
data = Read8bit(0x12); //read reg 0x10
|
||||
Write1Byte(0x12, data & 0XBF); //set EXTEN to disable 5v boost
|
||||
|
||||
//delay(2000);
|
||||
|
||||
data = Read8bit(0x90);
|
||||
Write1Byte(0x90, (data & 0xF8) | 0X01); //set GPIO0 to float , using enternal pulldown resistor to enable supply from BUS_5VS
|
||||
}
|
||||
}
|
||||
|
||||
void AXP192::SetLed(uint8_t state)
|
||||
{
|
||||
uint8_t reg_addr=0x94;
|
||||
uint8_t data;
|
||||
data=Read8bit(reg_addr);
|
||||
|
||||
if(state)
|
||||
{
|
||||
data=data&0XFD;
|
||||
}
|
||||
else
|
||||
{
|
||||
data|=0X02;
|
||||
}
|
||||
|
||||
Write1Byte(reg_addr,data);
|
||||
}
|
||||
|
||||
//set led state(GPIO high active,set 1 to enable amplifier)
|
||||
void AXP192::SetSpkEnable(uint8_t state)
|
||||
{
|
||||
uint8_t reg_addr=0x94;
|
||||
uint8_t gpio_bit=0x04;
|
||||
uint8_t data;
|
||||
data=Read8bit(reg_addr);
|
||||
|
||||
if(state)
|
||||
{
|
||||
data|=gpio_bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
data&=~gpio_bit;
|
||||
}
|
||||
|
||||
Write1Byte(reg_addr,data);
|
||||
}
|
||||
|
||||
void AXP192::SetCHGCurrent(uint8_t state)
|
||||
{
|
||||
uint8_t data = Read8bit(0x33);
|
||||
data &= 0xf0;
|
||||
data = data | ( state & 0x0f );
|
||||
Write1Byte(0x33,data);
|
||||
}
|
106
lib/libesp32/CORE2_Library/AXP192.h
Executable file
106
lib/libesp32/CORE2_Library/AXP192.h
Executable file
@ -0,0 +1,106 @@
|
||||
#ifndef __AXP192_H__
|
||||
#define __AXP192_H__
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#define SLEEP_MSEC(us) (((uint64_t)us) * 1000L)
|
||||
#define SLEEP_SEC(us) (((uint64_t)us) * 1000000L)
|
||||
#define SLEEP_MIN(us) (((uint64_t)us) * 60L * 1000000L)
|
||||
#define SLEEP_HR(us) (((uint64_t)us) * 60L * 60L * 1000000L)
|
||||
|
||||
#define AXP_ADDR 0X34
|
||||
|
||||
#define PowerOff(x) SetSleep(x)
|
||||
|
||||
class AXP192 {
|
||||
public:
|
||||
|
||||
enum CHGCurrent{
|
||||
kCHG_100mA = 0,
|
||||
kCHG_190mA,
|
||||
kCHG_280mA,
|
||||
kCHG_360mA,
|
||||
kCHG_450mA,
|
||||
kCHG_550mA,
|
||||
kCHG_630mA,
|
||||
kCHG_700mA,
|
||||
kCHG_780mA,
|
||||
kCHG_880mA,
|
||||
kCHG_960mA,
|
||||
kCHG_1000mA,
|
||||
kCHG_1080mA,
|
||||
kCHG_1160mA,
|
||||
kCHG_1240mA,
|
||||
kCHG_1320mA,
|
||||
};
|
||||
|
||||
AXP192();
|
||||
void begin(void);
|
||||
void ScreenBreath(uint8_t brightness);
|
||||
bool GetBatState();
|
||||
|
||||
void EnableCoulombcounter(void);
|
||||
void DisableCoulombcounter(void);
|
||||
void StopCoulombcounter(void);
|
||||
void ClearCoulombcounter(void);
|
||||
uint32_t GetCoulombchargeData(void);
|
||||
uint32_t GetCoulombdischargeData(void);
|
||||
float GetCoulombData(void);
|
||||
void PowerOff(void);
|
||||
void SetAdcState(bool state);
|
||||
// -- sleep
|
||||
void PrepareToSleep(void);
|
||||
void RestoreFromLightSleep(void);
|
||||
void DeepSleep(uint64_t time_in_us = 0);
|
||||
void LightSleep(uint64_t time_in_us = 0);
|
||||
uint8_t GetWarningLeve(void);
|
||||
|
||||
public:
|
||||
// void SetChargeVoltage( uint8_t );
|
||||
// void SetChargeCurrent( uint8_t );
|
||||
float GetBatVoltage();
|
||||
float GetBatCurrent();
|
||||
float GetVinVoltage();
|
||||
float GetVinCurrent();
|
||||
float GetVBusVoltage();
|
||||
float GetVBusCurrent();
|
||||
float GetTempInAXP192();
|
||||
float GetBatPower();
|
||||
float GetBatChargeCurrent();
|
||||
float GetAPSVoltage();
|
||||
float GetBatCoulombInput();
|
||||
float GetBatCoulombOut();
|
||||
uint8_t GetWarningLevel(void);
|
||||
void SetCoulombClear();
|
||||
void SetLDO2( bool State );
|
||||
void SetDCDC3( bool State );
|
||||
|
||||
uint8_t AXPInState();
|
||||
bool isACIN();
|
||||
bool isCharging();
|
||||
bool isVBUS();
|
||||
|
||||
void SetLDOVoltage(uint8_t number , uint16_t voltage);
|
||||
void SetDCVoltage(uint8_t number , uint16_t voltage);
|
||||
void SetESPVoltage(uint16_t voltage);
|
||||
void SetLcdVoltage(uint16_t voltage);
|
||||
void SetLDOEnable( uint8_t number ,bool state );
|
||||
void SetLCDRSet( bool state );
|
||||
void SetBusPowerMode( uint8_t state );
|
||||
void SetLed(uint8_t state);
|
||||
void SetSpkEnable(uint8_t state);
|
||||
void SetCHGCurrent(uint8_t state);
|
||||
|
||||
private:
|
||||
void Write1Byte( uint8_t Addr , uint8_t Data );
|
||||
uint8_t Read8bit( uint8_t Addr );
|
||||
uint16_t Read12Bit( uint8_t Addr);
|
||||
uint16_t Read13Bit( uint8_t Addr);
|
||||
uint16_t Read16bit( uint8_t Addr );
|
||||
uint32_t Read24bit( uint8_t Addr );
|
||||
uint32_t Read32bit( uint8_t Addr );
|
||||
void ReadBuff( uint8_t Addr , uint8_t Size , uint8_t *Buff );
|
||||
};
|
||||
|
||||
#endif
|
353
lib/libesp32/CORE2_Library/BM8563_RTC.cpp
Executable file
353
lib/libesp32/CORE2_Library/BM8563_RTC.cpp
Executable file
@ -0,0 +1,353 @@
|
||||
#include "BM8563_RTC.h"
|
||||
|
||||
BM8563_RTC::BM8563_RTC()
|
||||
{
|
||||
}
|
||||
|
||||
void BM8563_RTC::begin(void)
|
||||
{
|
||||
Wire1.begin(21, 22);
|
||||
WriteReg(0x00,0x00);
|
||||
WriteReg(0x01,0x00);
|
||||
WriteReg(0x0D,0x00);
|
||||
}
|
||||
|
||||
void BM8563_RTC::WriteReg(uint8_t reg, uint8_t data)
|
||||
{
|
||||
Wire1.beginTransmission(RTC_ADRESS);
|
||||
Wire1.write(reg);
|
||||
Wire1.write(data);
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t BM8563_RTC::ReadReg(uint8_t reg)
|
||||
{
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(reg);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 1);
|
||||
return Wire1.read();
|
||||
}
|
||||
|
||||
void BM8563_RTC::GetBm8563Time(void)
|
||||
{
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x02);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 7);
|
||||
while (Wire1.available())
|
||||
{
|
||||
|
||||
trdata[0] = Wire1.read();
|
||||
trdata[1] = Wire1.read();
|
||||
trdata[2] = Wire1.read();
|
||||
trdata[3] = Wire1.read();
|
||||
trdata[4] = Wire1.read();
|
||||
trdata[5] = Wire1.read();
|
||||
trdata[6] = Wire1.read();
|
||||
}
|
||||
|
||||
DataMask();
|
||||
Bcd2asc();
|
||||
Str2Time();
|
||||
}
|
||||
|
||||
void BM8563_RTC::Str2Time(void)
|
||||
{
|
||||
|
||||
Second = (asc[0] - 0x30) * 10 + asc[1] - 0x30;
|
||||
Minute = (asc[2] - 0x30) * 10 + asc[3] - 0x30;
|
||||
Hour = (asc[4] - 0x30) * 10 + asc[5] - 0x30;
|
||||
/*
|
||||
uint8_t Hour;
|
||||
uint8_t Week;
|
||||
uint8_t Day;
|
||||
uint8_t Month;
|
||||
uint8_t Year;
|
||||
*/
|
||||
}
|
||||
|
||||
void BM8563_RTC::DataMask()
|
||||
{
|
||||
|
||||
trdata[0] = trdata[0] & 0x7f; //秒
|
||||
trdata[1] = trdata[1] & 0x7f; //分
|
||||
trdata[2] = trdata[2] & 0x3f; //时
|
||||
|
||||
trdata[3] = trdata[3] & 0x3f; //日
|
||||
trdata[4] = trdata[4] & 0x07; //星期
|
||||
trdata[5] = trdata[5] & 0x1f; //月
|
||||
|
||||
trdata[6] = trdata[6] & 0xff; //年
|
||||
}
|
||||
/********************************************************************
|
||||
函 数 名: void Bcd2asc(void)
|
||||
功 能: bcd 码转换成 asc 码,供Lcd显示用
|
||||
说 明:
|
||||
调 用:
|
||||
入口参数:
|
||||
返 回 值:无
|
||||
***********************************************************************/
|
||||
void BM8563_RTC::Bcd2asc(void)
|
||||
{
|
||||
uint8_t i, j;
|
||||
for (j = 0, i = 0; i < 7; i++)
|
||||
{
|
||||
asc[j++] = (trdata[i] & 0xf0) >> 4 | 0x30; /*格式为: 秒 分 时 日 月 星期 年 */
|
||||
asc[j++] = (trdata[i] & 0x0f) | 0x30;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t BM8563_RTC::Bcd2ToByte(uint8_t Value)
|
||||
{
|
||||
uint8_t tmp = 0;
|
||||
tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10;
|
||||
return (tmp + (Value & (uint8_t)0x0F));
|
||||
}
|
||||
|
||||
uint8_t BM8563_RTC::ByteToBcd2(uint8_t Value)
|
||||
{
|
||||
uint8_t bcdhigh = 0;
|
||||
|
||||
while (Value >= 10)
|
||||
{
|
||||
bcdhigh++;
|
||||
Value -= 10;
|
||||
}
|
||||
|
||||
return ((uint8_t)(bcdhigh << 4) | Value);
|
||||
}
|
||||
|
||||
void BM8563_RTC::GetTime(RTC_TimeTypeDef *RTC_TimeStruct)
|
||||
{
|
||||
|
||||
//if()
|
||||
uint8_t buf[3] = {0};
|
||||
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x02);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 3);
|
||||
|
||||
while (Wire1.available())
|
||||
{
|
||||
|
||||
buf[0] = Wire1.read();
|
||||
buf[1] = Wire1.read();
|
||||
buf[2] = Wire1.read();
|
||||
}
|
||||
|
||||
RTC_TimeStruct->Seconds = Bcd2ToByte(buf[0] & 0x7f); //秒
|
||||
RTC_TimeStruct->Minutes = Bcd2ToByte(buf[1] & 0x7f); //分
|
||||
RTC_TimeStruct->Hours = Bcd2ToByte(buf[2] & 0x3f); //时
|
||||
}
|
||||
|
||||
void BM8563_RTC::SetTime(RTC_TimeTypeDef *RTC_TimeStruct)
|
||||
{
|
||||
|
||||
if (RTC_TimeStruct == NULL)
|
||||
return;
|
||||
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x02);
|
||||
Wire1.write(ByteToBcd2(RTC_TimeStruct->Seconds));
|
||||
Wire1.write(ByteToBcd2(RTC_TimeStruct->Minutes));
|
||||
Wire1.write(ByteToBcd2(RTC_TimeStruct->Hours));
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
void BM8563_RTC::GetDate(RTC_DateTypeDef *RTC_DateStruct)
|
||||
{
|
||||
|
||||
uint8_t buf[4] = {0};
|
||||
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x05);
|
||||
Wire1.endTransmission();
|
||||
Wire1.requestFrom(0x51, 4);
|
||||
|
||||
while (Wire1.available())
|
||||
{
|
||||
|
||||
buf[0] = Wire1.read();
|
||||
buf[1] = Wire1.read();
|
||||
buf[2] = Wire1.read();
|
||||
buf[3] = Wire1.read();
|
||||
}
|
||||
|
||||
RTC_DateStruct->Date = Bcd2ToByte(buf[0] & 0x3f);
|
||||
RTC_DateStruct->WeekDay = Bcd2ToByte(buf[1] & 0x07);
|
||||
RTC_DateStruct->Month = Bcd2ToByte(buf[2] & 0x1f);
|
||||
|
||||
if (buf[2] & 0x80)
|
||||
{
|
||||
RTC_DateStruct->Year = 1900 + Bcd2ToByte(buf[3] & 0xff);
|
||||
}
|
||||
else
|
||||
{
|
||||
RTC_DateStruct->Year = 2000 + Bcd2ToByte(buf[3] & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
void BM8563_RTC::SetDate(RTC_DateTypeDef *RTC_DateStruct)
|
||||
{
|
||||
|
||||
if (RTC_DateStruct == NULL)
|
||||
return;
|
||||
Wire1.beginTransmission(0x51);
|
||||
Wire1.write(0x05);
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->Date));
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->WeekDay));
|
||||
|
||||
if (RTC_DateStruct->Year < 2000)
|
||||
{
|
||||
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x80);
|
||||
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* code */
|
||||
Wire1.write(ByteToBcd2(RTC_DateStruct->Month) | 0x00);
|
||||
Wire1.write(ByteToBcd2((uint8_t)(RTC_DateStruct->Year % 100)));
|
||||
}
|
||||
|
||||
Wire1.endTransmission();
|
||||
}
|
||||
|
||||
int BM8563_RTC::SetAlarmIRQ(int afterSeconds)
|
||||
{
|
||||
uint8_t reg_value = 0;
|
||||
reg_value = ReadReg(0x01);
|
||||
|
||||
if (afterSeconds < 0)
|
||||
{
|
||||
reg_value &= ~(1 << 0);
|
||||
WriteReg(0x01, reg_value);
|
||||
reg_value = 0x03;
|
||||
WriteReg(0x0E, reg_value);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t type_value = 2;
|
||||
uint8_t div = 1;
|
||||
if (afterSeconds > 255)
|
||||
{
|
||||
div = 60;
|
||||
type_value = 0x83;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_value = 0x82;
|
||||
}
|
||||
|
||||
afterSeconds = (afterSeconds / div) & 0xFF;
|
||||
WriteReg(0x0F, afterSeconds);
|
||||
WriteReg(0x0E, type_value);
|
||||
|
||||
reg_value |= (1 << 0);
|
||||
reg_value &= ~(1 << 7);
|
||||
WriteReg(0x01, reg_value);
|
||||
return afterSeconds * div;
|
||||
}
|
||||
|
||||
int BM8563_RTC::SetAlarmIRQ(const RTC_TimeTypeDef &RTC_TimeStruct)
|
||||
{
|
||||
uint8_t irq_enable = false;
|
||||
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
||||
|
||||
if (RTC_TimeStruct.Minutes >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
|
||||
}
|
||||
|
||||
if (RTC_TimeStruct.Hours >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
||||
}
|
||||
|
||||
out_buf[2] = 0x00;
|
||||
out_buf[3] = 0x00;
|
||||
|
||||
uint8_t reg_value = ReadReg(0x01);
|
||||
|
||||
if (irq_enable)
|
||||
{
|
||||
reg_value |= (1 << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_value &= ~(1 << 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
WriteReg(0x09 + i, out_buf[i]);
|
||||
}
|
||||
WriteReg(0x01, reg_value);
|
||||
|
||||
return irq_enable ? 1 : 0;
|
||||
}
|
||||
|
||||
int BM8563_RTC::SetAlarmIRQ(const RTC_DateTypeDef &RTC_DateStruct, const RTC_TimeTypeDef &RTC_TimeStruct)
|
||||
{
|
||||
uint8_t irq_enable = false;
|
||||
uint8_t out_buf[4] = {0x80, 0x80, 0x80, 0x80};
|
||||
|
||||
if (RTC_TimeStruct.Minutes >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[0] = ByteToBcd2(RTC_TimeStruct.Minutes) & 0x7f;
|
||||
}
|
||||
|
||||
if (RTC_TimeStruct.Hours >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[1] = ByteToBcd2(RTC_TimeStruct.Hours) & 0x3f;
|
||||
}
|
||||
|
||||
if (RTC_DateStruct.Date >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[2] = ByteToBcd2(RTC_DateStruct.Date) & 0x3f;
|
||||
}
|
||||
|
||||
if (RTC_DateStruct.WeekDay >= 0)
|
||||
{
|
||||
irq_enable = true;
|
||||
out_buf[3] = ByteToBcd2(RTC_DateStruct.WeekDay) & 0x07;
|
||||
}
|
||||
|
||||
uint8_t reg_value = ReadReg(0x01);
|
||||
|
||||
if (irq_enable)
|
||||
{
|
||||
reg_value |= (1 << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_value &= ~(1 << 1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
WriteReg(0x09 + i, out_buf[i]);
|
||||
}
|
||||
WriteReg(0x01, reg_value);
|
||||
|
||||
return irq_enable ? 1 : 0;
|
||||
}
|
||||
|
||||
void BM8563_RTC::clearIRQ()
|
||||
{
|
||||
uint8_t data = ReadReg(0x01);
|
||||
WriteReg(0x01, data & 0xf3);
|
||||
}
|
||||
void BM8563_RTC::disableIRQ()
|
||||
{
|
||||
clearIRQ();
|
||||
uint8_t data = ReadReg(0x01);
|
||||
WriteReg(0x01, data & 0xfC);
|
||||
}
|
76
lib/libesp32/CORE2_Library/BM8563_RTC.h
Executable file
76
lib/libesp32/CORE2_Library/BM8563_RTC.h
Executable file
@ -0,0 +1,76 @@
|
||||
#ifndef __RTC_H__
|
||||
#define __RTC_H__
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
#define RTC_ADRESS 0x51
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Hours;
|
||||
uint8_t Minutes;
|
||||
uint8_t Seconds;
|
||||
}RTC_TimeTypeDef;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t WeekDay;
|
||||
uint8_t Month;
|
||||
uint8_t Date;
|
||||
uint16_t Year;
|
||||
}RTC_DateTypeDef;
|
||||
|
||||
class BM8563_RTC {
|
||||
public:
|
||||
BM8563_RTC();
|
||||
|
||||
void begin(void);
|
||||
void GetBm8563Time(void);
|
||||
|
||||
void SetTime(RTC_TimeTypeDef* RTC_TimeStruct);
|
||||
void SetDate(RTC_DateTypeDef* RTC_DateStruct);
|
||||
|
||||
void GetTime(RTC_TimeTypeDef* RTC_TimeStruct);
|
||||
void GetDate(RTC_DateTypeDef* RTC_DateStruct);
|
||||
|
||||
int SetAlarmIRQ(int afterSeconds);
|
||||
int SetAlarmIRQ( const RTC_TimeTypeDef &RTC_TimeStruct);
|
||||
int SetAlarmIRQ( const RTC_DateTypeDef &RTC_DateStruct, const RTC_TimeTypeDef &RTC_TimeStruct);
|
||||
|
||||
void clearIRQ();
|
||||
void disableIRQ();
|
||||
|
||||
public:
|
||||
uint8_t Second;
|
||||
uint8_t Minute;
|
||||
uint8_t Hour;
|
||||
uint8_t Week;
|
||||
uint8_t Day;
|
||||
uint8_t Month;
|
||||
uint8_t Year;
|
||||
uint8_t DateString[9];
|
||||
uint8_t TimeString[9];
|
||||
|
||||
uint8_t asc[14];
|
||||
|
||||
|
||||
private:
|
||||
void Bcd2asc(void);
|
||||
void DataMask();
|
||||
void Str2Time(void);
|
||||
void WriteReg(uint8_t reg, uint8_t data);
|
||||
uint8_t ReadReg(uint8_t reg);
|
||||
uint8_t Bcd2ToByte(uint8_t Value);
|
||||
uint8_t ByteToBcd2(uint8_t Value);
|
||||
|
||||
private:
|
||||
|
||||
/*定义数组用来存储读取的时间数据 */
|
||||
uint8_t trdata[7];
|
||||
/*定义数组用来存储转换的 asc 码时间数据*/
|
||||
//uint8_t asc[14];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
252
lib/libesp32/CORE2_Library/MPU6886.cpp
Executable file
252
lib/libesp32/CORE2_Library/MPU6886.cpp
Executable file
@ -0,0 +1,252 @@
|
||||
#include "MPU6886.h"
|
||||
#include <math.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
MPU6886::MPU6886(){
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer){
|
||||
|
||||
Wire1.beginTransmission(driver_Addr);
|
||||
Wire1.write(start_Addr);
|
||||
Wire1.endTransmission(false);
|
||||
uint8_t i = 0;
|
||||
Wire1.requestFrom(driver_Addr,number_Bytes);
|
||||
|
||||
//! Put read results in the Rx buffer
|
||||
while (Wire1.available()) {
|
||||
read_Buffer[i++] = Wire1.read();
|
||||
}
|
||||
}
|
||||
|
||||
void MPU6886::I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer){
|
||||
|
||||
Wire1.beginTransmission(driver_Addr);
|
||||
Wire1.write(start_Addr);
|
||||
Wire1.write(*write_Buffer);
|
||||
Wire1.endTransmission();
|
||||
|
||||
}
|
||||
|
||||
int MPU6886::Init(void){
|
||||
unsigned char tempdata[1];
|
||||
unsigned char regdata;
|
||||
|
||||
Wire1.begin(21,22);
|
||||
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS, MPU6886_WHOAMI, 1, tempdata);
|
||||
if(tempdata[0] != 0x19)
|
||||
return -1;
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
regdata = (0x01<<7);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
regdata = (0x01<<0);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_PWR_MGMT_1, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
regdata = 0x10;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x18;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x01;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_CONFIG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x05;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_SMPLRT_DIV, 1,®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG2, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_USER_CTRL, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x00;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_FIFO_EN, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x22;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_PIN_CFG, 1, ®data);
|
||||
delay(1);
|
||||
|
||||
regdata = 0x01;
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_INT_ENABLE, 1, ®data);
|
||||
|
||||
delay(100);
|
||||
getGres();
|
||||
getAres();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MPU6886::getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az){
|
||||
|
||||
uint8_t buf[6];
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_ACCEL_XOUT_H,6,buf);
|
||||
|
||||
*ax=((int16_t)buf[0]<<8)|buf[1];
|
||||
*ay=((int16_t)buf[2]<<8)|buf[3];
|
||||
*az=((int16_t)buf[4]<<8)|buf[5];
|
||||
|
||||
}
|
||||
void MPU6886::getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz){
|
||||
|
||||
uint8_t buf[6];
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_GYRO_XOUT_H,6,buf);
|
||||
|
||||
*gx=((uint16_t)buf[0]<<8)|buf[1];
|
||||
*gy=((uint16_t)buf[2]<<8)|buf[3];
|
||||
*gz=((uint16_t)buf[4]<<8)|buf[5];
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::getTempAdc(int16_t *t){
|
||||
|
||||
uint8_t buf[2];
|
||||
I2C_Read_NBytes(MPU6886_ADDRESS,MPU6886_TEMP_OUT_H,2,buf);
|
||||
|
||||
*t=((uint16_t)buf[0]<<8)|buf[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//!俯仰,航向,横滚:pitch,yaw,roll,指三维空间中飞行器的旋转状态。
|
||||
void MPU6886::getAhrsData(float *pitch,float *roll,float *yaw){
|
||||
|
||||
float accX = 0;
|
||||
float accY = 0;
|
||||
float accZ = 0;
|
||||
|
||||
float gyroX = 0;
|
||||
float gyroY = 0;
|
||||
float gyroZ = 0;
|
||||
|
||||
|
||||
getGyroData(&gyroX,&gyroY,&gyroZ);
|
||||
getAccelData(&accX,&accY,&accZ);
|
||||
|
||||
MahonyAHRSupdateIMU(gyroX * DEG_TO_RAD, gyroY * DEG_TO_RAD, gyroZ * DEG_TO_RAD, accX, accY, accZ,pitch,roll,yaw);
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::getGres(){
|
||||
|
||||
switch (Gyscale)
|
||||
{
|
||||
// Possible gyro scales (and their register bit settings) are:
|
||||
case GFS_250DPS:
|
||||
gRes = 250.0/32768.0;
|
||||
break;
|
||||
case GFS_500DPS:
|
||||
gRes = 500.0/32768.0;
|
||||
break;
|
||||
case GFS_1000DPS:
|
||||
gRes = 1000.0/32768.0;
|
||||
break;
|
||||
case GFS_2000DPS:
|
||||
gRes = 2000.0/32768.0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MPU6886::getAres(){
|
||||
switch (Acscale)
|
||||
{
|
||||
// Possible accelerometer scales (and their register bit settings) are:
|
||||
// 2 Gs (00), 4 Gs (01), 8 Gs (10), and 16 Gs (11).
|
||||
// Here's a bit of an algorith to calculate DPS/(ADC tick) based on that 2-bit value:
|
||||
case AFS_2G:
|
||||
aRes = 2.0/32768.0;
|
||||
break;
|
||||
case AFS_4G:
|
||||
aRes = 4.0/32768.0;
|
||||
break;
|
||||
case AFS_8G:
|
||||
aRes = 8.0/32768.0;
|
||||
break;
|
||||
case AFS_16G:
|
||||
aRes = 16.0/32768.0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::SetGyroFsr(Gscale scale)
|
||||
{
|
||||
//return IIC_Write_Byte(MPU_GYRO_CFG_REG,scale<<3);//设置陀螺仪满量程范围
|
||||
unsigned char regdata;
|
||||
regdata = (scale<<3);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_GYRO_CONFIG, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
Gyscale = scale;
|
||||
getGres();
|
||||
}
|
||||
|
||||
void MPU6886::SetAccelFsr(Ascale scale)
|
||||
{
|
||||
unsigned char regdata;
|
||||
regdata = (scale<<3);
|
||||
I2C_Write_NBytes(MPU6886_ADDRESS, MPU6886_ACCEL_CONFIG, 1, ®data);
|
||||
delay(10);
|
||||
|
||||
Acscale = scale;
|
||||
getAres();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void MPU6886::getAccelData(float* ax, float* ay, float* az){
|
||||
|
||||
|
||||
int16_t accX = 0;
|
||||
int16_t accY = 0;
|
||||
int16_t accZ = 0;
|
||||
getAccelAdc(&accX,&accY,&accZ);
|
||||
|
||||
|
||||
*ax = (float)accX * aRes;
|
||||
*ay = (float)accY * aRes;
|
||||
*az = (float)accZ * aRes;
|
||||
|
||||
}
|
||||
|
||||
void MPU6886::getGyroData(float* gx, float* gy, float* gz){
|
||||
int16_t gyroX = 0;
|
||||
int16_t gyroY = 0;
|
||||
int16_t gyroZ = 0;
|
||||
getGyroAdc(&gyroX,&gyroY,&gyroZ);
|
||||
|
||||
*gx = (float)gyroX * gRes;
|
||||
*gy = (float)gyroY * gRes;
|
||||
*gz = (float)gyroZ * gRes;
|
||||
}
|
||||
|
||||
void MPU6886::getTempData(float *t){
|
||||
|
||||
int16_t temp = 0;
|
||||
getTempAdc(&temp);
|
||||
|
||||
*t = (float)temp / 326.8 + 25.0;
|
||||
}
|
98
lib/libesp32/CORE2_Library/MPU6886.h
Executable file
98
lib/libesp32/CORE2_Library/MPU6886.h
Executable file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Note: The MPU6886 is an I2C sensor and uses the Arduino Wire library.
|
||||
Because the sensor is not 5V tolerant, we are using a 3.3 V 8 MHz Pro Mini or
|
||||
a 3.3 V Teensy 3.1. We have disabled the internal pull-ups used by the Wire
|
||||
library in the Wire.h/twi.c utility file. We are also using the 400 kHz fast
|
||||
I2C mode by setting the TWI_FREQ to 400000L /twi.h utility file.
|
||||
*/
|
||||
#ifndef _MPU6886_H_
|
||||
#define _MPU6886_H_
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Arduino.h>
|
||||
#include "MahonyAHRS.h"
|
||||
|
||||
#define MPU6886_ADDRESS 0x68
|
||||
#define MPU6886_WHOAMI 0x75
|
||||
#define MPU6886_ACCEL_INTEL_CTRL 0x69
|
||||
#define MPU6886_SMPLRT_DIV 0x19
|
||||
#define MPU6886_INT_PIN_CFG 0x37
|
||||
#define MPU6886_INT_ENABLE 0x38
|
||||
#define MPU6886_ACCEL_XOUT_H 0x3B
|
||||
#define MPU6886_ACCEL_XOUT_L 0x3C
|
||||
#define MPU6886_ACCEL_YOUT_H 0x3D
|
||||
#define MPU6886_ACCEL_YOUT_L 0x3E
|
||||
#define MPU6886_ACCEL_ZOUT_H 0x3F
|
||||
#define MPU6886_ACCEL_ZOUT_L 0x40
|
||||
|
||||
#define MPU6886_TEMP_OUT_H 0x41
|
||||
#define MPU6886_TEMP_OUT_L 0x42
|
||||
|
||||
#define MPU6886_GYRO_XOUT_H 0x43
|
||||
#define MPU6886_GYRO_XOUT_L 0x44
|
||||
#define MPU6886_GYRO_YOUT_H 0x45
|
||||
#define MPU6886_GYRO_YOUT_L 0x46
|
||||
#define MPU6886_GYRO_ZOUT_H 0x47
|
||||
#define MPU6886_GYRO_ZOUT_L 0x48
|
||||
|
||||
#define MPU6886_USER_CTRL 0x6A
|
||||
#define MPU6886_PWR_MGMT_1 0x6B
|
||||
#define MPU6886_PWR_MGMT_2 0x6C
|
||||
#define MPU6886_CONFIG 0x1A
|
||||
#define MPU6886_GYRO_CONFIG 0x1B
|
||||
#define MPU6886_ACCEL_CONFIG 0x1C
|
||||
#define MPU6886_ACCEL_CONFIG2 0x1D
|
||||
#define MPU6886_FIFO_EN 0x23
|
||||
|
||||
//#define G (9.8)
|
||||
#define RtA 57.324841
|
||||
#define AtR 0.0174533
|
||||
#define Gyro_Gr 0.0010653
|
||||
|
||||
class MPU6886 {
|
||||
public:
|
||||
enum Ascale {
|
||||
AFS_2G = 0,
|
||||
AFS_4G,
|
||||
AFS_8G,
|
||||
AFS_16G
|
||||
};
|
||||
|
||||
enum Gscale {
|
||||
GFS_250DPS = 0,
|
||||
GFS_500DPS,
|
||||
GFS_1000DPS,
|
||||
GFS_2000DPS
|
||||
};
|
||||
|
||||
Gscale Gyscale = GFS_2000DPS;
|
||||
Ascale Acscale = AFS_8G;
|
||||
public:
|
||||
MPU6886();
|
||||
int Init(void);
|
||||
void getAccelAdc(int16_t* ax, int16_t* ay, int16_t* az);
|
||||
void getGyroAdc(int16_t* gx, int16_t* gy, int16_t* gz);
|
||||
void getTempAdc(int16_t *t);
|
||||
|
||||
void getAccelData(float* ax, float* ay, float* az);
|
||||
void getGyroData(float* gx, float* gy, float* gz);
|
||||
void getTempData(float *t);
|
||||
|
||||
void SetGyroFsr(Gscale scale);
|
||||
void SetAccelFsr(Ascale scale);
|
||||
|
||||
void getAhrsData(float *pitch,float *roll,float *yaw);
|
||||
|
||||
public:
|
||||
float aRes, gRes;
|
||||
|
||||
private:
|
||||
|
||||
private:
|
||||
void I2C_Read_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer);
|
||||
void I2C_Write_NBytes(uint8_t driver_Addr, uint8_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer);
|
||||
void getGres();
|
||||
void getAres();
|
||||
|
||||
};
|
||||
#endif
|
254
lib/libesp32/CORE2_Library/MahonyAHRS.cpp
Executable file
254
lib/libesp32/CORE2_Library/MahonyAHRS.cpp
Executable file
@ -0,0 +1,254 @@
|
||||
//=====================================================================================================
|
||||
// MahonyAHRS.c
|
||||
//=====================================================================================================
|
||||
//
|
||||
// Madgwick's implementation of Mayhony's AHRS algorithm.
|
||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
||||
//
|
||||
// Date Author Notes
|
||||
// 29/09/2011 SOH Madgwick Initial release
|
||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
||||
//
|
||||
//=====================================================================================================
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Header files
|
||||
|
||||
#include "MahonyAHRS.h"
|
||||
#include "Arduino.h"
|
||||
#include <math.h>
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Definitions
|
||||
|
||||
#define sampleFreq 25.0f // sample frequency in Hz
|
||||
#define twoKpDef (2.0f * 1.0f) // 2 * proportional gain
|
||||
#define twoKiDef (2.0f * 0.0f) // 2 * integral gain
|
||||
|
||||
//#define twoKiDef (0.0f * 0.0f)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Variable definitions
|
||||
|
||||
volatile float twoKp = twoKpDef; // 2 * proportional gain (Kp)
|
||||
volatile float twoKi = twoKiDef; // 2 * integral gain (Ki)
|
||||
volatile float q0 = 1.0, q1 = 0.0, q2 = 0.0, q3 = 0.0; // quaternion of sensor frame relative to auxiliary frame
|
||||
volatile float integralFBx = 0.0f, integralFBy = 0.0f, integralFBz = 0.0f; // integral error terms scaled by Ki
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
|
||||
//float invSqrt(float x);
|
||||
|
||||
//====================================================================================================
|
||||
// Functions
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// AHRS algorithm update
|
||||
|
||||
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
|
||||
float recipNorm;
|
||||
float q0q0, q0q1, q0q2, q0q3, q1q1, q1q2, q1q3, q2q2, q2q3, q3q3;
|
||||
float hx, hy, bx, bz;
|
||||
float halfvx, halfvy, halfvz, halfwx, halfwy, halfwz;
|
||||
float halfex, halfey, halfez;
|
||||
float qa, qb, qc;
|
||||
|
||||
// Use IMU algorithm if magnetometer measurement invalid (avoids NaN in magnetometer normalisation)
|
||||
if((mx == 0.0f) && (my == 0.0f) && (mz == 0.0f)) {
|
||||
//MahonyAHRSupdateIMU(gx, gy, gz, ax, ay, az);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
||||
|
||||
// Normalise accelerometer measurement
|
||||
recipNorm = sqrt(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Normalise magnetometer measurement
|
||||
recipNorm = sqrt(mx * mx + my * my + mz * mz);
|
||||
mx *= recipNorm;
|
||||
my *= recipNorm;
|
||||
mz *= recipNorm;
|
||||
|
||||
// Auxiliary variables to avoid repeated arithmetic
|
||||
q0q0 = q0 * q0;
|
||||
q0q1 = q0 * q1;
|
||||
q0q2 = q0 * q2;
|
||||
q0q3 = q0 * q3;
|
||||
q1q1 = q1 * q1;
|
||||
q1q2 = q1 * q2;
|
||||
q1q3 = q1 * q3;
|
||||
q2q2 = q2 * q2;
|
||||
q2q3 = q2 * q3;
|
||||
q3q3 = q3 * q3;
|
||||
|
||||
// Reference direction of Earth's magnetic field
|
||||
hx = 2.0f * (mx * (0.5f - q2q2 - q3q3) + my * (q1q2 - q0q3) + mz * (q1q3 + q0q2));
|
||||
hy = 2.0f * (mx * (q1q2 + q0q3) + my * (0.5f - q1q1 - q3q3) + mz * (q2q3 - q0q1));
|
||||
bx = sqrt(hx * hx + hy * hy);
|
||||
bz = 2.0f * (mx * (q1q3 - q0q2) + my * (q2q3 + q0q1) + mz * (0.5f - q1q1 - q2q2));
|
||||
|
||||
// Estimated direction of gravity and magnetic field
|
||||
halfvx = q1q3 - q0q2;
|
||||
halfvy = q0q1 + q2q3;
|
||||
halfvz = q0q0 - 0.5f + q3q3;
|
||||
halfwx = bx * (0.5f - q2q2 - q3q3) + bz * (q1q3 - q0q2);
|
||||
halfwy = bx * (q1q2 - q0q3) + bz * (q0q1 + q2q3);
|
||||
halfwz = bx * (q0q2 + q1q3) + bz * (0.5f - q1q1 - q2q2);
|
||||
|
||||
// Error is sum of cross product between estimated direction and measured direction of field vectors
|
||||
halfex = (ay * halfvz - az * halfvy) + (my * halfwz - mz * halfwy);
|
||||
halfey = (az * halfvx - ax * halfvz) + (mz * halfwx - mx * halfwz);
|
||||
halfez = (ax * halfvy - ay * halfvx) + (mx * halfwy - my * halfwx);
|
||||
|
||||
// Compute and apply integral feedback if enabled
|
||||
if(twoKi > 0.0f) {
|
||||
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
|
||||
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
|
||||
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
|
||||
gx += integralFBx; // apply integral feedback
|
||||
gy += integralFBy;
|
||||
gz += integralFBz;
|
||||
}
|
||||
else {
|
||||
integralFBx = 0.0f; // prevent integral windup
|
||||
integralFBy = 0.0f;
|
||||
integralFBz = 0.0f;
|
||||
}
|
||||
|
||||
// Apply proportional feedback
|
||||
gx += twoKp * halfex;
|
||||
gy += twoKp * halfey;
|
||||
gz += twoKp * halfez;
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion
|
||||
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
|
||||
gy *= (0.5f * (1.0f / sampleFreq));
|
||||
gz *= (0.5f * (1.0f / sampleFreq));
|
||||
qa = q0;
|
||||
qb = q1;
|
||||
qc = q2;
|
||||
q0 += (-qb * gx - qc * gy - q3 * gz);
|
||||
q1 += (qa * gx + qc * gz - q3 * gy);
|
||||
q2 += (qa * gy - qb * gz + q3 * gx);
|
||||
q3 += (qa * gz + qb * gy - qc * gx);
|
||||
|
||||
// Normalise quaternion
|
||||
recipNorm = sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
|
||||
q0 *= recipNorm;
|
||||
q1 *= recipNorm;
|
||||
q2 *= recipNorm;
|
||||
q3 *= recipNorm;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// IMU algorithm update
|
||||
|
||||
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az,float *pitch,float *roll,float *yaw) {
|
||||
float recipNorm;
|
||||
float halfvx, halfvy, halfvz;
|
||||
float halfex, halfey, halfez;
|
||||
float qa, qb, qc;
|
||||
|
||||
|
||||
// Compute feedback only if accelerometer measurement valid (avoids NaN in accelerometer normalisation)
|
||||
if(!((ax == 0.0f) && (ay == 0.0f) && (az == 0.0f))) {
|
||||
|
||||
// Normalise accelerometer measurement
|
||||
recipNorm = invSqrt(ax * ax + ay * ay + az * az);
|
||||
ax *= recipNorm;
|
||||
ay *= recipNorm;
|
||||
az *= recipNorm;
|
||||
|
||||
// Estimated direction of gravity and vector perpendicular to magnetic flux
|
||||
halfvx = q1 * q3 - q0 * q2;
|
||||
halfvy = q0 * q1 + q2 * q3;
|
||||
halfvz = q0 * q0 - 0.5f + q3 * q3;
|
||||
|
||||
|
||||
|
||||
// Error is sum of cross product between estimated and measured direction of gravity
|
||||
halfex = (ay * halfvz - az * halfvy);
|
||||
halfey = (az * halfvx - ax * halfvz);
|
||||
halfez = (ax * halfvy - ay * halfvx);
|
||||
|
||||
// Compute and apply integral feedback if enabled
|
||||
if(twoKi > 0.0f) {
|
||||
integralFBx += twoKi * halfex * (1.0f / sampleFreq); // integral error scaled by Ki
|
||||
integralFBy += twoKi * halfey * (1.0f / sampleFreq);
|
||||
integralFBz += twoKi * halfez * (1.0f / sampleFreq);
|
||||
gx += integralFBx; // apply integral feedback
|
||||
gy += integralFBy;
|
||||
gz += integralFBz;
|
||||
}
|
||||
else {
|
||||
integralFBx = 0.0f; // prevent integral windup
|
||||
integralFBy = 0.0f;
|
||||
integralFBz = 0.0f;
|
||||
}
|
||||
|
||||
// Apply proportional feedback
|
||||
gx += twoKp * halfex;
|
||||
gy += twoKp * halfey;
|
||||
gz += twoKp * halfez;
|
||||
}
|
||||
|
||||
// Integrate rate of change of quaternion
|
||||
gx *= (0.5f * (1.0f / sampleFreq)); // pre-multiply common factors
|
||||
gy *= (0.5f * (1.0f / sampleFreq));
|
||||
gz *= (0.5f * (1.0f / sampleFreq));
|
||||
qa = q0;
|
||||
qb = q1;
|
||||
qc = q2;
|
||||
q0 += (-qb * gx - qc * gy - q3 * gz);
|
||||
q1 += (qa * gx + qc * gz - q3 * gy);
|
||||
q2 += (qa * gy - qb * gz + q3 * gx);
|
||||
q3 += (qa * gz + qb * gy - qc * gx);
|
||||
|
||||
// Normalise quaternion
|
||||
recipNorm = invSqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
|
||||
q0 *= recipNorm;
|
||||
q1 *= recipNorm;
|
||||
q2 *= recipNorm;
|
||||
q3 *= recipNorm;
|
||||
|
||||
|
||||
*pitch = asin(-2 * q1 * q3 + 2 * q0* q2); // pitch
|
||||
*roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1); // roll
|
||||
*yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3); //yaw
|
||||
|
||||
*pitch *= RAD_TO_DEG;
|
||||
*yaw *= RAD_TO_DEG;
|
||||
// Declination of SparkFun Electronics (40°05'26.6"N 105°11'05.9"W) is
|
||||
// 8° 30' E ± 0° 21' (or 8.5°) on 2016-07-19
|
||||
// - http://www.ngdc.noaa.gov/geomag-web/#declination
|
||||
*yaw -= 8.5;
|
||||
*roll *= RAD_TO_DEG;
|
||||
|
||||
///Serial.printf("%f %f %f \r\n", pitch, roll, yaw);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Fast inverse square-root
|
||||
// See: http://en.wikipedia.org/wiki/Fast_inverse_square_root
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
float invSqrt(float x) {
|
||||
float halfx = 0.5f * x;
|
||||
float y = x;
|
||||
long i = *(long*)&y;
|
||||
i = 0x5f3759df - (i>>1);
|
||||
y = *(float*)&i;
|
||||
y = y * (1.5f - (halfx * y * y));
|
||||
return y;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
//====================================================================================================
|
||||
// END OF CODE
|
||||
//====================================================================================================
|
33
lib/libesp32/CORE2_Library/MahonyAHRS.h
Executable file
33
lib/libesp32/CORE2_Library/MahonyAHRS.h
Executable file
@ -0,0 +1,33 @@
|
||||
//=====================================================================================================
|
||||
// MahonyAHRS.h
|
||||
//=====================================================================================================
|
||||
//
|
||||
// Madgwick's implementation of Mayhony's AHRS algorithm.
|
||||
// See: http://www.x-io.co.uk/node/8#open_source_ahrs_and_imu_algorithms
|
||||
//
|
||||
// Date Author Notes
|
||||
// 29/09/2011 SOH Madgwick Initial release
|
||||
// 02/10/2011 SOH Madgwick Optimised for reduced CPU load
|
||||
//
|
||||
//=====================================================================================================
|
||||
#ifndef MahonyAHRS_h
|
||||
#define MahonyAHRS_h
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Variable declaration
|
||||
|
||||
extern volatile float twoKp; // 2 * proportional gain (Kp)
|
||||
extern volatile float twoKi; // 2 * integral gain (Ki)
|
||||
//volatile float q0, q1, q2, q3; // quaternion of sensor frame relative to auxiliary frame
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
|
||||
void MahonyAHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz);
|
||||
//void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az);
|
||||
void MahonyAHRSupdateIMU(float gx, float gy, float gz, float ax, float ay, float az,float *pitch,float *roll,float *yaw);
|
||||
float invSqrt(float x);
|
||||
#endif
|
||||
//=====================================================================================================
|
||||
// End of file
|
||||
//=====================================================================================================
|
@ -87,6 +87,6 @@ build_flags = ${esp_defaults.build_flags}
|
||||
|
||||
[core32]
|
||||
platform = espressif32 @ 2.1.0
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/tasmota/arduino-esp32/releases/download/1.0.4.2/esp32-1.0.4.2.zip
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/1.0.5-rc4/esp32-1.0.5-rc4.zip
|
||||
build_unflags = ${esp32_defaults.build_unflags}
|
||||
build_flags = ${esp32_defaults.build_flags}
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -642,6 +642,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
it-IT.h - localization for Italian - Italy for Tasmota
|
||||
|
||||
Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 20.11.2020
|
||||
Copyright (C) 2020 Gennaro Tortone - some mods by Antonio Fragola - Updated by bovirus - rev. 28.12.2020
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 - CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 - DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 - PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 - CLK"
|
||||
#define D_SENSOR_P9813_DAT "P9813 - DAT"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 - DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 - DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "IR ALux - RCV"
|
||||
@ -671,8 +673,8 @@
|
||||
#define D_SENSOR_A4988_STP "A4988 - STP"
|
||||
#define D_SENSOR_A4988_ENA "A4988 - ENA"
|
||||
#define D_SENSOR_A4988_MS1 "A4988 - MS1"
|
||||
#define D_SENSOR_OUTPUT_HI "Output - Hi"
|
||||
#define D_SENSOR_OUTPUT_LO "Output - Lo"
|
||||
#define D_SENSOR_OUTPUT_HI "Uscita - Hi"
|
||||
#define D_SENSOR_OUTPUT_LO "Uscita - Lo"
|
||||
#define D_SENSOR_AS608_TX "AS608 - TX"
|
||||
#define D_SENSOR_AS608_RX "AS608 - RX"
|
||||
#define D_SENSOR_DDS2382_TX "DDS238-2 - TX"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -646,6 +646,8 @@
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
|
||||
#define D_SENSOR_P9813_CLK "P9813 Clk"
|
||||
#define D_SENSOR_P9813_DAT "P9813 Dat"
|
||||
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
|
||||
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
|
||||
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
|
||||
|
@ -484,7 +484,7 @@
|
||||
#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by //
|
||||
// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow
|
||||
// #define USE_WS2812_INVERTED // Use inverted data signal
|
||||
#define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106)
|
||||
#define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106, NEO_HW_P9813)
|
||||
#define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW)
|
||||
#define USE_MY92X1 // Add support for MY92X1 RGBCW led controller as used in Sonoff B1, Ailight and Lohas
|
||||
#define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code)
|
||||
|
@ -142,7 +142,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
||||
uint32_t mqtt_switches : 1; // bit 0 (v9.0.0.3) - SetOption114 - (Switch) Detach Switches from relays and enable MQTT action state for all the SwitchModes (1)
|
||||
uint32_t mi32_enable : 1; // bit 1 (v9.1.0.1) - SetOption115 - (ESP32 BLE) Enable ESP32 MI32 BLE (1)
|
||||
uint32_t zb_disable_autoquery : 1; // bit 2 (v9.1.0.1) - SetOption116 - (Zigbee) Disable auto-query of zigbee lights and devices (1)
|
||||
uint32_t spare03 : 1; // bit 3
|
||||
uint32_t fade_fixed_duration : 1; // bit 3 (v9.1.0.2) - SetOption117 - (Light) run fading at fixed duration instead of fixed slew rate
|
||||
uint32_t spare04 : 1; // bit 4
|
||||
uint32_t spare05 : 1; // bit 5
|
||||
uint32_t spare06 : 1; // bit 6
|
||||
|
@ -17,9 +17,6 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
IPAddress syslog_host_addr; // Syslog host IP address
|
||||
uint32_t syslog_host_hash = 0; // Syslog host name hash
|
||||
|
||||
extern "C" {
|
||||
extern struct rst_info resetInfo;
|
||||
}
|
||||
@ -1899,34 +1896,11 @@ void SetSyslog(uint32_t loglevel)
|
||||
TasmotaGlobal.syslog_timer = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
void GetLog(uint32_t idx, char** entry_pp, size_t* len_p)
|
||||
{
|
||||
char* entry_p = nullptr;
|
||||
size_t len = 0;
|
||||
|
||||
if (idx) {
|
||||
char* it = TasmotaGlobal.web_log;
|
||||
do {
|
||||
uint32_t cur_idx = *it;
|
||||
it++;
|
||||
size_t tmp = strchrspn(it, '\1');
|
||||
tmp++; // Skip terminating '\1'
|
||||
if (cur_idx == idx) { // Found the requested entry
|
||||
len = tmp;
|
||||
entry_p = it;
|
||||
break;
|
||||
}
|
||||
it += tmp;
|
||||
} while (it < TasmotaGlobal.web_log + WEB_LOG_SIZE && *it != '\0');
|
||||
}
|
||||
*entry_pp = entry_p;
|
||||
*len_p = len;
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void Syslog(void)
|
||||
{
|
||||
static IPAddress syslog_host_addr; // Syslog host IP address
|
||||
static uint32_t syslog_host_hash = 0; // Syslog host name hash
|
||||
|
||||
// Destroys TasmotaGlobal.log_data
|
||||
|
||||
uint32_t current_hash = GetHash(SettingsText(SET_SYSLOG_HOST), strlen(SettingsText(SET_SYSLOG_HOST)));
|
||||
@ -1935,14 +1909,14 @@ void Syslog(void)
|
||||
WiFi.hostByName(SettingsText(SET_SYSLOG_HOST), syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash
|
||||
}
|
||||
if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) {
|
||||
char syslog_preamble[64]; // Hostname + Id
|
||||
char syslog_preamble[64]; // Hostname + Id
|
||||
snprintf_P(syslog_preamble, sizeof(syslog_preamble), PSTR("%s ESP-"), NetworkHostname());
|
||||
memmove(TasmotaGlobal.log_data + strlen(syslog_preamble), TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data) - strlen(syslog_preamble));
|
||||
TasmotaGlobal.log_data[sizeof(TasmotaGlobal.log_data) -1] = '\0';
|
||||
memcpy(TasmotaGlobal.log_data, syslog_preamble, strlen(syslog_preamble));
|
||||
PortUdp_write(TasmotaGlobal.log_data, strlen(TasmotaGlobal.log_data));
|
||||
PortUdp.endPacket();
|
||||
delay(1); // Add time for UDP handling (#5512)
|
||||
delay(1); // Add time for UDP handling (#5512)
|
||||
} else {
|
||||
TasmotaGlobal.syslog_level = 0;
|
||||
TasmotaGlobal.syslog_timer = SYSLOG_TIMER;
|
||||
@ -1950,53 +1924,102 @@ void Syslog(void)
|
||||
}
|
||||
}
|
||||
|
||||
void AddLog(uint32_t loglevel)
|
||||
{
|
||||
char mxtime[10]; // "13:45:21 "
|
||||
snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d "), RtcTime.hour, RtcTime.minute, RtcTime.second);
|
||||
void SyslogAsync(void) {
|
||||
static uint32_t index = 1;
|
||||
|
||||
char* line;
|
||||
size_t len;
|
||||
while (GetLog(TasmotaGlobal.syslog_level, &index, &line, &len)) {
|
||||
if (len > 13) {
|
||||
strlcpy(TasmotaGlobal.log_data, line +13, len -13); // Skip mxtime
|
||||
Syslog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GetLog(uint32_t req_loglevel, uint32_t* index_p, char** entry_pp, size_t* len_p) {
|
||||
uint32_t index = *index_p;
|
||||
|
||||
if (!req_loglevel || (index == TasmotaGlobal.log_buffer_pointer)) { return false; }
|
||||
|
||||
if (!index) { // Dump all
|
||||
index = TasmotaGlobal.log_buffer_pointer +1;
|
||||
if (index > 255) { index = 1; }
|
||||
}
|
||||
|
||||
do {
|
||||
size_t len = 0;
|
||||
uint32_t loglevel = 0;
|
||||
char* entry_p = TasmotaGlobal.log_buffer;
|
||||
do {
|
||||
uint32_t cur_idx = *entry_p;
|
||||
entry_p++;
|
||||
size_t tmp = strchrspn(entry_p, '\1');
|
||||
tmp++; // Skip terminating '\1'
|
||||
if (cur_idx == index) { // Found the requested entry
|
||||
loglevel = *entry_p - '0';
|
||||
entry_p++; // Skip loglevel
|
||||
len = tmp -1;
|
||||
break;
|
||||
}
|
||||
entry_p += tmp;
|
||||
} while (entry_p < TasmotaGlobal.log_buffer + LOG_BUFFER_SIZE && *entry_p != '\0');
|
||||
index++;
|
||||
if (index > 255) { index = 1; } // Skip 0 as it is not allowed
|
||||
*index_p = index;
|
||||
if ((len > 0) &&
|
||||
(loglevel <= req_loglevel) &&
|
||||
(TasmotaGlobal.masterlog_level <= req_loglevel)) {
|
||||
*entry_pp = entry_p;
|
||||
*len_p = len;
|
||||
return true;
|
||||
}
|
||||
delay(0);
|
||||
} while (index != TasmotaGlobal.log_buffer_pointer);
|
||||
return false;
|
||||
}
|
||||
|
||||
void AddLog(uint32_t loglevel) {
|
||||
// char mxtime[10]; // "13:45:21 "
|
||||
// snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d "), RtcTime.hour, RtcTime.minute, RtcTime.second);
|
||||
char mxtime[14]; // "13:45:21.999 "
|
||||
snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d.%03d "), RtcTime.hour, RtcTime.minute, RtcTime.second, RtcMillis());
|
||||
|
||||
if ((loglevel <= TasmotaGlobal.seriallog_level) &&
|
||||
(TasmotaGlobal.masterlog_level <= TasmotaGlobal.seriallog_level)) {
|
||||
Serial.printf("%s%s\r\n", mxtime, TasmotaGlobal.log_data);
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
if (Settings.webserver &&
|
||||
(loglevel <= Settings.weblog_level) &&
|
||||
(TasmotaGlobal.masterlog_level <= Settings.weblog_level)) {
|
||||
|
||||
uint32_t highest_loglevel = Settings.weblog_level;
|
||||
if (Settings.mqttlog_level > highest_loglevel) { highest_loglevel = Settings.mqttlog_level; }
|
||||
if (TasmotaGlobal.syslog_level > highest_loglevel) { highest_loglevel = TasmotaGlobal.syslog_level; }
|
||||
if ((loglevel <= highest_loglevel) && // Log only when needed
|
||||
(TasmotaGlobal.masterlog_level <= highest_loglevel)) {
|
||||
// Delimited, zero-terminated buffer of log lines.
|
||||
// Each entry has this format: [index][log data]['\1']
|
||||
TasmotaGlobal.web_log_index &= 0xFF;
|
||||
if (!TasmotaGlobal.web_log_index) {
|
||||
TasmotaGlobal.web_log_index++; // Index 0 is not allowed as it is the end of char string
|
||||
// Each entry has this format: [index][loglevel][log data]['\1']
|
||||
TasmotaGlobal.log_buffer_pointer &= 0xFF;
|
||||
if (!TasmotaGlobal.log_buffer_pointer) {
|
||||
TasmotaGlobal.log_buffer_pointer++; // Index 0 is not allowed as it is the end of char string
|
||||
}
|
||||
while (TasmotaGlobal.web_log_index == TasmotaGlobal.web_log[0] || // If log already holds the next index, remove it
|
||||
strlen(TasmotaGlobal.web_log) + strlen(TasmotaGlobal.log_data) + 13 > WEB_LOG_SIZE) // 13 = web_log_index + mxtime + '\1' + '\0'
|
||||
while (TasmotaGlobal.log_buffer_pointer == TasmotaGlobal.log_buffer[0] || // If log already holds the next index, remove it
|
||||
strlen(TasmotaGlobal.log_buffer) + strlen(TasmotaGlobal.log_data) + strlen(mxtime) + 4 > LOG_BUFFER_SIZE) // 4 = log_buffer_pointer + '\1' + '\0'
|
||||
{
|
||||
char* it = TasmotaGlobal.web_log;
|
||||
it++; // Skip web_log_index
|
||||
char* it = TasmotaGlobal.log_buffer;
|
||||
it++; // Skip log_buffer_pointer
|
||||
it += strchrspn(it, '\1'); // Skip log line
|
||||
it++; // Skip delimiting "\1"
|
||||
memmove(TasmotaGlobal.web_log, it, WEB_LOG_SIZE -(it-TasmotaGlobal.web_log)); // Move buffer forward to remove oldest log line
|
||||
memmove(TasmotaGlobal.log_buffer, it, LOG_BUFFER_SIZE -(it-TasmotaGlobal.log_buffer)); // Move buffer forward to remove oldest log line
|
||||
}
|
||||
snprintf_P(TasmotaGlobal.web_log, sizeof(TasmotaGlobal.web_log), PSTR("%s%c%s%s\1"), TasmotaGlobal.web_log, TasmotaGlobal.web_log_index++, mxtime, TasmotaGlobal.log_data);
|
||||
TasmotaGlobal.web_log_index &= 0xFF;
|
||||
if (!TasmotaGlobal.web_log_index) {
|
||||
TasmotaGlobal.web_log_index++; // Index 0 is not allowed as it is the end of char string
|
||||
snprintf_P(TasmotaGlobal.log_buffer, sizeof(TasmotaGlobal.log_buffer), PSTR("%s%c%c%s%s\1"),
|
||||
TasmotaGlobal.log_buffer, TasmotaGlobal.log_buffer_pointer++, '0'+loglevel, mxtime, TasmotaGlobal.log_data);
|
||||
TasmotaGlobal.log_buffer_pointer &= 0xFF;
|
||||
if (!TasmotaGlobal.log_buffer_pointer) {
|
||||
TasmotaGlobal.log_buffer_pointer++; // Index 0 is not allowed as it is the end of char string
|
||||
}
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
if (Settings.flag.mqtt_enabled && // SetOption3 - Enable MQTT
|
||||
!TasmotaGlobal.global_state.mqtt_down &&
|
||||
(loglevel <= Settings.mqttlog_level) &&
|
||||
(TasmotaGlobal.masterlog_level <= Settings.mqttlog_level)) { MqttPublishLogging(mxtime); }
|
||||
|
||||
if (!TasmotaGlobal.global_state.network_down &&
|
||||
(loglevel <= TasmotaGlobal.syslog_level) &&
|
||||
(TasmotaGlobal.masterlog_level <= TasmotaGlobal.syslog_level)) { Syslog(); }
|
||||
|
||||
TasmotaGlobal.prepped_loglevel = 0;
|
||||
// TasmotaGlobal.prepped_loglevel = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
void PrepLog_P(uint32_t loglevel, PGM_P formatP, ...)
|
||||
{
|
||||
va_list arg;
|
||||
@ -2006,13 +2029,14 @@ void PrepLog_P(uint32_t loglevel, PGM_P formatP, ...)
|
||||
|
||||
TasmotaGlobal.prepped_loglevel = loglevel;
|
||||
}
|
||||
|
||||
*/
|
||||
void AddLog_P(uint32_t loglevel, PGM_P formatP, ...)
|
||||
{
|
||||
/*
|
||||
if (TasmotaGlobal.prepped_loglevel) {
|
||||
AddLog(TasmotaGlobal.prepped_loglevel);
|
||||
}
|
||||
|
||||
*/
|
||||
va_list arg;
|
||||
va_start(arg, formatP);
|
||||
vsnprintf_P(TasmotaGlobal.log_data, sizeof(TasmotaGlobal.log_data), formatP, arg);
|
||||
|
@ -1154,11 +1154,15 @@ void CmndGpio(void)
|
||||
TasmotaGlobal.restart_flag = 2;
|
||||
}
|
||||
}
|
||||
Response_P(PSTR("{"));
|
||||
bool jsflg = false;
|
||||
bool jsflg2 = false;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
|
||||
if (ValidGPIO(i, template_gp.io[i]) || ((255 == XdrvMailbox.payload) && !FlashPin(i))) {
|
||||
if (jsflg) { ResponseAppend_P(PSTR(",")); }
|
||||
if (!jsflg) {
|
||||
Response_P(PSTR("{"));
|
||||
} else {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
}
|
||||
jsflg = true;
|
||||
uint32_t sensor_type = Settings.my_gp.io[i];
|
||||
if (!ValidGPIO(i, template_gp.io[i])) {
|
||||
@ -1183,12 +1187,16 @@ void CmndGpio(void)
|
||||
sensor_names = kSensorNamesFixed;
|
||||
}
|
||||
char stemp1[TOPSZ];
|
||||
ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s%s\"}"),
|
||||
i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex);
|
||||
if ((ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":{\"%d\":\"%s%s\"}"), i, sensor_type, GetTextIndexed(stemp1, sizeof(stemp1), sensor_name_idx, sensor_names), sindex) > (LOGSZ - TOPSZ)) || (i == ARRAY_SIZE(Settings.my_gp.io) -1)) {
|
||||
ResponseJsonEndEnd();
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, XdrvMailbox.command);
|
||||
jsflg2 = true;
|
||||
jsflg = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsflg) {
|
||||
ResponseJsonEnd();
|
||||
if (jsflg2) {
|
||||
ResponseClear();
|
||||
} else {
|
||||
ResponseCmndChar(D_JSON_NOT_SUPPORTED);
|
||||
}
|
||||
@ -2068,6 +2076,9 @@ void CmndDriver(void)
|
||||
|
||||
void CmndInfo(void) {
|
||||
NvsInfo();
|
||||
#ifdef USE_TFS
|
||||
TfsInfo();
|
||||
#endif
|
||||
ResponseCmndDone();
|
||||
}
|
||||
|
||||
|
@ -167,10 +167,19 @@ void SettingsErase(uint8_t type) {
|
||||
}
|
||||
|
||||
void SettingsRead(void *data, size_t size) {
|
||||
#ifdef USE_TFS
|
||||
// if (!TfsLoadFile("/settings", (uint8_t*)data, size)) {
|
||||
NvmLoad("main", "Settings", data, size);
|
||||
// }
|
||||
#else
|
||||
NvmLoad("main", "Settings", data, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SettingsWrite(const void *pSettings, unsigned nSettingsLen) {
|
||||
#ifdef USE_TFS
|
||||
// TfsSaveFile("/settings", (const uint8_t*)pSettings, nSettingsLen);
|
||||
#endif
|
||||
NvmSave("main", "Settings", pSettings, nSettingsLen);
|
||||
}
|
||||
|
||||
@ -182,23 +191,11 @@ void QPCWrite(const void *pSettings, unsigned nSettingsLen) {
|
||||
NvmSave("qpc", "pcreg", pSettings, nSettingsLen);
|
||||
}
|
||||
|
||||
void ZigbeeErase(void) {
|
||||
NvmErase("zb");
|
||||
}
|
||||
|
||||
void ZigbeeRead(void *pSettings, unsigned nSettingsLen) {
|
||||
NvmLoad("zb", "zigbee", pSettings, nSettingsLen);
|
||||
}
|
||||
|
||||
void ZigbeeWrite(const void *pSettings, unsigned nSettingsLen) {
|
||||
NvmSave("zb", "zigbee", pSettings, nSettingsLen);
|
||||
}
|
||||
|
||||
void NvsInfo(void) {
|
||||
nvs_stats_t nvs_stats;
|
||||
nvs_get_stats(NULL, &nvs_stats);
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("INF: NVS Used %d, Free %d, Total %d, Namspaces %d"),
|
||||
nvs_stats.used_entries, nvs_stats.free_entries, nvs_stats.total_entries, nvs_stats.namespace_count);
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("NVS: Used %d/%d entries, NameSpaces %d"),
|
||||
nvs_stats.used_entries, nvs_stats.total_entries, nvs_stats.namespace_count);
|
||||
}
|
||||
|
||||
//
|
||||
|
148
tasmota/support_filesystem.ino
Normal file
148
tasmota/support_filesystem.ino
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
support_filesystem.ino - Filesystem support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*********************************************************************************************\
|
||||
* ESP32 Filesystem Support
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
#ifdef USE_TFS
|
||||
|
||||
//#define USE_LITTLEFS // LittleFS not tested yet as currently ESP8266 only
|
||||
//#define USE_FFAT // FFat minimal 983k partition (4096 sector size) - tested
|
||||
#define USE_SPIFFS // SPIFFS - tested
|
||||
|
||||
#ifdef USE_LITTLEFS
|
||||
#include <LittleFS.h>
|
||||
#define TASMOTA_FS LittleFS
|
||||
#endif
|
||||
#ifdef USE_FFAT
|
||||
#include <FFat.h>
|
||||
#define TASMOTA_FS FFat
|
||||
#endif
|
||||
#ifdef USE_SPIFFS
|
||||
#include <SPIFFS.h>
|
||||
#define TASMOTA_FS SPIFFS
|
||||
#endif
|
||||
|
||||
bool TfsInit(void) {
|
||||
static uint8_t FsMounted = 0;
|
||||
|
||||
if (FsMounted) { return FsMounted -1; }
|
||||
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Mounting..."));
|
||||
if (!TASMOTA_FS.begin()) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Formatting..."));
|
||||
TASMOTA_FS.format();
|
||||
if (!TASMOTA_FS.begin()) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Failed"));
|
||||
FsMounted = 1; // false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Mounted"));
|
||||
FsMounted = 2; // true
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TfsFileExists(const char *fname){
|
||||
if (!TfsInit()) { return false; }
|
||||
|
||||
bool yes = false;
|
||||
File file = TASMOTA_FS.open(fname, "r");
|
||||
if (!file.isDirectory()) {
|
||||
yes = true;
|
||||
} else {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: File not found"));
|
||||
}
|
||||
file.close();
|
||||
return yes;
|
||||
}
|
||||
|
||||
bool TfsSaveFile(const char *fname, const uint8_t *buf, uint32_t len) {
|
||||
if (!TfsInit()) { return false; }
|
||||
|
||||
File file = TASMOTA_FS.open(fname, "w");
|
||||
if (!file) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Save failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
file.write(buf, len);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TfsEraseFile(const char *fname, uint32_t len) {
|
||||
if (!TfsInit()) { return false; }
|
||||
|
||||
File file = TASMOTA_FS.open(fname, "w");
|
||||
if (!file) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Erase failed"));
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t init_value = 0xff;
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
file.write(&init_value, 1);
|
||||
}
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TfsLoadFile(const char *fname, uint8_t *buf, uint32_t len) {
|
||||
if (!TfsInit()) { return false; }
|
||||
if (!TfsFileExists(fname)) { return false; }
|
||||
|
||||
File file = TASMOTA_FS.open(fname, "r");
|
||||
if (!file) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: File not found"));
|
||||
return false;
|
||||
}
|
||||
|
||||
file.read(buf, len);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void TfsInfo(void) {
|
||||
if (!TfsInit()) { return; }
|
||||
|
||||
uint32_t total_bytes = TASMOTA_FS.totalBytes();
|
||||
#ifdef USE_SPIFFS
|
||||
uint32_t used_bytes = TASMOTA_FS.usedBytes();
|
||||
#endif // USE_SPIFFS
|
||||
#ifdef USE_FFAT
|
||||
uint32_t used_bytes = total_bytes - TASMOTA_FS.freeBytes();
|
||||
#endif // USE_FFAT
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: Used %d/%d bytes"), used_bytes, total_bytes);
|
||||
|
||||
File root = TASMOTA_FS.open("/");
|
||||
File file = root.openNextFile();
|
||||
while (file) {
|
||||
String filename = file.name();
|
||||
size_t filesize = file.size();
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("TFS: File %s, size %d"), filename.c_str(), filesize);
|
||||
file = root.openNextFile();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_TFS
|
||||
#endif // ESP32
|
@ -392,7 +392,7 @@ void RtcSecond(void)
|
||||
Rtc.standard_time = RuleToTime(Settings.tflag[0], RtcTime.year);
|
||||
|
||||
// Do not use AddLog_P( here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9
|
||||
PrepLog_P(LOG_LEVEL_DEBUG, PSTR("RTC: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"),
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("RTC: " D_UTC_TIME " %s, " D_DST_TIME " %s, " D_STD_TIME " %s"),
|
||||
GetDateAndTime(DT_UTC).c_str(), GetDateAndTime(DT_DST).c_str(), GetDateAndTime(DT_STD).c_str());
|
||||
|
||||
if (Rtc.local_time < START_VALID_TIME) { // 2016-01-01
|
||||
@ -407,7 +407,7 @@ void RtcSecond(void)
|
||||
|
||||
if ((Rtc.utc_time > (2 * 60 * 60)) && (last_sync < Rtc.utc_time - (2 * 60 * 60))) { // Every two hours a warning
|
||||
// Do not use AddLog_P( here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9
|
||||
PrepLog_P(LOG_LEVEL_DEBUG, PSTR("RTC: Not synced"));
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("RTC: Not synced"));
|
||||
last_sync = Rtc.utc_time;
|
||||
}
|
||||
|
||||
@ -482,3 +482,7 @@ void RtcInit(void) {
|
||||
BreakTime(Rtc.utc_time, RtcTime);
|
||||
TickerRtc.attach(1, RtcSecond);
|
||||
}
|
||||
|
||||
void RtcPreInit(void) {
|
||||
Rtc.millis = millis();
|
||||
}
|
||||
|
@ -845,6 +845,9 @@ void PerformEverySecond(void)
|
||||
}
|
||||
}
|
||||
|
||||
MqttPublishLoggingAsync();
|
||||
SyslogAsync();
|
||||
|
||||
ResetGlobalValues();
|
||||
|
||||
if (Settings.tele_period) {
|
||||
@ -894,10 +897,11 @@ void Every100mSeconds(void)
|
||||
// As the max amount of sleep = 250 mSec this loop will shift in time...
|
||||
power_t power_now;
|
||||
|
||||
/*
|
||||
if (TasmotaGlobal.prepped_loglevel) {
|
||||
AddLog(TasmotaGlobal.prepped_loglevel);
|
||||
}
|
||||
|
||||
*/
|
||||
if (TasmotaGlobal.latching_relay_pulse) {
|
||||
TasmotaGlobal.latching_relay_pulse--;
|
||||
if (!TasmotaGlobal.latching_relay_pulse) SetLatchingRelay(0, 0);
|
||||
|
@ -183,6 +183,7 @@ const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to
|
||||
#define NEO_HW_SK6812 2 // NeoPixelBus hardware SK6812
|
||||
#define NEO_HW_LC8812 2 // NeoPixelBus hardware LC8812
|
||||
#define NEO_HW_APA106 3 // NeoPixelBus hardware APA106
|
||||
#define NEO_HW_P9813 4 // NeoPixelBus hardware P9813
|
||||
|
||||
#define MQTT_PUBSUBCLIENT 1 // Mqtt PubSubClient library
|
||||
#define MQTT_TASMOTAMQTT 2 // Mqtt TasmotaMqtt library based on esp-mqtt-arduino - soon obsolete
|
||||
|
@ -86,7 +86,7 @@ struct {
|
||||
uint32_t blink_timer; // Power cycle timer
|
||||
uint32_t backlog_timer; // Timer for next command in backlog
|
||||
uint32_t loop_load_avg; // Indicative loop load average
|
||||
uint32_t web_log_index; // Index in Web log buffer
|
||||
uint32_t log_buffer_pointer; // Index in log buffer
|
||||
uint32_t uptime; // Counting every second until 4294967295 = 130 year
|
||||
|
||||
power_t power; // Current copy of Settings.power
|
||||
@ -153,7 +153,7 @@ struct {
|
||||
uint8_t module_type; // Current copy of Settings.module or user template type
|
||||
uint8_t last_source; // Last command source
|
||||
uint8_t shutters_present; // Number of actual define shutters
|
||||
uint8_t prepped_loglevel; // Delayed log level message
|
||||
// uint8_t prepped_loglevel; // Delayed log level message
|
||||
|
||||
#ifndef SUPPORT_IF_STATEMENT
|
||||
uint8_t backlog_index; // Command backlog index
|
||||
@ -169,7 +169,7 @@ struct {
|
||||
char mqtt_topic[TOPSZ]; // Composed MQTT topic
|
||||
char mqtt_data[MESSZ]; // MQTT publish buffer and web page ajax buffer
|
||||
char log_data[LOGSZ]; // Logging
|
||||
char web_log[WEB_LOG_SIZE]; // Web log buffer
|
||||
char log_buffer[LOG_BUFFER_SIZE]; // Web log buffer
|
||||
} TasmotaGlobal;
|
||||
|
||||
#ifdef SUPPORT_IF_STATEMENT
|
||||
@ -191,6 +191,8 @@ void setup(void) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RtcPreInit();
|
||||
|
||||
memset(&TasmotaGlobal, 0, sizeof(TasmotaGlobal));
|
||||
TasmotaGlobal.baudrate = APP_BAUDRATE;
|
||||
TasmotaGlobal.seriallog_timer = SERIALLOG_TIMER;
|
||||
|
@ -61,7 +61,7 @@
|
||||
#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by //
|
||||
// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow
|
||||
#ifndef USE_WS2812_HARDWARE
|
||||
#define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106)
|
||||
#define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106, NEO_HW_P9813)
|
||||
#endif
|
||||
#ifndef USE_WS2812_CTYPE
|
||||
#define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW)
|
||||
|
@ -107,6 +107,12 @@ String EthernetMacAddress(void);
|
||||
#define ARDUINO_CORE_RELEASE ARDUINO_ESP32_RELEASE
|
||||
#endif // ARDUINO_ESP32_RELEASE
|
||||
|
||||
#define USE_TFS
|
||||
|
||||
#ifdef USE_SCRIPT
|
||||
#undef USE_TFS
|
||||
#endif // USE_SCRIPT
|
||||
|
||||
// Hardware has no ESP32
|
||||
#undef USE_TUYA_DIMMER
|
||||
#undef USE_PWM_DIMMER
|
||||
@ -203,11 +209,7 @@ String EthernetMacAddress(void);
|
||||
#define WS2812_LEDS 30 // [Pixels] Number of LEDs
|
||||
#endif
|
||||
|
||||
//#ifdef USE_MQTT_TLS // Set to 4000 on 20200922 per #9305
|
||||
// const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog
|
||||
//#else
|
||||
const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog
|
||||
//#endif
|
||||
const uint16_t LOG_BUFFER_SIZE = 4000; // Max number of characters in logbuffer used by weblog, syslog and mqttlog
|
||||
|
||||
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2)
|
||||
#error "Arduino ESP8266 Core versions before 2.7.1 are not supported"
|
||||
|
@ -129,6 +129,7 @@ enum UserSelectablePins {
|
||||
GPIO_AS608_TX, GPIO_AS608_RX, // Serial interface AS608 / R503
|
||||
GPIO_SHELLY_DIMMER_BOOT0, GPIO_SHELLY_DIMMER_RST_INV,
|
||||
GPIO_RC522_RST, // RC522 reset
|
||||
GPIO_P9813_CLK, GPIO_P9813_DAT, // P9813 Clock and Data
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
enum ProgramSelectablePins {
|
||||
@ -237,7 +238,8 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_WE517_TX "|" D_SENSOR_WE517_RX "|"
|
||||
D_SENSOR_AS608_TX "|" D_SENSOR_AS608_RX "|"
|
||||
D_SENSOR_SHELLY_DIMMER_BOOT0 "|" D_SENSOR_SHELLY_DIMMER_RST_INV "|"
|
||||
D_SENSOR_RC522_RST
|
||||
D_SENSOR_RC522_RST "|"
|
||||
D_SENSOR_P9813_CLK "|" D_SENSOR_P9813_DAT
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
@ -247,6 +249,7 @@ const char kSensorNamesFixed[] PROGMEM =
|
||||
#define MAX_A4988_MSS 3
|
||||
#define MAX_WEBCAM_DATA 8
|
||||
#define MAX_WEBCAM_HSD 3
|
||||
#define MAX_SM2135_DAT 4
|
||||
|
||||
const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
GPIO_NONE, // Not used
|
||||
@ -336,7 +339,12 @@ const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
#ifdef USE_WS2812
|
||||
#if (USE_WS2812_HARDWARE == NEO_HW_P9813)
|
||||
AGPIO(GPIO_P9813_CLK), // P9813 CLOCK
|
||||
AGPIO(GPIO_P9813_DAT), // P9813 DATA
|
||||
#else
|
||||
AGPIO(GPIO_WS2812), // WS2812 Led string
|
||||
#endif // NEO_HW_P9813
|
||||
#endif
|
||||
#ifdef USE_ARILUX_RF
|
||||
AGPIO(GPIO_ARIRFRCV), // AriLux RF Receive input
|
||||
@ -352,8 +360,8 @@ const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
AGPIO(GPIO_SM16716_SEL), // SM16716 SELECT
|
||||
#endif // USE_SM16716
|
||||
#ifdef USE_SM2135
|
||||
AGPIO(GPIO_SM2135_CLK), // SM2135 CLOCK
|
||||
AGPIO(GPIO_SM2135_DAT), // SM2135 DATA
|
||||
AGPIO(GPIO_SM2135_CLK), // SM2135 CLOCK
|
||||
AGPIO(GPIO_SM2135_DAT) + MAX_SM2135_DAT, // SM2135 DATA
|
||||
#endif // USE_SM2135
|
||||
#ifdef USE_TUYA_MCU
|
||||
AGPIO(GPIO_TUYA_TX), // Tuya Serial interface
|
||||
|
@ -20,6 +20,6 @@
|
||||
#ifndef _TASMOTA_VERSION_H_
|
||||
#define _TASMOTA_VERSION_H_
|
||||
|
||||
const uint32_t VERSION = 0x09010002;
|
||||
const uint32_t VERSION = 0x09020001;
|
||||
|
||||
#endif // _TASMOTA_VERSION_H_
|
||||
|
@ -1661,6 +1661,18 @@ bool HandleRootStatusRefresh(void)
|
||||
ExecuteWebCommand(svalue, SRC_WEBGUI);
|
||||
}
|
||||
#endif // USE_SONOFF_RF
|
||||
#ifdef USE_ZIGBEE
|
||||
WebGetArg("zbj", tmp, sizeof(tmp));
|
||||
if (strlen(tmp)) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("ZbPermitJoin"));
|
||||
ExecuteWebCommand(svalue, SRC_WEBGUI);
|
||||
}
|
||||
WebGetArg("zbr", tmp, sizeof(tmp));
|
||||
if (strlen(tmp)) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("ZbMap"));
|
||||
ExecuteWebCommand(svalue, SRC_WEBGUI);
|
||||
}
|
||||
#endif // USE_ZIGBEE
|
||||
WSContentBegin(200, CT_HTML);
|
||||
WSContentSend_P(PSTR("{t}"));
|
||||
XsnsCall(FUNC_WEB_SENSOR);
|
||||
@ -3005,34 +3017,28 @@ void HandleHttpCommand(void)
|
||||
}
|
||||
|
||||
WSContentBegin(200, CT_JSON);
|
||||
uint32_t curridx = TasmotaGlobal.web_log_index;
|
||||
uint32_t curridx = TasmotaGlobal.log_buffer_pointer;
|
||||
String svalue = Webserver->arg("cmnd");
|
||||
if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
|
||||
ExecuteWebCommand((char*)svalue.c_str(), SRC_WEBCOMMAND);
|
||||
if (TasmotaGlobal.web_log_index != curridx) {
|
||||
uint32_t counter = curridx;
|
||||
if (TasmotaGlobal.log_buffer_pointer != curridx) {
|
||||
WSContentSend_P(PSTR("{"));
|
||||
bool cflg = false;
|
||||
do {
|
||||
char* tmp;
|
||||
size_t len;
|
||||
GetLog(counter, &tmp, &len);
|
||||
if (len) {
|
||||
// [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
|
||||
char* JSON = (char*)memchr(tmp, '{', len);
|
||||
if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
|
||||
size_t JSONlen = len - (JSON - tmp);
|
||||
if (JSONlen > sizeof(TasmotaGlobal.mqtt_data)) { JSONlen = sizeof(TasmotaGlobal.mqtt_data); }
|
||||
char stemp[JSONlen];
|
||||
strlcpy(stemp, JSON +1, JSONlen -2);
|
||||
WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp);
|
||||
cflg = true;
|
||||
}
|
||||
uint32_t index = curridx;
|
||||
char* line;
|
||||
size_t len;
|
||||
while (GetLog(Settings.weblog_level, &index, &line, &len)) {
|
||||
// [14:49:36.123 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
|
||||
char* JSON = (char*)memchr(line, '{', len);
|
||||
if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
|
||||
size_t JSONlen = len - (JSON - line);
|
||||
if (JSONlen > sizeof(TasmotaGlobal.mqtt_data)) { JSONlen = sizeof(TasmotaGlobal.mqtt_data); }
|
||||
char stemp[JSONlen];
|
||||
strlcpy(stemp, JSON +1, JSONlen -2);
|
||||
WSContentSend_P(PSTR("%s%s"), (cflg) ? "," : "", stemp);
|
||||
cflg = true;
|
||||
}
|
||||
counter++;
|
||||
counter &= 0xFF;
|
||||
if (!counter) counter++; // Skip 0 as it is not allowed
|
||||
} while (counter != TasmotaGlobal.web_log_index);
|
||||
}
|
||||
WSContentSend_P(PSTR("}"));
|
||||
} else {
|
||||
WSContentSend_P(PSTR("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}"));
|
||||
@ -3066,9 +3072,6 @@ void HandleConsole(void)
|
||||
|
||||
void HandleConsoleRefresh(void)
|
||||
{
|
||||
bool cflg = true;
|
||||
uint32_t counter = 0; // Initial start, should never be 0 again
|
||||
|
||||
String svalue = Webserver->arg("c1");
|
||||
if (svalue.length() && (svalue.length() < MQTT_MAX_PACKET_SIZE)) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_COMMAND "%s"), svalue.c_str());
|
||||
@ -3077,34 +3080,24 @@ void HandleConsoleRefresh(void)
|
||||
|
||||
char stmp[8];
|
||||
WebGetArg("c2", stmp, sizeof(stmp));
|
||||
if (strlen(stmp)) { counter = atoi(stmp); }
|
||||
uint32_t index = 0; // Initial start, dump all
|
||||
if (strlen(stmp)) { index = atoi(stmp); }
|
||||
|
||||
WSContentBegin(200, CT_PLAIN);
|
||||
WSContentSend_P(PSTR("%d}1%d}1"), TasmotaGlobal.web_log_index, Web.reset_web_log_flag);
|
||||
WSContentSend_P(PSTR("%d}1%d}1"), TasmotaGlobal.log_buffer_pointer, Web.reset_web_log_flag);
|
||||
if (!Web.reset_web_log_flag) {
|
||||
counter = 0;
|
||||
index = 0;
|
||||
Web.reset_web_log_flag = true;
|
||||
}
|
||||
if (counter != TasmotaGlobal.web_log_index) {
|
||||
if (!counter) {
|
||||
counter = TasmotaGlobal.web_log_index;
|
||||
cflg = false;
|
||||
}
|
||||
do {
|
||||
char* tmp;
|
||||
size_t len;
|
||||
GetLog(counter, &tmp, &len);
|
||||
if (len) {
|
||||
if (len > sizeof(TasmotaGlobal.mqtt_data) -2) { len = sizeof(TasmotaGlobal.mqtt_data); }
|
||||
char stemp[len +1];
|
||||
strlcpy(stemp, tmp, len);
|
||||
WSContentSend_P(PSTR("%s%s"), (cflg) ? "\n" : "", stemp);
|
||||
cflg = true;
|
||||
}
|
||||
counter++;
|
||||
counter &= 0xFF;
|
||||
if (!counter) { counter++; } // Skip log index 0 as it is not allowed
|
||||
} while (counter != TasmotaGlobal.web_log_index);
|
||||
bool cflg = (index);
|
||||
char* line;
|
||||
size_t len;
|
||||
while (GetLog(Settings.weblog_level, &index, &line, &len)) {
|
||||
if (len > sizeof(TasmotaGlobal.mqtt_data) -2) { len = sizeof(TasmotaGlobal.mqtt_data); }
|
||||
char stemp[len +1];
|
||||
strlcpy(stemp, line, len);
|
||||
WSContentSend_P(PSTR("%s%s"), (cflg) ? "\n" : "", stemp);
|
||||
cflg = true;
|
||||
}
|
||||
WSContentSend_P(PSTR("}1"));
|
||||
WSContentEnd();
|
||||
|
@ -291,18 +291,19 @@ void MqttUnsubscribe(const char *topic)
|
||||
MqttUnsubscribeLib(topic);
|
||||
}
|
||||
|
||||
void MqttPublishLogging(const char *mxtime)
|
||||
{
|
||||
char saved_mqtt_data[strlen(TasmotaGlobal.mqtt_data) +1];
|
||||
memcpy(saved_mqtt_data, TasmotaGlobal.mqtt_data, sizeof(saved_mqtt_data));
|
||||
void MqttPublishLoggingAsync(void) {
|
||||
static uint32_t index = 1;
|
||||
|
||||
// ResponseTime_P(PSTR(",\"Log\":{\"%s\"}}"), TasmotaGlobal.log_data); // Will fail as some messages contain JSON
|
||||
Response_P(PSTR("%s%s"), mxtime, TasmotaGlobal.log_data); // No JSON and ugly!!
|
||||
char stopic[TOPSZ];
|
||||
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, PSTR("LOGGING"));
|
||||
MqttPublishLib(stopic, false);
|
||||
if (!Settings.flag.mqtt_enabled) { return; } // SetOption3 - Enable MQTT
|
||||
|
||||
memcpy(TasmotaGlobal.mqtt_data, saved_mqtt_data, sizeof(saved_mqtt_data));
|
||||
char* line;
|
||||
size_t len;
|
||||
while (GetLog(Settings.mqttlog_level, &index, &line, &len)) {
|
||||
strlcpy(TasmotaGlobal.mqtt_data, line, len); // No JSON and ugly!!
|
||||
char stopic[TOPSZ];
|
||||
GetTopic_P(stopic, STAT, TasmotaGlobal.mqtt_topic, PSTR("LOGGING"));
|
||||
MqttPublishLib(stopic, false);
|
||||
}
|
||||
}
|
||||
|
||||
void MqttPublish(const char* topic, bool retained)
|
||||
|
@ -2137,7 +2137,10 @@ bool LightApplyFade(void) { // did the value chanegd and needs to be applied
|
||||
// compute the duration of the animation
|
||||
// Note: Settings.light_speed is the number of half-seconds for a 100% fade,
|
||||
// i.e. light_speed=1 means 1024 steps in 500ms
|
||||
Light.fade_duration = (distance * Settings.light_speed * 500) / 1023;
|
||||
Light.fade_duration = Settings.light_speed * 500;
|
||||
if (!Settings.flag5.fade_fixed_duration) {
|
||||
Light.fade_duration = (distance * Light.fade_duration) / 1023; // time is proportional to distance, except with SO117
|
||||
}
|
||||
if (Settings.save_data) {
|
||||
// Also postpone the save_data for the duration of the Fade (in seconds)
|
||||
uint32_t delay_seconds = 1 + (Light.fade_duration + 999) / 1000; // add one more second
|
||||
|
@ -67,8 +67,8 @@ keywords if then else endif, or, and are better readable for beginners (others m
|
||||
|
||||
#define MAX_SARRAY_NUM 32
|
||||
|
||||
uint32_t EncodeLightId(uint8_t relay_id);
|
||||
uint32_t DecodeLightId(uint32_t hue_id);
|
||||
//uint32_t EncodeLightId(uint8_t relay_id);
|
||||
//uint32_t DecodeLightId(uint32_t hue_id);
|
||||
|
||||
#ifdef USE_UNISHOX_COMPRESSION
|
||||
#define USE_SCRIPT_COMPRESSION
|
||||
@ -108,7 +108,11 @@ uint32_t DecodeLightId(uint32_t hue_id);
|
||||
#pragma message "script 24c256 file option used"
|
||||
#else
|
||||
//#warning "EEP_SCRIPT_SIZE also needs USE_24C256"
|
||||
#if EEP_SCRIPT_SIZE==SPI_FLASH_SEC_SIZE
|
||||
#pragma message "internal eeprom script buffer used"
|
||||
#else
|
||||
#pragma message "internal compressed eeprom script buffer used"
|
||||
#endif
|
||||
//#define USE_24C256
|
||||
#endif
|
||||
#endif // EEP_SCRIPT_SIZE
|
||||
@ -119,7 +123,7 @@ uint32_t DecodeLightId(uint32_t hue_id);
|
||||
#endif // USE_UNISHOX_COMPRESSION
|
||||
|
||||
|
||||
#ifdef USE_SCRIPT_COMPRESSION
|
||||
//#ifdef USE_SCRIPT_COMPRESSION
|
||||
#include <unishox.h>
|
||||
|
||||
#define SCRIPT_COMPRESS compressor.unishox_compress
|
||||
@ -127,7 +131,8 @@ uint32_t DecodeLightId(uint32_t hue_id);
|
||||
#ifndef UNISHOXRSIZE
|
||||
#define UNISHOXRSIZE 2560
|
||||
#endif
|
||||
#endif // USE_SCRIPT_COMPRESSION
|
||||
|
||||
//#endif // USE_SCRIPT_COMPRESSION
|
||||
|
||||
#ifndef STASK_PRIO
|
||||
#define STASK_PRIO 1
|
||||
@ -158,6 +163,51 @@ void Script_ticker4_end(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// EEPROM MACROS
|
||||
// i2c eeprom
|
||||
|
||||
#if defined(ALT_EEPROM) && !defined(ESP32)
|
||||
#undef EEP_WRITE
|
||||
#undef EEP_READ
|
||||
#undef EEP_INIT
|
||||
#define EEP_WRITE(A,B,C) alt_eeprom_writeBytes(A, B, (uint8_t*)C);
|
||||
#define EEP_READ(A,B,C) alt_eeprom_readBytes(A, B, (uint8_t*)C);
|
||||
#define EEP_INIT(A) alt_eeprom_init(A)
|
||||
|
||||
#if EEP_SCRIPT_SIZE>6500
|
||||
#undef EEP_SCRIPT_SIZE
|
||||
#define EEP_SCRIPT_SIZE 6500
|
||||
#endif
|
||||
|
||||
uint32_t eeprom_block;
|
||||
|
||||
// these support only one 4 k block below EEPROM this steals 4k of application area
|
||||
uint32_t alt_eeprom_init(uint32_t size) {
|
||||
//EEPROM.begin(size);
|
||||
eeprom_block = (uint32_t)&_FS_end - 0x40200000 - SPI_FLASH_SEC_SIZE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void alt_eeprom_writeBytes(uint32_t adr, uint32_t len, uint8_t *buf) {
|
||||
uint32_t *lwp=(uint32_t*)buf;
|
||||
ESP.flashEraseSector(eeprom_block / SPI_FLASH_SEC_SIZE);
|
||||
ESP.flashWrite(eeprom_block , lwp, SPI_FLASH_SEC_SIZE);
|
||||
}
|
||||
|
||||
void alt_eeprom_readBytes(uint32_t adr, uint32_t len, uint8_t *buf) {
|
||||
uint32_t *lwp=(uint32_t*)buf;
|
||||
ESP.flashRead(eeprom_block , lwp, SPI_FLASH_SEC_SIZE);
|
||||
}
|
||||
#else
|
||||
#undef EEP_WRITE
|
||||
#undef EEP_READ
|
||||
#undef EEP_INIT
|
||||
#define EEP_WRITE(A,B,C) eeprom_writeBytes(A, B, (uint8_t*)C);
|
||||
#define EEP_READ(A,B,C) eeprom_readBytes(A, B, (uint8_t*)C);
|
||||
#define EEP_INIT(A) eeprom_init(A)
|
||||
#endif // ALT_EEPROM
|
||||
|
||||
|
||||
|
||||
#if defined(LITTLEFS_SCRIPT_SIZE) || (USE_SCRIPT_FATFS==-1)
|
||||
#ifdef ESP32
|
||||
@ -516,10 +566,7 @@ void RulesTeleperiod(void) {
|
||||
if (bitRead(Settings.rule_enabled, 0) && TasmotaGlobal.mqtt_data[0]) Run_Scripter(">T", 2, TasmotaGlobal.mqtt_data);
|
||||
}
|
||||
|
||||
// EEPROM MACROS
|
||||
// i2c eeprom
|
||||
#define EEP_WRITE(A,B,C) eeprom_writeBytes(A, B, (uint8_t*)C);
|
||||
#define EEP_READ(A,B,C) eeprom_readBytes(A, B, (uint8_t*)C);
|
||||
|
||||
|
||||
|
||||
#define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++;
|
||||
@ -1537,7 +1584,7 @@ float fvar;
|
||||
char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp, JsonParserObject *jo) {
|
||||
uint16_t count,len = 0;
|
||||
uint8_t nres = 0;
|
||||
char vname[32];
|
||||
char vname[64];
|
||||
float fvar = 0;
|
||||
tind->index = 0;
|
||||
tind->bits.data = 0;
|
||||
@ -1666,7 +1713,7 @@ char *isvar(char *lp, uint8_t *vtype, struct T_INDEX *tind, float *fp, char *sp,
|
||||
|
||||
if (jo) {
|
||||
// look for json input
|
||||
char jvname[32];
|
||||
char jvname[64];
|
||||
strcpy(jvname, vname);
|
||||
const char* str_value;
|
||||
uint8_t aindex;
|
||||
@ -1872,6 +1919,19 @@ chknext:
|
||||
fvar = xPortGetCoreID();
|
||||
goto exit;
|
||||
}
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
if (!strncmp(vname, "c2ps(", 5)) {
|
||||
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0);
|
||||
while (*lp==' ') lp++;
|
||||
float fvar1;
|
||||
lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0);
|
||||
fvar = core2_setaxppin(fvar, fvar1);
|
||||
lp++;
|
||||
len=0;
|
||||
goto exit;
|
||||
}
|
||||
#endif // USE_M5STACK_CORE2
|
||||
|
||||
#ifdef USE_SCRIPT_TASK
|
||||
if (!strncmp(vname, "ct(", 3)) {
|
||||
lp = GetNumericArgument(lp + 3, OPER_EQU, &fvar, 0);
|
||||
@ -2620,7 +2680,7 @@ chknext:
|
||||
len++;
|
||||
goto exit;
|
||||
}
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH))
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
|
||||
if (!strncmp(vname, "pl(", 3)) {
|
||||
char path[SCRIPT_MAXSSIZE];
|
||||
lp = GetStringArgument(lp + 3, OPER_EQU, path, 0);
|
||||
@ -2813,7 +2873,7 @@ chknext:
|
||||
len = 0;
|
||||
goto strexit;
|
||||
}
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH))
|
||||
#if defined(ESP32) && (defined(USE_I2S_AUDIO) || defined(USE_TTGO_WATCH) || defined(USE_M5STACK_CORE2))
|
||||
if (!strncmp(vname, "say(", 4)) {
|
||||
char text[SCRIPT_MAXSSIZE];
|
||||
lp = GetStringArgument(lp + 4, OPER_EQU, text, 0);
|
||||
@ -3114,7 +3174,7 @@ chknext:
|
||||
goto exit;
|
||||
}
|
||||
#endif // USE_TTGO_WATCH
|
||||
#if defined(USE_TTGO_WATCH) && defined(USE_FT5206)
|
||||
#if defined(USE_FT5206)
|
||||
if (!strncmp(vname, "wtch(", 5)) {
|
||||
lp = GetNumericArgument(lp + 5, OPER_EQU, &fvar, 0);
|
||||
fvar = Touch_Status(fvar);
|
||||
@ -3734,22 +3794,45 @@ void esp32_beep(int32_t freq ,uint32_t len) {
|
||||
xTimerChangePeriod( beep_th, ticks, 10);
|
||||
}
|
||||
}
|
||||
#endif // ESP32
|
||||
|
||||
void esp32_pwm(int32_t value) {
|
||||
uint8_t pwmpin[5];
|
||||
|
||||
void esp_pwm(int32_t value, uint32 freq, uint32_t channel) {
|
||||
if (channel < 1 || channel > 3) channel = 1;
|
||||
#ifdef ESP32
|
||||
channel+=7;
|
||||
if (value < 0) {
|
||||
if (value <= -64) value = 0;
|
||||
ledcSetup(7, 4000, 10);
|
||||
ledcAttachPin(-value, 7);
|
||||
ledcWrite(7, 0);
|
||||
// set range to 10 bit
|
||||
ledcSetup(channel, freq, 10);
|
||||
ledcAttachPin(-value, channel);
|
||||
ledcWrite(channel, 0);
|
||||
} else {
|
||||
if (value > 1023) {
|
||||
value = 1023;
|
||||
}
|
||||
ledcWrite(7, value);
|
||||
ledcWrite(channel, value);
|
||||
}
|
||||
#else
|
||||
// esp8266 default to range 0-1023
|
||||
channel-=1;
|
||||
if (value < 0) {
|
||||
if (value <= -64) value = 0;
|
||||
pwmpin[channel] = -value;
|
||||
pinMode(pwmpin[channel], OUTPUT);
|
||||
analogWriteFreq(freq);
|
||||
analogWrite(pwmpin[channel], 0);
|
||||
} else {
|
||||
if (value > 1023) {
|
||||
value = 1023;
|
||||
}
|
||||
analogWrite(pwmpin[channel],value);
|
||||
}
|
||||
#endif // ESP32
|
||||
}
|
||||
|
||||
#endif // ESP32
|
||||
|
||||
|
||||
//#define IFTHEN_DEBUG
|
||||
|
||||
@ -4164,14 +4247,34 @@ int16_t Run_script_sub(const char *type, int8_t tlen, JsonParserObject *jo) {
|
||||
lp++;
|
||||
goto next_line;
|
||||
}
|
||||
else if (!strncmp(lp, "pwm(", 4)) {
|
||||
lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, 0);
|
||||
#endif //ESP32
|
||||
|
||||
else if (!strncmp(lp, "pwm", 3)) {
|
||||
lp += 3;
|
||||
uint8_t channel = 1;
|
||||
if (*(lp+1)=='(') {
|
||||
channel = *lp & 7;
|
||||
if (channel > 5) {
|
||||
channel = 5;
|
||||
}
|
||||
lp += 2;
|
||||
} else {
|
||||
if (*lp=='(') {
|
||||
lp++;
|
||||
} else {
|
||||
goto next_line;
|
||||
}
|
||||
}
|
||||
lp = GetNumericArgument(lp, OPER_EQU, &fvar, 0);
|
||||
SCRIPT_SKIP_SPACES
|
||||
esp32_pwm(fvar);
|
||||
float fvar1=4000;
|
||||
if (*lp!=')') {
|
||||
lp = GetNumericArgument(lp, OPER_EQU, &fvar1, 0);
|
||||
}
|
||||
esp_pwm(fvar, fvar1, channel);
|
||||
lp++;
|
||||
goto next_line;
|
||||
}
|
||||
#endif //ESP32
|
||||
else if (!strncmp(lp, "wcs", 3)) {
|
||||
lp+=4;
|
||||
// skip one space after cmd
|
||||
@ -5116,7 +5219,16 @@ void SaveScript(void) {
|
||||
|
||||
#ifdef EEP_SCRIPT_SIZE
|
||||
if (glob_script_mem.flags&1) {
|
||||
#if EEP_SCRIPT_SIZE==SPI_FLASH_SEC_SIZE
|
||||
EEP_WRITE(0, EEP_SCRIPT_SIZE, glob_script_mem.script_ram);
|
||||
#else
|
||||
char *ucs;
|
||||
ucs = (char*)calloc(SPI_FLASH_SEC_SIZE + 4, 1);
|
||||
if (!script_compress(ucs,EEP_SCRIPT_SIZE-1)) {
|
||||
EEP_WRITE(0, EEP_SCRIPT_SIZE, ucs);
|
||||
}
|
||||
if (ucs) free(ucs);
|
||||
#endif
|
||||
}
|
||||
#endif // EEP_SCRIPT_SIZE
|
||||
|
||||
@ -5198,6 +5310,21 @@ void ScriptSaveSettings(void) {
|
||||
SaveScriptEnd();
|
||||
}
|
||||
|
||||
//
|
||||
uint32_t script_compress(char *dest, uint32_t size) {
|
||||
//AddLog_P(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram));
|
||||
uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), dest, size);
|
||||
if (len_compressed > 0) {
|
||||
dest[len_compressed] = 0;
|
||||
AddLog_P(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram));
|
||||
return 0;
|
||||
} else {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
//#endif // USE_SCRIPT_COMPRESSION
|
||||
|
||||
void SaveScriptEnd(void) {
|
||||
|
||||
#ifdef USE_SCRIPT_GLOBVARS
|
||||
@ -5212,20 +5339,11 @@ void SaveScriptEnd(void) {
|
||||
}
|
||||
|
||||
#ifdef USE_SCRIPT_COMPRESSION
|
||||
//AddLog_P(LOG_LEVEL_INFO,PSTR("in string: %s len = %d"),glob_script_mem.script_ram,strlen(glob_script_mem.script_ram));
|
||||
uint32_t len_compressed = SCRIPT_COMPRESS(glob_script_mem.script_ram, strlen(glob_script_mem.script_ram), Settings.rules[0], MAX_SCRIPT_SIZE-1);
|
||||
if (len_compressed > 0) {
|
||||
Settings.rules[0][len_compressed] = 0;
|
||||
AddLog_P(LOG_LEVEL_INFO,PSTR("script compressed to %d bytes = %d %%"),len_compressed,len_compressed * 100 / strlen(glob_script_mem.script_ram));
|
||||
} else {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("script compress error: %d"), len_compressed);
|
||||
}
|
||||
script_compress(Settings.rules[0],MAX_SCRIPT_SIZE-1);
|
||||
#endif // USE_SCRIPT_COMPRESSION
|
||||
|
||||
if (bitRead(Settings.rule_enabled, 0)) {
|
||||
|
||||
|
||||
|
||||
int16_t res = Init_Scripter();
|
||||
if (res) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR("script init error: %d"), res);
|
||||
@ -5728,24 +5846,26 @@ bool Script_SubCmd(void) {
|
||||
if (!bitRead(Settings.rule_enabled, 0)) return false;
|
||||
|
||||
if (tasm_cmd_activ) return false;
|
||||
//AddLog_P(LOG_LEVEL_INFO,PSTR(">> %s, %s, %d, %d "),XdrvMailbox.topic, XdrvMailbox.data, XdrvMailbox.payload, XdrvMailbox.index);
|
||||
|
||||
char command[CMDSZ];
|
||||
strlcpy(command, XdrvMailbox.topic, CMDSZ);
|
||||
uint32_t pl = XdrvMailbox.payload;
|
||||
char pld[64];
|
||||
strlcpy(pld, XdrvMailbox.data, sizeof(pld));
|
||||
if (XdrvMailbox.index > 1) {
|
||||
char ind[2];
|
||||
ind[0] = XdrvMailbox.index | 0x30;
|
||||
ind[1] = 0;
|
||||
strcat(command, ind);
|
||||
}
|
||||
|
||||
int32_t pl = XdrvMailbox.payload;
|
||||
|
||||
char cmdbuff[128];
|
||||
char *cp = cmdbuff;
|
||||
*cp++ = '#';
|
||||
strcpy(cp, XdrvMailbox.topic);
|
||||
uint8_t tlen = strlen(XdrvMailbox.topic);
|
||||
strcpy(cp, command);
|
||||
uint8_t tlen = strlen(command);
|
||||
cp += tlen;
|
||||
if (XdrvMailbox.index > 0) {
|
||||
*cp++ = XdrvMailbox.index | 0x30;
|
||||
tlen++;
|
||||
}
|
||||
if ((XdrvMailbox.payload>0) || (XdrvMailbox.data_len>0)) {
|
||||
if (XdrvMailbox.data_len>0) {
|
||||
*cp++ = '(';
|
||||
strncpy(cp, XdrvMailbox.data,XdrvMailbox.data_len);
|
||||
cp += XdrvMailbox.data_len;
|
||||
@ -5755,12 +5875,16 @@ bool Script_SubCmd(void) {
|
||||
//toLog(cmdbuff);
|
||||
uint32_t res = Run_Scripter(cmdbuff, tlen + 1, 0);
|
||||
//AddLog_P(LOG_LEVEL_INFO,">>%d",res);
|
||||
if (res) return false;
|
||||
if (res) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (pl>=0) {
|
||||
Response_P(S_JSON_COMMAND_NVALUE, command, pl);
|
||||
cp=XdrvMailbox.data;
|
||||
while (*cp==' ') cp++;
|
||||
if (isdigit(*cp) || *cp=='-') {
|
||||
Response_P(S_JSON_COMMAND_NVALUE, command, XdrvMailbox.payload);
|
||||
} else {
|
||||
Response_P(S_JSON_COMMAND_SVALUE, command, pld);
|
||||
Response_P(S_JSON_COMMAND_SVALUE, command, XdrvMailbox.data);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -6990,7 +7114,7 @@ exgc:
|
||||
WSContentSend_PD("['");
|
||||
char lbl[16];
|
||||
if (todflg>=0) {
|
||||
sprintf(lbl, "%d", todflg / divflg);
|
||||
sprintf(lbl, "%d:%02d", todflg / divflg, (todflg % divflg) * (60 / divflg) );
|
||||
todflg++;
|
||||
if (todflg >= entries) {
|
||||
todflg = 0;
|
||||
@ -7395,9 +7519,10 @@ bool Xdrv10(uint8_t function)
|
||||
#endif //USE_BUTTON_EVENT
|
||||
|
||||
#ifdef EEP_SCRIPT_SIZE
|
||||
if (eeprom_init(EEP_SCRIPT_SIZE)) {
|
||||
// found 32kb eeprom
|
||||
if (EEP_INIT(EEP_SCRIPT_SIZE)) {
|
||||
// found 32kb eeprom,
|
||||
char *script;
|
||||
#if EEP_SCRIPT_SIZE==SPI_FLASH_SEC_SIZE
|
||||
script = (char*)calloc(EEP_SCRIPT_SIZE + 4, 1);
|
||||
if (!script) break;
|
||||
glob_script_mem.script_ram = script;
|
||||
@ -7407,6 +7532,28 @@ bool Xdrv10(uint8_t function)
|
||||
memset(script, EEP_SCRIPT_SIZE, 0);
|
||||
}
|
||||
script[EEP_SCRIPT_SIZE - 1] = 0;
|
||||
#else
|
||||
char *ucs;
|
||||
ucs = (char*)calloc(SPI_FLASH_SEC_SIZE + 4, 1);
|
||||
if (!ucs) break;
|
||||
EEP_READ(0, SPI_FLASH_SEC_SIZE, ucs);
|
||||
if (*ucs==0xff) {
|
||||
memset(ucs, SPI_FLASH_SEC_SIZE, 0);
|
||||
}
|
||||
ucs[SPI_FLASH_SEC_SIZE - 1] = 0;
|
||||
|
||||
script = (char*)calloc(EEP_SCRIPT_SIZE + 4, 1);
|
||||
if (!script) break;
|
||||
glob_script_mem.script_ram = script;
|
||||
glob_script_mem.script_size = EEP_SCRIPT_SIZE;
|
||||
|
||||
int32_t len_decompressed;
|
||||
len_decompressed = SCRIPT_DECOMPRESS(ucs, strlen(ucs), glob_script_mem.script_ram, glob_script_mem.script_size);
|
||||
if (len_decompressed>0) glob_script_mem.script_ram[len_decompressed] = 0;
|
||||
|
||||
if (ucs) free(ucs);
|
||||
|
||||
#endif
|
||||
// use rules storage for permanent vars
|
||||
glob_script_mem.script_pram = (uint8_t*)Settings.rules[0];
|
||||
glob_script_mem.script_pram_size = MAX_SCRIPT_SIZE;
|
||||
@ -7422,7 +7569,7 @@ bool Xdrv10(uint8_t function)
|
||||
// fs on SD card
|
||||
#ifdef ESP32
|
||||
if (PinUsed(GPIO_SPI_MOSI) && PinUsed(GPIO_SPI_MISO) && PinUsed(GPIO_SPI_CLK)) {
|
||||
SPI.begin(Pin(GPIO_SPI_CLK),Pin(GPIO_SPI_MISO),Pin(GPIO_SPI_MOSI), -1);
|
||||
SPI.begin(Pin(GPIO_SPI_CLK), Pin(GPIO_SPI_MISO), Pin(GPIO_SPI_MOSI), -1);
|
||||
}
|
||||
#endif // ESP32
|
||||
fsp = &SD;
|
||||
|
@ -2089,8 +2089,8 @@ uint32_t Touch_Status(uint32_t sel) {
|
||||
|
||||
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
void Touch_MQTT(uint8_t index, const char *cp) {
|
||||
ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, buttons[index]->vpower.on_off);
|
||||
void Touch_MQTT(uint8_t index, const char *cp, uint32_t val) {
|
||||
ResponseTime_P(PSTR(",\"FT5206\":{\"%s%d\":\"%d\"}}"), cp, index+1, val);
|
||||
MqttPublishTeleSensor();
|
||||
}
|
||||
|
||||
@ -2100,6 +2100,10 @@ void Touch_RDW_BUTT(uint32_t count, uint32_t pwr) {
|
||||
else buttons[count]->vpower.on_off = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
uint8_t tbstate[3];
|
||||
#endif
|
||||
|
||||
// check digitizer hit
|
||||
void Touch_Check(void(*rotconvert)(int16_t *x, int16_t *y)) {
|
||||
uint16_t temp;
|
||||
@ -2113,6 +2117,26 @@ uint8_t vbutt=0;
|
||||
|
||||
if (renderer) {
|
||||
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
// handle 3 built in touch buttons
|
||||
uint16_t xcenter = 80;
|
||||
#define TDELTA 30
|
||||
#define TYPOS 275
|
||||
|
||||
for (uint32_t tbut = 0; tbut < 3; tbut++) {
|
||||
if (pLoc.x>(xcenter-TDELTA) && pLoc.x<(xcenter+TDELTA) && pLoc.y>(TYPOS-TDELTA) && pLoc.y<(TYPOS+TDELTA)) {
|
||||
// hit a button
|
||||
if (!(tbstate[tbut] & 1)) {
|
||||
// pressed
|
||||
tbstate[tbut] |= 1;
|
||||
//AddLog_P(LOG_LEVEL_INFO, PSTR("tbut: %d pressed"), tbut);
|
||||
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
|
||||
}
|
||||
}
|
||||
xcenter += 100;
|
||||
}
|
||||
#endif
|
||||
|
||||
rotconvert(&pLoc.x, &pLoc.y);
|
||||
|
||||
//AddLog_P(LOG_LEVEL_INFO, PSTR("touch %d - %d"), pLoc.x, pLoc.y);
|
||||
@ -2142,7 +2166,7 @@ uint8_t vbutt=0;
|
||||
cp="PBT";
|
||||
}
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
|
||||
Touch_MQTT(count,cp);
|
||||
Touch_MQTT(count, cp, buttons[count]->vpower.on_off);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2156,6 +2180,16 @@ uint8_t vbutt=0;
|
||||
}
|
||||
} else {
|
||||
// no hit
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
for (uint32_t tbut = 0; tbut < 3; tbut++) {
|
||||
if (tbstate[tbut] & 1) {
|
||||
// released
|
||||
tbstate[tbut] &= 0xfe;
|
||||
Touch_MQTT(tbut, "BIB", tbstate[tbut] & 1);
|
||||
//AddLog_P(LOG_LEVEL_INFO, PSTR("tbut: %d released"), tbut);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||
if (buttons[count]) {
|
||||
buttons[count]->press(false);
|
||||
@ -2164,7 +2198,7 @@ uint8_t vbutt=0;
|
||||
if (buttons[count]->vpower.is_pushbutton) {
|
||||
// push button
|
||||
buttons[count]->vpower.on_off = 0;
|
||||
Touch_MQTT(count,"PBT");
|
||||
Touch_MQTT(count,"PBT", buttons[count]->vpower.on_off);
|
||||
buttons[count]->xdrawButton(buttons[count]->vpower.on_off);
|
||||
}
|
||||
}
|
||||
|
@ -1214,6 +1214,13 @@ void TuyaSetTime(void) {
|
||||
|
||||
uint16_t payload_len = 8;
|
||||
uint8_t payload_buffer[8];
|
||||
uint8_t tuya_day_of_week;
|
||||
if (RtcTime.day_of_week == 1) {
|
||||
tuya_day_of_week = 7;
|
||||
} else {
|
||||
tuya_day_of_week = RtcTime.day_of_week-1;
|
||||
}
|
||||
|
||||
payload_buffer[0] = 0x01;
|
||||
payload_buffer[1] = RtcTime.year %100;
|
||||
payload_buffer[2] = RtcTime.month;
|
||||
@ -1221,7 +1228,7 @@ void TuyaSetTime(void) {
|
||||
payload_buffer[4] = RtcTime.hour;
|
||||
payload_buffer[5] = RtcTime.minute;
|
||||
payload_buffer[6] = RtcTime.second;
|
||||
payload_buffer[7] = RtcTime.day_of_week;
|
||||
payload_buffer[7] = tuya_day_of_week; //1 for Monday in TUYA Doc
|
||||
|
||||
TuyaSendCmd(TUYA_CMD_SET_TIME, payload_buffer, payload_len);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ void HueRespondToMSearch(void)
|
||||
snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE));
|
||||
}
|
||||
// Do not use AddLog_P( here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9
|
||||
PrepLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"),
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_HUE " %s " D_TO " %s:%d"),
|
||||
message, udp_remote_ip.toString().c_str(), udp_remote_port);
|
||||
|
||||
udp_response_mutex = false;
|
||||
|
@ -75,7 +75,7 @@ void WemoRespondToMSearch(int echo_type)
|
||||
snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE));
|
||||
}
|
||||
// Do not use AddLog_P( here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9
|
||||
PrepLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"),
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_WEMO " " D_JSON_TYPE " %d, %s " D_TO " %s:%d"),
|
||||
echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port);
|
||||
|
||||
udp_response_mutex = false;
|
||||
|
@ -234,14 +234,18 @@ private:
|
||||
int _deviceId;
|
||||
|
||||
String WemoSerialnumber(void) {
|
||||
char serial[18];
|
||||
char serial[20];
|
||||
|
||||
snprintf_P(serial, sizeof(serial), PSTR("201612K%08X-%d"), ESP_getChipId(), _deviceId);
|
||||
char index[8] = { 0 };
|
||||
if (_deviceId > 1) { // Keep backward compatibility
|
||||
snprintf_P(index, sizeof(index), PSTR("%02X"), _deviceId);
|
||||
}
|
||||
snprintf_P(serial, sizeof(serial), PSTR("201612K%08X%s"), ESP_getChipId(), index);
|
||||
return String(serial);
|
||||
}
|
||||
|
||||
String WemoUuid(void) {
|
||||
char uuid[29];
|
||||
char uuid[32];
|
||||
|
||||
snprintf_P(uuid, sizeof(uuid), PSTR("Socket-1_0-%s"), WemoSerialnumber().c_str());
|
||||
return String(uuid);
|
||||
@ -297,8 +301,8 @@ public:
|
||||
snprintf_P(message, sizeof(message), PSTR(D_FAILED_TO_SEND_RESPONSE));
|
||||
}
|
||||
// Do not use AddLog_P here (interrupt routine) if syslog or mqttlog is enabled. UDP/TCP will force exception 9
|
||||
PrepLog_P(LOG_LEVEL_DEBUG, PSTR("WMO: WeMo Type %d, %s to %s:%d"),
|
||||
echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port);
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("WMO: WeMo Type %d, %s to %s:%d"),
|
||||
echo_type, message, udp_remote_ip.toString().c_str(), udp_remote_port);
|
||||
}
|
||||
|
||||
void HandleServerLoop() {
|
||||
|
@ -90,6 +90,10 @@ public:
|
||||
bool recv_until = false; // ignore all messages until the received frame fully matches
|
||||
bool eeprom_present = false; // is the ZBBridge EEPROM present?
|
||||
bool eeprom_ready = false; // is the ZBBridge EEPROM formatted and ready?
|
||||
// Zigbee mapping
|
||||
bool mapping_in_progress = false; // is there a mapping in progress
|
||||
bool mapping_ready = false; // do we have mapping information ready
|
||||
uint32_t mapping_end_time = 0;
|
||||
|
||||
uint8_t on_error_goto = ZIGBEE_LABEL_ABORT; // on error goto label, 99 default to abort
|
||||
uint8_t on_timeout_goto = ZIGBEE_LABEL_ABORT; // on timeout goto label, 99 default to abort
|
||||
|
@ -717,6 +717,7 @@ public:
|
||||
// sequence number for Zigbee frames
|
||||
uint16_t shortaddr; // unique key if not null, or unspecified if null
|
||||
uint8_t seqNumber;
|
||||
bool is_router; // flag used by ZbMap to distibguish routers from end-devices
|
||||
bool hidden;
|
||||
bool reachable;
|
||||
// Light information for Hue integration integration, last known values
|
||||
@ -742,6 +743,7 @@ public:
|
||||
attr_list(),
|
||||
shortaddr(_shortaddr),
|
||||
seqNumber(0),
|
||||
is_router(false),
|
||||
hidden(false),
|
||||
reachable(false),
|
||||
data(),
|
||||
@ -768,6 +770,10 @@ public:
|
||||
inline bool getReachable(void) const { return reachable; }
|
||||
inline bool getPower(uint8_t ep =0) const;
|
||||
|
||||
inline bool isRouter(void) const { return is_router; }
|
||||
inline bool isCoordinator(void) const { return 0x0000 == shortaddr; }
|
||||
inline void setRouter(bool router) { is_router = router; }
|
||||
|
||||
inline void setLQI(uint8_t _lqi) { lqi = _lqi; }
|
||||
inline void setBatteryPercent(uint8_t bp) { batterypercent = bp; }
|
||||
|
||||
|
@ -304,7 +304,9 @@ void loadZigbeeDevices(bool dump_only = false) {
|
||||
AddLog_P(LOG_LEVEL_ERROR, PSTR(D_LOG_ZIGBEE "Cannot allocate 4KB buffer"));
|
||||
return;
|
||||
}
|
||||
ZigbeeRead(&spi_buffer, z_spi_len);
|
||||
#ifdef USE_TFS
|
||||
TfsLoadFile("/zb", spi_buffer, z_spi_len);
|
||||
#endif
|
||||
z_dev_start = spi_buffer;
|
||||
#endif // ESP32
|
||||
Z_Flashentry flashdata;
|
||||
@ -367,7 +369,9 @@ void saveZigbeeDevices(void) {
|
||||
ESP.flashRead(z_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE);
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
ZigbeeRead(&spi_buffer, z_spi_len);
|
||||
#ifdef USE_TFS
|
||||
TfsLoadFile("/zb", spi_buffer, z_spi_len);
|
||||
#endif
|
||||
#endif // ESP32
|
||||
|
||||
Z_Flashentry *flashdata = (Z_Flashentry*)(spi_buffer + z_block_offset);
|
||||
@ -385,7 +389,9 @@ void saveZigbeeDevices(void) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data store in Flash (0x%08X - %d bytes)"), z_dev_start, buf_len);
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
ZigbeeWrite(&spi_buffer, z_spi_len);
|
||||
#ifdef USE_TFS
|
||||
TfsSaveFile("/zb", spi_buffer, z_spi_len);
|
||||
#endif
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data saved in %s (%d bytes)"), PSTR("Flash"), buf_len);
|
||||
#endif // ESP32
|
||||
free(spi_buffer);
|
||||
@ -419,7 +425,9 @@ void eraseZigbeeDevices(void) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased in %s"), PSTR("Flash"));
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
ZigbeeErase();
|
||||
#ifdef USE_TFS
|
||||
TfsEraseFile("/zb", z_block_len);
|
||||
#endif
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "Zigbee Devices Data erased (%d bytes)"), z_block_len);
|
||||
#endif // ESP32
|
||||
}
|
||||
|
@ -130,12 +130,13 @@ const char Z_strings[] PROGMEM =
|
||||
"AnalogInMaxValue" "\x00"
|
||||
"AnalogInMinValue" "\x00"
|
||||
"AnalogInOutOfService" "\x00"
|
||||
"AqaraRotate" "\x00"
|
||||
"AnalogValue" "\x00"
|
||||
"AnalogInReliability" "\x00"
|
||||
"AnalogInResolution" "\x00"
|
||||
"AnalogInStatusFlags" "\x00"
|
||||
"AnalogInEngineeringUnits" "\x00"
|
||||
"AnalogInApplicationType" "\x00"
|
||||
"AqaraRotate" "\x00"
|
||||
"Aqara_FF05" "\x00"
|
||||
"AnalogOutDescription" "\x00"
|
||||
"AnalogOutMaxValue" "\x00"
|
||||
@ -150,7 +151,6 @@ const char Z_strings[] PROGMEM =
|
||||
"AnalogOutApplicationType" "\x00"
|
||||
"AnalogDescription" "\x00"
|
||||
"AnalogOutOfService" "\x00"
|
||||
"AnalogValue" "\x00"
|
||||
"AnalogPriorityArray" "\x00"
|
||||
"AnalogReliability" "\x00"
|
||||
"AnalogRelinquishDefault" "\x00"
|
||||
@ -275,6 +275,11 @@ const char Z_strings[] PROGMEM =
|
||||
"ValvePosition" "\x00"
|
||||
"EurotronicErrors" "\x00"
|
||||
"CurrentTemperatureSetPoint" "\x00"
|
||||
"EurotronicHostFlags" "\x00"
|
||||
"TRVMirrorDisplay" "\x00"
|
||||
"TRVBoost" "\x00"
|
||||
"TRVWindowOpen" "\x00"
|
||||
"TRVChildProtection" "\x00"
|
||||
"ThSetpoint" "\x00"
|
||||
"TempTarget" "\x00"
|
||||
"Hue" "\x00"
|
||||
@ -395,6 +400,7 @@ const char Z_strings[] PROGMEM =
|
||||
"TuyaFanMode" "\x00"
|
||||
"TuyaForceMode" "\x00"
|
||||
"TuyaWeekSelect" "\x00"
|
||||
"OppleMode" "\x00"
|
||||
"TerncyDuration" "\x00"
|
||||
"TerncyRotate" "\x00"
|
||||
"Identify" "\x00"
|
||||
@ -545,27 +551,27 @@ enum Z_offsets {
|
||||
Zo_AnalogInMaxValue = 676,
|
||||
Zo_AnalogInMinValue = 693,
|
||||
Zo_AnalogInOutOfService = 710,
|
||||
Zo_AqaraRotate = 731,
|
||||
Zo_AnalogValue = 731,
|
||||
Zo_AnalogInReliability = 743,
|
||||
Zo_AnalogInResolution = 763,
|
||||
Zo_AnalogInStatusFlags = 782,
|
||||
Zo_AnalogInEngineeringUnits = 802,
|
||||
Zo_AnalogInApplicationType = 827,
|
||||
Zo_Aqara_FF05 = 851,
|
||||
Zo_AnalogOutDescription = 862,
|
||||
Zo_AnalogOutMaxValue = 883,
|
||||
Zo_AnalogOutMinValue = 901,
|
||||
Zo_AnalogOutOutOfService = 919,
|
||||
Zo_AnalogOutValue = 941,
|
||||
Zo_AnalogOutReliability = 956,
|
||||
Zo_AnalogOutRelinquishDefault = 977,
|
||||
Zo_AnalogOutResolution = 1004,
|
||||
Zo_AnalogOutStatusFlags = 1024,
|
||||
Zo_AnalogOutEngineeringUnits = 1045,
|
||||
Zo_AnalogOutApplicationType = 1071,
|
||||
Zo_AnalogDescription = 1096,
|
||||
Zo_AnalogOutOfService = 1114,
|
||||
Zo_AnalogValue = 1133,
|
||||
Zo_AqaraRotate = 851,
|
||||
Zo_Aqara_FF05 = 863,
|
||||
Zo_AnalogOutDescription = 874,
|
||||
Zo_AnalogOutMaxValue = 895,
|
||||
Zo_AnalogOutMinValue = 913,
|
||||
Zo_AnalogOutOutOfService = 931,
|
||||
Zo_AnalogOutValue = 953,
|
||||
Zo_AnalogOutReliability = 968,
|
||||
Zo_AnalogOutRelinquishDefault = 989,
|
||||
Zo_AnalogOutResolution = 1016,
|
||||
Zo_AnalogOutStatusFlags = 1036,
|
||||
Zo_AnalogOutEngineeringUnits = 1057,
|
||||
Zo_AnalogOutApplicationType = 1083,
|
||||
Zo_AnalogDescription = 1108,
|
||||
Zo_AnalogOutOfService = 1126,
|
||||
Zo_AnalogPriorityArray = 1145,
|
||||
Zo_AnalogReliability = 1165,
|
||||
Zo_AnalogRelinquishDefault = 1183,
|
||||
@ -690,217 +696,223 @@ enum Z_offsets {
|
||||
Zo_ValvePosition = 3473,
|
||||
Zo_EurotronicErrors = 3487,
|
||||
Zo_CurrentTemperatureSetPoint = 3504,
|
||||
Zo_ThSetpoint = 3531,
|
||||
Zo_TempTarget = 3542,
|
||||
Zo_Hue = 3553,
|
||||
Zo_Sat = 3557,
|
||||
Zo_RemainingTime = 3561,
|
||||
Zo_X = 3575,
|
||||
Zo_Y = 3577,
|
||||
Zo_DriftCompensation = 3579,
|
||||
Zo_CompensationText = 3597,
|
||||
Zo_CT = 3614,
|
||||
Zo_ColorMode = 3617,
|
||||
Zo_NumberOfPrimaries = 3627,
|
||||
Zo_Primary1X = 3645,
|
||||
Zo_Primary1Y = 3655,
|
||||
Zo_Primary1Intensity = 3665,
|
||||
Zo_Primary2X = 3683,
|
||||
Zo_Primary2Y = 3693,
|
||||
Zo_Primary2Intensity = 3703,
|
||||
Zo_Primary3X = 3721,
|
||||
Zo_Primary3Y = 3731,
|
||||
Zo_Primary3Intensity = 3741,
|
||||
Zo_WhitePointX = 3759,
|
||||
Zo_WhitePointY = 3771,
|
||||
Zo_ColorPointRX = 3783,
|
||||
Zo_ColorPointRY = 3796,
|
||||
Zo_ColorPointRIntensity = 3809,
|
||||
Zo_ColorPointGX = 3830,
|
||||
Zo_ColorPointGY = 3843,
|
||||
Zo_ColorPointGIntensity = 3856,
|
||||
Zo_ColorPointBX = 3877,
|
||||
Zo_ColorPointBY = 3890,
|
||||
Zo_ColorPointBIntensity = 3903,
|
||||
Zo_Illuminance = 3924,
|
||||
Zo_IlluminanceMinMeasuredValue = 3936,
|
||||
Zo_IlluminanceMaxMeasuredValue = 3964,
|
||||
Zo_IlluminanceTolerance = 3992,
|
||||
Zo_IlluminanceLightSensorType = 4013,
|
||||
Zo_IlluminanceLevelStatus = 4040,
|
||||
Zo_IlluminanceTargetLevel = 4063,
|
||||
Zo_Temperature = 4086,
|
||||
Zo_TemperatureMinMeasuredValue = 4098,
|
||||
Zo_TemperatureMaxMeasuredValue = 4126,
|
||||
Zo_TemperatureTolerance = 4154,
|
||||
Zo_Pressure = 4175,
|
||||
Zo_PressureMinMeasuredValue = 4184,
|
||||
Zo_PressureMaxMeasuredValue = 4209,
|
||||
Zo_PressureTolerance = 4234,
|
||||
Zo_PressureScaledValue = 4252,
|
||||
Zo_PressureMinScaledValue = 4272,
|
||||
Zo_PressureMaxScaledValue = 4295,
|
||||
Zo_PressureScaledTolerance = 4318,
|
||||
Zo_PressureScale = 4342,
|
||||
Zo_SeaPressure = 4356,
|
||||
Zo_FlowRate = 4368,
|
||||
Zo_FlowMinMeasuredValue = 4377,
|
||||
Zo_FlowMaxMeasuredValue = 4398,
|
||||
Zo_FlowTolerance = 4419,
|
||||
Zo_Humidity = 4433,
|
||||
Zo_HumidityMinMeasuredValue = 4442,
|
||||
Zo_HumidityMaxMeasuredValue = 4467,
|
||||
Zo_HumidityTolerance = 4492,
|
||||
Zo_Occupancy = 4510,
|
||||
Zo_OccupancySensorType = 4520,
|
||||
Zo_ZoneState = 4540,
|
||||
Zo_ZoneType = 4550,
|
||||
Zo_ZoneStatus = 4559,
|
||||
Zo_CIE = 4570,
|
||||
Zo_Contact = 4574,
|
||||
Zo_Fire = 4582,
|
||||
Zo_Water = 4587,
|
||||
Zo_CO = 4593,
|
||||
Zo_PersonalAlarm = 4596,
|
||||
Zo_Movement = 4610,
|
||||
Zo_Panic = 4619,
|
||||
Zo_GlassBreak = 4625,
|
||||
Zo_EnergyTotal = 4636,
|
||||
Zo_CompanyName = 4648,
|
||||
Zo_MeterTypeID = 4660,
|
||||
Zo_DataQualityID = 4672,
|
||||
Zo_CustomerName = 4686,
|
||||
Zo_Model = 4699,
|
||||
Zo_PartNumber = 4705,
|
||||
Zo_ProductRevision = 4716,
|
||||
Zo_SoftwareRevision = 4732,
|
||||
Zo_UtilityName = 4749,
|
||||
Zo_POD = 4761,
|
||||
Zo_AvailablePower = 4765,
|
||||
Zo_PowerThreshold = 4780,
|
||||
Zo_RMSVoltage = 4795,
|
||||
Zo_RMSCurrent = 4806,
|
||||
Zo_ActivePower = 4817,
|
||||
Zo_ReactivePower = 4829,
|
||||
Zo_ApparentPower = 4843,
|
||||
Zo_NumberOfResets = 4857,
|
||||
Zo_PersistentMemoryWrites = 4872,
|
||||
Zo_LastMessageLQI = 4895,
|
||||
Zo_LastMessageRSSI = 4910,
|
||||
Zo_TuyaScheduleWorkdays = 4926,
|
||||
Zo_TuyaScheduleHolidays = 4947,
|
||||
Zo_Power2 = 4968,
|
||||
Zo_Power3 = 4975,
|
||||
Zo_Power4 = 4982,
|
||||
Zo_TuyaChildLock = 4989,
|
||||
Zo_TuyaWindowDetection = 5003,
|
||||
Zo_TuyaValveDetection = 5023,
|
||||
Zo_TuyaAutoLock = 5042,
|
||||
Zo_TuyaTempTarget = 5055,
|
||||
Zo_TuyaBattery = 5070,
|
||||
Zo_TuyaMinTemp = 5082,
|
||||
Zo_TuyaMaxTemp = 5094,
|
||||
Zo_TuyaBoostTime = 5106,
|
||||
Zo_TuyaComfortTemp = 5120,
|
||||
Zo_TuyaEcoTemp = 5136,
|
||||
Zo_TuyaValvePosition = 5148,
|
||||
Zo_TuyaAwayTemp = 5166,
|
||||
Zo_TuyaAwayDays = 5179,
|
||||
Zo_TuyaPreset = 5192,
|
||||
Zo_TuyaFanMode = 5203,
|
||||
Zo_TuyaForceMode = 5215,
|
||||
Zo_TuyaWeekSelect = 5229,
|
||||
Zo_TerncyDuration = 5244,
|
||||
Zo_TerncyRotate = 5259,
|
||||
Zo_Identify = 5272,
|
||||
Zo_xxxx = 5281,
|
||||
Zo_IdentifyQuery = 5286,
|
||||
Zo_AddGroup = 5300,
|
||||
Zo_xxxx00 = 5309,
|
||||
Zo_ViewGroup = 5316,
|
||||
Zo_GetGroup = 5326,
|
||||
Zo_01xxxx = 5335,
|
||||
Zo_GetAllGroups = 5342,
|
||||
Zo_00 = 5355,
|
||||
Zo_RemoveGroup = 5358,
|
||||
Zo_RemoveAllGroups = 5370,
|
||||
Zo_ViewScene = 5386,
|
||||
Zo_xxxxyy = 5396,
|
||||
Zo_RemoveScene = 5403,
|
||||
Zo_RemoveAllScenes = 5415,
|
||||
Zo_RecallScene = 5431,
|
||||
Zo_GetSceneMembership = 5443,
|
||||
Zo_PowerOffEffect = 5462,
|
||||
Zo_xxyy = 5477,
|
||||
Zo_PowerOnRecall = 5482,
|
||||
Zo_PowerOnTimer = 5496,
|
||||
Zo_xxyyyyzzzz = 5509,
|
||||
Zo_xx0A00 = 5520,
|
||||
Zo_DimmerUp = 5527,
|
||||
Zo_00190200 = 5536,
|
||||
Zo_DimmerDown = 5545,
|
||||
Zo_01190200 = 5556,
|
||||
Zo_DimmerStop = 5565,
|
||||
Zo_ResetAlarm = 5576,
|
||||
Zo_xxyyyy = 5587,
|
||||
Zo_ResetAllAlarms = 5594,
|
||||
Zo_xx000A00 = 5609,
|
||||
Zo_HueSat = 5618,
|
||||
Zo_xxyy0A00 = 5625,
|
||||
Zo_Color = 5634,
|
||||
Zo_xxxxyyyy0A00 = 5640,
|
||||
Zo_xxxx0A00 = 5653,
|
||||
Zo_ShutterOpen = 5662,
|
||||
Zo_ShutterClose = 5674,
|
||||
Zo_ShutterStop = 5687,
|
||||
Zo_ShutterLift = 5699,
|
||||
Zo_xx = 5711,
|
||||
Zo_ShutterTilt = 5714,
|
||||
Zo_Shutter = 5726,
|
||||
Zo_DimmerMove = 5734,
|
||||
Zo_xx0A = 5745,
|
||||
Zo_DimmerStepUp = 5750,
|
||||
Zo_00xx0A00 = 5763,
|
||||
Zo_DimmerStepDown = 5772,
|
||||
Zo_01xx0A00 = 5787,
|
||||
Zo_DimmerStep = 5796,
|
||||
Zo_xx190A00 = 5807,
|
||||
Zo_01 = 5816,
|
||||
Zo_HueMove = 5819,
|
||||
Zo_xx19 = 5827,
|
||||
Zo_HueStepUp = 5832,
|
||||
Zo_HueStepDown = 5842,
|
||||
Zo_03xx0A00 = 5854,
|
||||
Zo_HueStep = 5863,
|
||||
Zo_SatMove = 5871,
|
||||
Zo_SatStep = 5879,
|
||||
Zo_xx190A = 5887,
|
||||
Zo_ColorMove = 5894,
|
||||
Zo_xxxxyyyy = 5904,
|
||||
Zo_ColorStep = 5913,
|
||||
Zo_ColorTempMoveUp = 5923,
|
||||
Zo_01xxxx000000000000 = 5939,
|
||||
Zo_ColorTempMoveDown = 5958,
|
||||
Zo_03xxxx000000000000 = 5976,
|
||||
Zo_ColorTempMoveStop = 5995,
|
||||
Zo_00xxxx000000000000 = 6013,
|
||||
Zo_ColorTempMove = 6032,
|
||||
Zo_xxyyyy000000000000 = 6046,
|
||||
Zo_ColorTempStepUp = 6065,
|
||||
Zo_01xxxx0A0000000000 = 6081,
|
||||
Zo_ColorTempStepDown = 6100,
|
||||
Zo_03xxxx0A0000000000 = 6118,
|
||||
Zo_ColorTempStep = 6137,
|
||||
Zo_xxyyyy0A0000000000 = 6151,
|
||||
Zo_ArrowClick = 6170,
|
||||
Zo_ArrowHold = 6181,
|
||||
Zo_ArrowRelease = 6191,
|
||||
Zo_ZoneStatusChange = 6204,
|
||||
Zo_xxxxyyzz = 6221,
|
||||
Zo_xxyyzzzz = 6230,
|
||||
Zo_AddScene = 6239,
|
||||
Zo_xxyyyyzz = 6248,
|
||||
Zo_StoreScene = 6257,
|
||||
Zo_EurotronicHostFlags = 3531,
|
||||
Zo_TRVMirrorDisplay = 3551,
|
||||
Zo_TRVBoost = 3568,
|
||||
Zo_TRVWindowOpen = 3577,
|
||||
Zo_TRVChildProtection = 3591,
|
||||
Zo_ThSetpoint = 3610,
|
||||
Zo_TempTarget = 3621,
|
||||
Zo_Hue = 3632,
|
||||
Zo_Sat = 3636,
|
||||
Zo_RemainingTime = 3640,
|
||||
Zo_X = 3654,
|
||||
Zo_Y = 3656,
|
||||
Zo_DriftCompensation = 3658,
|
||||
Zo_CompensationText = 3676,
|
||||
Zo_CT = 3693,
|
||||
Zo_ColorMode = 3696,
|
||||
Zo_NumberOfPrimaries = 3706,
|
||||
Zo_Primary1X = 3724,
|
||||
Zo_Primary1Y = 3734,
|
||||
Zo_Primary1Intensity = 3744,
|
||||
Zo_Primary2X = 3762,
|
||||
Zo_Primary2Y = 3772,
|
||||
Zo_Primary2Intensity = 3782,
|
||||
Zo_Primary3X = 3800,
|
||||
Zo_Primary3Y = 3810,
|
||||
Zo_Primary3Intensity = 3820,
|
||||
Zo_WhitePointX = 3838,
|
||||
Zo_WhitePointY = 3850,
|
||||
Zo_ColorPointRX = 3862,
|
||||
Zo_ColorPointRY = 3875,
|
||||
Zo_ColorPointRIntensity = 3888,
|
||||
Zo_ColorPointGX = 3909,
|
||||
Zo_ColorPointGY = 3922,
|
||||
Zo_ColorPointGIntensity = 3935,
|
||||
Zo_ColorPointBX = 3956,
|
||||
Zo_ColorPointBY = 3969,
|
||||
Zo_ColorPointBIntensity = 3982,
|
||||
Zo_Illuminance = 4003,
|
||||
Zo_IlluminanceMinMeasuredValue = 4015,
|
||||
Zo_IlluminanceMaxMeasuredValue = 4043,
|
||||
Zo_IlluminanceTolerance = 4071,
|
||||
Zo_IlluminanceLightSensorType = 4092,
|
||||
Zo_IlluminanceLevelStatus = 4119,
|
||||
Zo_IlluminanceTargetLevel = 4142,
|
||||
Zo_Temperature = 4165,
|
||||
Zo_TemperatureMinMeasuredValue = 4177,
|
||||
Zo_TemperatureMaxMeasuredValue = 4205,
|
||||
Zo_TemperatureTolerance = 4233,
|
||||
Zo_Pressure = 4254,
|
||||
Zo_PressureMinMeasuredValue = 4263,
|
||||
Zo_PressureMaxMeasuredValue = 4288,
|
||||
Zo_PressureTolerance = 4313,
|
||||
Zo_PressureScaledValue = 4331,
|
||||
Zo_PressureMinScaledValue = 4351,
|
||||
Zo_PressureMaxScaledValue = 4374,
|
||||
Zo_PressureScaledTolerance = 4397,
|
||||
Zo_PressureScale = 4421,
|
||||
Zo_SeaPressure = 4435,
|
||||
Zo_FlowRate = 4447,
|
||||
Zo_FlowMinMeasuredValue = 4456,
|
||||
Zo_FlowMaxMeasuredValue = 4477,
|
||||
Zo_FlowTolerance = 4498,
|
||||
Zo_Humidity = 4512,
|
||||
Zo_HumidityMinMeasuredValue = 4521,
|
||||
Zo_HumidityMaxMeasuredValue = 4546,
|
||||
Zo_HumidityTolerance = 4571,
|
||||
Zo_Occupancy = 4589,
|
||||
Zo_OccupancySensorType = 4599,
|
||||
Zo_ZoneState = 4619,
|
||||
Zo_ZoneType = 4629,
|
||||
Zo_ZoneStatus = 4638,
|
||||
Zo_CIE = 4649,
|
||||
Zo_Contact = 4653,
|
||||
Zo_Fire = 4661,
|
||||
Zo_Water = 4666,
|
||||
Zo_CO = 4672,
|
||||
Zo_PersonalAlarm = 4675,
|
||||
Zo_Movement = 4689,
|
||||
Zo_Panic = 4698,
|
||||
Zo_GlassBreak = 4704,
|
||||
Zo_EnergyTotal = 4715,
|
||||
Zo_CompanyName = 4727,
|
||||
Zo_MeterTypeID = 4739,
|
||||
Zo_DataQualityID = 4751,
|
||||
Zo_CustomerName = 4765,
|
||||
Zo_Model = 4778,
|
||||
Zo_PartNumber = 4784,
|
||||
Zo_ProductRevision = 4795,
|
||||
Zo_SoftwareRevision = 4811,
|
||||
Zo_UtilityName = 4828,
|
||||
Zo_POD = 4840,
|
||||
Zo_AvailablePower = 4844,
|
||||
Zo_PowerThreshold = 4859,
|
||||
Zo_RMSVoltage = 4874,
|
||||
Zo_RMSCurrent = 4885,
|
||||
Zo_ActivePower = 4896,
|
||||
Zo_ReactivePower = 4908,
|
||||
Zo_ApparentPower = 4922,
|
||||
Zo_NumberOfResets = 4936,
|
||||
Zo_PersistentMemoryWrites = 4951,
|
||||
Zo_LastMessageLQI = 4974,
|
||||
Zo_LastMessageRSSI = 4989,
|
||||
Zo_TuyaScheduleWorkdays = 5005,
|
||||
Zo_TuyaScheduleHolidays = 5026,
|
||||
Zo_Power2 = 5047,
|
||||
Zo_Power3 = 5054,
|
||||
Zo_Power4 = 5061,
|
||||
Zo_TuyaChildLock = 5068,
|
||||
Zo_TuyaWindowDetection = 5082,
|
||||
Zo_TuyaValveDetection = 5102,
|
||||
Zo_TuyaAutoLock = 5121,
|
||||
Zo_TuyaTempTarget = 5134,
|
||||
Zo_TuyaBattery = 5149,
|
||||
Zo_TuyaMinTemp = 5161,
|
||||
Zo_TuyaMaxTemp = 5173,
|
||||
Zo_TuyaBoostTime = 5185,
|
||||
Zo_TuyaComfortTemp = 5199,
|
||||
Zo_TuyaEcoTemp = 5215,
|
||||
Zo_TuyaValvePosition = 5227,
|
||||
Zo_TuyaAwayTemp = 5245,
|
||||
Zo_TuyaAwayDays = 5258,
|
||||
Zo_TuyaPreset = 5271,
|
||||
Zo_TuyaFanMode = 5282,
|
||||
Zo_TuyaForceMode = 5294,
|
||||
Zo_TuyaWeekSelect = 5308,
|
||||
Zo_OppleMode = 5323,
|
||||
Zo_TerncyDuration = 5333,
|
||||
Zo_TerncyRotate = 5348,
|
||||
Zo_Identify = 5361,
|
||||
Zo_xxxx = 5370,
|
||||
Zo_IdentifyQuery = 5375,
|
||||
Zo_AddGroup = 5389,
|
||||
Zo_xxxx00 = 5398,
|
||||
Zo_ViewGroup = 5405,
|
||||
Zo_GetGroup = 5415,
|
||||
Zo_01xxxx = 5424,
|
||||
Zo_GetAllGroups = 5431,
|
||||
Zo_00 = 5444,
|
||||
Zo_RemoveGroup = 5447,
|
||||
Zo_RemoveAllGroups = 5459,
|
||||
Zo_ViewScene = 5475,
|
||||
Zo_xxxxyy = 5485,
|
||||
Zo_RemoveScene = 5492,
|
||||
Zo_RemoveAllScenes = 5504,
|
||||
Zo_RecallScene = 5520,
|
||||
Zo_GetSceneMembership = 5532,
|
||||
Zo_PowerOffEffect = 5551,
|
||||
Zo_xxyy = 5566,
|
||||
Zo_PowerOnRecall = 5571,
|
||||
Zo_PowerOnTimer = 5585,
|
||||
Zo_xxyyyyzzzz = 5598,
|
||||
Zo_xx0A00 = 5609,
|
||||
Zo_DimmerUp = 5616,
|
||||
Zo_00190200 = 5625,
|
||||
Zo_DimmerDown = 5634,
|
||||
Zo_01190200 = 5645,
|
||||
Zo_DimmerStop = 5654,
|
||||
Zo_ResetAlarm = 5665,
|
||||
Zo_xxyyyy = 5676,
|
||||
Zo_ResetAllAlarms = 5683,
|
||||
Zo_xx000A00 = 5698,
|
||||
Zo_HueSat = 5707,
|
||||
Zo_xxyy0A00 = 5714,
|
||||
Zo_Color = 5723,
|
||||
Zo_xxxxyyyy0A00 = 5729,
|
||||
Zo_xxxx0A00 = 5742,
|
||||
Zo_ShutterOpen = 5751,
|
||||
Zo_ShutterClose = 5763,
|
||||
Zo_ShutterStop = 5776,
|
||||
Zo_ShutterLift = 5788,
|
||||
Zo_xx = 5800,
|
||||
Zo_ShutterTilt = 5803,
|
||||
Zo_Shutter = 5815,
|
||||
Zo_DimmerMove = 5823,
|
||||
Zo_xx0A = 5834,
|
||||
Zo_DimmerStepUp = 5839,
|
||||
Zo_00xx0A00 = 5852,
|
||||
Zo_DimmerStepDown = 5861,
|
||||
Zo_01xx0A00 = 5876,
|
||||
Zo_DimmerStep = 5885,
|
||||
Zo_xx190A00 = 5896,
|
||||
Zo_01 = 5905,
|
||||
Zo_HueMove = 5908,
|
||||
Zo_xx19 = 5916,
|
||||
Zo_HueStepUp = 5921,
|
||||
Zo_HueStepDown = 5931,
|
||||
Zo_03xx0A00 = 5943,
|
||||
Zo_HueStep = 5952,
|
||||
Zo_SatMove = 5960,
|
||||
Zo_SatStep = 5968,
|
||||
Zo_xx190A = 5976,
|
||||
Zo_ColorMove = 5983,
|
||||
Zo_xxxxyyyy = 5993,
|
||||
Zo_ColorStep = 6002,
|
||||
Zo_ColorTempMoveUp = 6012,
|
||||
Zo_01xxxx000000000000 = 6028,
|
||||
Zo_ColorTempMoveDown = 6047,
|
||||
Zo_03xxxx000000000000 = 6065,
|
||||
Zo_ColorTempMoveStop = 6084,
|
||||
Zo_00xxxx000000000000 = 6102,
|
||||
Zo_ColorTempMove = 6121,
|
||||
Zo_xxyyyy000000000000 = 6135,
|
||||
Zo_ColorTempStepUp = 6154,
|
||||
Zo_01xxxx0A0000000000 = 6170,
|
||||
Zo_ColorTempStepDown = 6189,
|
||||
Zo_03xxxx0A0000000000 = 6207,
|
||||
Zo_ColorTempStep = 6226,
|
||||
Zo_xxyyyy0A0000000000 = 6240,
|
||||
Zo_ArrowClick = 6259,
|
||||
Zo_ArrowHold = 6270,
|
||||
Zo_ArrowRelease = 6280,
|
||||
Zo_ZoneStatusChange = 6293,
|
||||
Zo_xxxxyyzz = 6310,
|
||||
Zo_xxyyzzzz = 6319,
|
||||
Zo_AddScene = 6328,
|
||||
Zo_xxyyyyzz = 6337,
|
||||
Zo_StoreScene = 6346,
|
||||
};
|
||||
|
||||
|
||||
|
@ -127,7 +127,7 @@ enum Cx_cluster_short {
|
||||
Cx0010, Cx0011, Cx0012, Cx0013, Cx0014, Cx001A, Cx0020, Cx0100,
|
||||
Cx0101, Cx0102, Cx0201, Cx0300, Cx0400, Cx0401, Cx0402, Cx0403,
|
||||
Cx0404, Cx0405, Cx0406, Cx0500, Cx0702, Cx0B01, Cx0B04, Cx0B05,
|
||||
CxEF00, CxFCCC,
|
||||
CxEF00, CxFCC0, CxFCCC,
|
||||
};
|
||||
|
||||
const uint16_t Cx_cluster[] PROGMEM = {
|
||||
@ -136,7 +136,7 @@ const uint16_t Cx_cluster[] PROGMEM = {
|
||||
0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x001A, 0x0020, 0x0100,
|
||||
0x0101, 0x0102, 0x0201, 0x0300, 0x0400, 0x0401, 0x0402, 0x0403,
|
||||
0x0404, 0x0405, 0x0406, 0x0500, 0x0702, 0x0B01, 0x0B04, 0x0B05,
|
||||
0xEF00, 0xFCCC,
|
||||
0xEF00, 0xFCC0, 0xFCCC,
|
||||
};
|
||||
|
||||
uint16_t CxToCluster(uint8_t cx) {
|
||||
@ -466,6 +466,13 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
|
||||
{ Zuint8, Cx0201, 0x4001, Z_(ValvePosition), Cm1, 0 },
|
||||
{ Zuint8, Cx0201, 0x4002, Z_(EurotronicErrors), Cm1, 0 },
|
||||
{ Zint16, Cx0201, 0x4003, Z_(CurrentTemperatureSetPoint), Cm_100, 0 },
|
||||
{ Zuint24, Cx0201, 0x4008, Z_(EurotronicHostFlags), Cm1, 0 },
|
||||
// below are synthetic virtual attributes used to decode EurotronicHostFlags
|
||||
// Last byte acts as a field mask for the lowest byte value
|
||||
{ Zbool, Cx0201, 0xF002, Z_(TRVMirrorDisplay), Cm1, 0 },
|
||||
{ Zbool, Cx0201, 0xF004, Z_(TRVBoost), Cm1, 0 },
|
||||
{ Zbool, Cx0201, 0xF010, Z_(TRVWindowOpen), Cm1, 0 },
|
||||
{ Zbool, Cx0201, 0xF080, Z_(TRVChildProtection), Cm1, 0 },
|
||||
// below are virtual attributes to simplify ZbData import/export
|
||||
{ Zuint8, Cx0201, 0xFFF0, Z_(ThSetpoint), Cm1 + Z_EXPORT_DATA, Z_MAPPING(Z_Data_Thermo, th_setpoint) },
|
||||
{ Zint16, Cx0201, 0xFFF1, Z_(TempTarget), Cm_100 + Z_EXPORT_DATA, Z_MAPPING(Z_Data_Thermo, temperature_target) },
|
||||
@ -618,15 +625,15 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
|
||||
{ Ztuya1, CxEF00, 0x0112, Z_(TuyaWindowDetection), Cm1, 0 },
|
||||
{ Ztuya1, CxEF00, 0x0114, Z_(TuyaValveDetection), Cm1, 0 },
|
||||
{ Ztuya1, CxEF00, 0x0174, Z_(TuyaAutoLock), Cm1, 0 },
|
||||
{ Ztuya2, CxEF00, 0x0202, Z_(TuyaTempTarget), Cm_10, 0 },
|
||||
{ Ztuya2, CxEF00, 0x0203, Z_(LocalTemperature), Cm_10, 0 }, // will be overwritten by actual LocalTemperature
|
||||
{ Zint16, CxEF00, 0x0202, Z_(TuyaTempTarget), Cm_10, Z_MAPPING(Z_Data_Thermo, temperature_target) },
|
||||
{ Zint16, CxEF00, 0x0203, Z_(LocalTemperature), Cm_10, Z_MAPPING(Z_Data_Thermo, temperature) }, // will be overwritten by actual LocalTemperature
|
||||
{ Ztuya2, CxEF00, 0x0215, Z_(TuyaBattery), Cm1, 0 }, // TODO check equivalent?
|
||||
{ Ztuya2, CxEF00, 0x0266, Z_(TuyaMinTemp), Cm1, 0 },
|
||||
{ Ztuya2, CxEF00, 0x0267, Z_(TuyaMaxTemp), Cm1, 0 },
|
||||
{ Ztuya2, CxEF00, 0x0269, Z_(TuyaBoostTime), Cm1, 0 },
|
||||
{ Ztuya2, CxEF00, 0x026B, Z_(TuyaComfortTemp), Cm1, 0 },
|
||||
{ Ztuya2, CxEF00, 0x026C, Z_(TuyaEcoTemp), Cm1, 0 },
|
||||
{ Ztuya2, CxEF00, 0x026D, Z_(TuyaValvePosition), Cm1, 0 },
|
||||
{ Zuint8, CxEF00, 0x026D, Z_(TuyaValvePosition), Cm1, Z_MAPPING(Z_Data_Thermo, th_setpoint) },
|
||||
{ Ztuya2, CxEF00, 0x0272, Z_(TuyaAwayTemp), Cm1, 0 },
|
||||
{ Ztuya2, CxEF00, 0x0275, Z_(TuyaAwayDays), Cm1, 0 },
|
||||
{ Ztuya4, CxEF00, 0x0404, Z_(TuyaPreset), Cm1, 0 },
|
||||
@ -634,6 +641,9 @@ const Z_AttributeConverter Z_PostProcess[] PROGMEM = {
|
||||
{ Ztuya4, CxEF00, 0x046A, Z_(TuyaForceMode), Cm1, 0 },
|
||||
{ Ztuya4, CxEF00, 0x046F, Z_(TuyaWeekSelect), Cm1, 0 },
|
||||
|
||||
// Aqara Opple spacific
|
||||
{ Zbool, CxFCC0, 0x0009, Z_(OppleMode), Cm1, 0 },
|
||||
|
||||
// Terncy specific - 0xFCCC
|
||||
{ Zuint16, CxFCCC, 0x001A, Z_(TerncyDuration), Cm1, 0 },
|
||||
{ Zint16, CxFCCC, 0x001B, Z_(TerncyRotate), Cm1, 0 },
|
||||
@ -876,6 +886,11 @@ int32_t encodeSingleAttribute(class SBuffer &buf, double val_d, const char *val_
|
||||
buf.add16(u32);
|
||||
break;
|
||||
// unisgned 32
|
||||
case Zuint24:
|
||||
buf.add16(u32);
|
||||
buf.add8(u32 >> 16);
|
||||
break;
|
||||
// unisgned 24
|
||||
case Zuint32: // uint32
|
||||
case Zdata32: // data32
|
||||
case Zmap32: // map32
|
||||
@ -971,6 +986,15 @@ uint32_t parseSingleAttribute(Z_attribute & attr, const SBuffer &buf,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Zuint24:
|
||||
{
|
||||
uint32_t uint24_val = buf.get16(i) + (buf.get8(i+2) >> 16);
|
||||
// i += 3;
|
||||
if (0xFFFFFF != uint24_val) {
|
||||
attr.setUInt(uint24_val);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Zuint32: // uint32
|
||||
case ZUTC: // UTC
|
||||
{
|
||||
@ -1277,15 +1301,24 @@ void ZCLFrame::computeSyntheticAttributes(Z_attribute_list& attr_list) {
|
||||
}
|
||||
break;
|
||||
case 0x02010008: // Pi Heating Demand - solve Eutotronic bug
|
||||
case 0x02014008: // Eurotronic Host Flags decoding
|
||||
{
|
||||
const char * manufacturer_c = zigbee_devices.getManufacturerId(_srcaddr); // null if unknown
|
||||
String manufacturerId((char*) manufacturer_c);
|
||||
if (manufacturerId.equals(F("Eurotronic"))) {
|
||||
// Eurotronic does not report 0..100 but 0..255, including 255 which is normally an ivalid value
|
||||
uint8_t valve = attr.getUInt();
|
||||
if (attr.isNone()) { valve = 255; }
|
||||
uint8_t valve_100 = changeUIntScale(valve, 0, 255, 0, 100);
|
||||
attr.setUInt(valve_100);
|
||||
if (ccccaaaa == 0x02010008) {
|
||||
// Eurotronic does not report 0..100 but 0..255, including 255 which is normally an ivalid value
|
||||
uint8_t valve = attr.getUInt();
|
||||
if (attr.isNone()) { valve = 255; }
|
||||
uint8_t valve_100 = changeUIntScale(valve, 0, 255, 0, 100);
|
||||
attr.setUInt(valve_100);
|
||||
} else if (ccccaaaa == 0x02014008) {
|
||||
uint32_t mode = attr.getUInt();
|
||||
if (mode & 0x02) { attr_list.addAttribute(0x0201, 0xF002).setUInt(1); }
|
||||
if (mode & 0x04) { attr_list.addAttribute(0x0201, 0xF004).setUInt(1); }
|
||||
if (mode & 0x10) { attr_list.addAttribute(0x0201, 0xF010).setUInt(1); }
|
||||
if (mode & 0x80) { attr_list.addAttribute(0x0201, 0xF080).setUInt(1); }
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1583,6 +1616,9 @@ void ZCLFrame::syntheticAnalogValue(Z_attribute_list &attr_list, class Z_attribu
|
||||
if (modelId.startsWith(F("lumi.plug"))) {
|
||||
attr.setKeyId(0x0702, 0x0000); // change to EnergyTotal
|
||||
}
|
||||
if (modelId.startsWith(F("lumi.ctrl"))) {
|
||||
attr.setKeyId(0x0B04, 0x050B); // change to ActivePower
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1637,9 +1673,9 @@ void ZCLFrame::syntheticAqaraSensor(Z_attribute_list &attr_list, class Z_attribu
|
||||
} else if (0x66 == attrid) {
|
||||
attr_list.addAttribute(0x0403, 0x0000).setUInt((ival32 + 50) / 100); // Pressure
|
||||
}
|
||||
} else if (modelId.startsWith(F("lumi.plug"))) {
|
||||
} else if (modelId.startsWith(F("lumi.plug")) || modelId.startsWith(F("lumi.ctrl"))) {
|
||||
if (0x64 == attrid) {
|
||||
attr_list.addAttribute(0x0600, 0x0000).setInt(uval32); // Power (on/off)
|
||||
attr_list.addAttribute(0x0006, 0x0000).setInt(uval32); // Power (on/off)
|
||||
} else if (0x98 == attrid) {
|
||||
attr_list.addAttribute(0x0B04, 0x050B).setInt(ival32); // Active Power
|
||||
} else if (0x95 == attrid) {
|
||||
@ -1896,6 +1932,13 @@ void Z_postProcessAttributes(uint16_t shortaddr, uint16_t src_ep, class Z_attrib
|
||||
uint32_t uval32 = attr.getUInt(); // call converter to uint only once
|
||||
int32_t ival32 = attr.getInt(); // call converter to int only once
|
||||
// AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Mapping type=%d offset=%d zigbee_type=%02X value=%d\n"), (uint8_t) map_type, map_offset, zigbee_type, ival32);
|
||||
switch (ccccaaaa) {
|
||||
case 0xEF000202:
|
||||
case 0xEF000203: // need to convert Tuya temperatures from 1/10 to 1/00 °C
|
||||
ival32 = ival32 * 10;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (zigbee_type) {
|
||||
case Zenum8:
|
||||
case Zmap8:
|
||||
|
180
tasmota/xdrv_23_zigbee_7_5_map.ino
Normal file
180
tasmota/xdrv_23_zigbee_7_5_map.ino
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
xdrv_23_zigbee_7_5_map.ino - zigbee support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Theo Arends and Stephan Hadinger
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_ZIGBEE
|
||||
|
||||
class Z_Mapper_Edge {
|
||||
public:
|
||||
|
||||
// enum Edge_Type : uint8_t {
|
||||
// Unknown = 0x00,
|
||||
// Parent = 0x01, // node_1 is parent of node_2
|
||||
// Child = 0x02, // node_1 is child of node_2
|
||||
// Sibling = 0x03, // both nodes are siblings
|
||||
// };
|
||||
|
||||
Z_Mapper_Edge(void) :
|
||||
node_1(BAD_SHORTADDR),
|
||||
node_2(BAD_SHORTADDR),
|
||||
lqi(0x00)
|
||||
// edge_type(Unknown)
|
||||
{}
|
||||
|
||||
// Z_Mapper_Edge(uint16_t node_a, uint16_t node_b, uint8_t _lqi, Edge_Type _type) :
|
||||
Z_Mapper_Edge(uint16_t node_a, uint16_t node_b, uint8_t _lqi) :
|
||||
node_1(BAD_SHORTADDR),
|
||||
node_2(BAD_SHORTADDR),
|
||||
lqi(_lqi)
|
||||
// edge_type(_type)
|
||||
{
|
||||
setEdges(node_a, node_b);
|
||||
}
|
||||
|
||||
void setEdges(uint16_t node_a, uint16_t node_b);
|
||||
|
||||
bool sameEdge(const Z_Mapper_Edge & edge2) const;
|
||||
|
||||
// Edge_Type Z_Mapper_Edge_Type_Reverse(Edge_Type _type) {
|
||||
// switch (_type) {
|
||||
// case Parent: return Child;
|
||||
// case Child: return Parent;
|
||||
// default: return _type;
|
||||
// }
|
||||
// }
|
||||
|
||||
// we always orientate the edge from with shortaddresses in ascending order
|
||||
// invariant: node_1 < node_2
|
||||
uint16_t node_1;
|
||||
uint16_t node_2;
|
||||
|
||||
uint8_t lqi;
|
||||
// Edge_Type edge_type;
|
||||
};
|
||||
|
||||
//
|
||||
// Handles the mapping of Zigbee devices
|
||||
//
|
||||
class Z_Mapper {
|
||||
public:
|
||||
Z_Mapper(void) :
|
||||
edges()
|
||||
{}
|
||||
|
||||
void reset(void) { edges.reset(); }
|
||||
|
||||
Z_Mapper_Edge & findEdge(const Z_Mapper_Edge & edge2);
|
||||
bool addEdge(const Z_Mapper_Edge & edge2);
|
||||
|
||||
void dumpInternals(void) const;
|
||||
|
||||
LList<Z_Mapper_Edge> edges;
|
||||
|
||||
};
|
||||
|
||||
// global
|
||||
Z_Mapper zigbee_mapper;
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Implementation for Z_Mapper_Edge
|
||||
\*********************************************************************************************/
|
||||
void Z_Mapper_Edge::setEdges(uint16_t node_a, uint16_t node_b) {
|
||||
if (node_a < node_b) {
|
||||
node_1 = node_a;
|
||||
node_2 = node_b;
|
||||
} else if (node_a > node_b) {
|
||||
node_1 = node_b;
|
||||
node_2 = node_a;
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
bool Z_Mapper_Edge::sameEdge(const Z_Mapper_Edge & edge2) const {
|
||||
return (node_1 == edge2.node_1) && (node_2 == edge2.node_2);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Implementation for Z_Mapper
|
||||
\*********************************************************************************************/
|
||||
Z_Mapper_Edge & Z_Mapper::findEdge(const Z_Mapper_Edge & edge2) {
|
||||
if ((edge2.node_1 == BAD_SHORTADDR) || (edge2.node_2 == BAD_SHORTADDR)) { return *(Z_Mapper_Edge*)nullptr; }
|
||||
for (auto & edge : edges) {
|
||||
if (edge2.sameEdge(edge)) {
|
||||
return edge;
|
||||
}
|
||||
}
|
||||
return *(Z_Mapper_Edge*)nullptr;
|
||||
}
|
||||
|
||||
bool Z_Mapper::addEdge(const Z_Mapper_Edge & edge2) {
|
||||
if ((edge2.node_1 == BAD_SHORTADDR) || (edge2.node_2 == BAD_SHORTADDR)) { return false; }
|
||||
Z_Mapper_Edge & cur_edge = findEdge(edge2);
|
||||
if (&cur_edge == nullptr) {
|
||||
edges.addHead(edge2);
|
||||
} else {
|
||||
//upgrade fields
|
||||
if (edge2.lqi > cur_edge.lqi) {
|
||||
cur_edge.lqi = edge2.lqi;
|
||||
}
|
||||
// if (cur_edge.edge_type == Z_Mapper_Edge::Unknown) {
|
||||
// cur_edge.edge_type = edge2.edge_type;
|
||||
// } else if ((edge2.edge_type == Z_Mapper_Edge::Parent) || (edge2.edge_type == Z_Mapper_Edge::Child)) {
|
||||
// // Parent or Child always has priority over Sibling
|
||||
// cur_edge.edge_type = edge2.edge_type;
|
||||
// }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Z_Mapper::dumpInternals(void) const {
|
||||
WSContentSend_P(PSTR("nodes:[" "{id:\"0x0000\",label:\"Coordinator\",group:\"o\",title:\"0x0000\"}"));
|
||||
for (const auto & device : zigbee_devices.getDevices()) {
|
||||
WSContentSend_P(PSTR(",{id:\"0x%04X\",group:\"%c\",title:\"0x%04X\",label:\""),
|
||||
device.shortaddr, device.isRouter() ? 'r' : 'e', device.shortaddr);
|
||||
|
||||
const char *fname = device.friendlyName;
|
||||
if (fname != nullptr) {
|
||||
WSContentSend_P(PSTR("%s"), fname);
|
||||
} else {
|
||||
WSContentSend_P(PSTR("0x%04X"), device.shortaddr);
|
||||
}
|
||||
WSContentSend_P("\"}");
|
||||
}
|
||||
WSContentSend_P(PSTR("],"));
|
||||
|
||||
WSContentSend_P(PSTR("edges:["));
|
||||
for (auto & edge : edges) {
|
||||
uint32_t lqi_color = 0x000;
|
||||
// if (edge.lqi >= 192) {
|
||||
// lqi_color = 0x364;
|
||||
// } else if (edge.lqi >= 128) {
|
||||
// lqi_color = 0x346;
|
||||
// } else if (edge.lqi > 0) {
|
||||
// lqi_color = 0xd56;
|
||||
// }
|
||||
char hex[8];
|
||||
snprintf(hex, sizeof(hex), PSTR("%d"), edge.lqi);
|
||||
|
||||
WSContentSend_P("{from:\"0x%04X\",to:\"0x%04X\",label:\"%s\",color:\"#%03X\"},",
|
||||
edge.node_1, edge.node_2, (edge.lqi > 0) ? hex : "", lqi_color);
|
||||
}
|
||||
WSContentSend_P(PSTR("],"));
|
||||
}
|
||||
|
||||
#endif // USE_ZIGBEE
|
@ -229,7 +229,7 @@ void Z_Send_State_or_Map(uint16_t shortaddr, uint8_t index, uint16_t zdo_cmd) {
|
||||
// This callback is registered to send ZbMap(s) to each device one at a time
|
||||
void Z_Map(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t endpoint, uint32_t value) {
|
||||
if (BAD_SHORTADDR != shortaddr) {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "sending `ZnMap 0x%04X`"), shortaddr);
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "sending `ZbMap 0x%04X`"), shortaddr);
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
Z_Send_State_or_Map(shortaddr, value, ZDO_MGMT_LQI_REQ);
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
@ -238,6 +238,8 @@ void Z_Map(uint16_t shortaddr, uint16_t groupaddr, uint16_t cluster, uint8_t end
|
||||
#endif // USE_ZIGBEE_EZSP
|
||||
} else {
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "ZbMap done"));
|
||||
zigbee.mapping_in_progress = false;
|
||||
zigbee.mapping_ready = true;
|
||||
}
|
||||
}
|
||||
/*********************************************************************************************\
|
||||
@ -1057,6 +1059,7 @@ int32_t Z_Mgmt_Lqi_Bind_Rsp(int32_t res, const class SBuffer &buf, boolean lqi)
|
||||
|
||||
// device is reachable
|
||||
zigbee_devices.deviceWasReached(shortaddr);
|
||||
bool non_empty = false; // check whether the response contains relevant information
|
||||
|
||||
const char * friendlyName = zigbee_devices.getFriendlyName(shortaddr);
|
||||
|
||||
@ -1087,6 +1090,7 @@ int32_t Z_Mgmt_Lqi_Bind_Rsp(int32_t res, const class SBuffer &buf, boolean lqi)
|
||||
uint8_t m_lqi = buf.get8(idx + 21);
|
||||
idx += 22;
|
||||
|
||||
non_empty = true;
|
||||
if (i > 0) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
}
|
||||
@ -1110,6 +1114,27 @@ int32_t Z_Mgmt_Lqi_Bind_Rsp(int32_t res, const class SBuffer &buf, boolean lqi)
|
||||
TrueFalseNull(m_permitjoin & 0x02),
|
||||
m_depth,
|
||||
m_lqi);
|
||||
|
||||
// detect any router
|
||||
Z_Device & device = zigbee_devices.findShortAddr(m_shortaddr);
|
||||
if (device.valid()) {
|
||||
if ((m_dev_type & 0x03) == 1) { // it is a router
|
||||
device.setRouter(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Add information to zigbee mapper
|
||||
// Z_Mapper_Edge::Edge_Type edge_type;
|
||||
// switch ((m_dev_type & 0x70) >> 4) {
|
||||
// case 0: edge_type = Z_Mapper_Edge::Parent; break;
|
||||
// case 1: edge_type = Z_Mapper_Edge::Child; break;
|
||||
// case 2: edge_type = Z_Mapper_Edge::Sibling; break;
|
||||
// default: edge_type = Z_Mapper_Edge::Unknown; break;
|
||||
|
||||
// }
|
||||
// Z_Mapper_Edge edge(m_shortaddr, shortaddr, m_lqi, edge_type);
|
||||
Z_Mapper_Edge edge(m_shortaddr, shortaddr, m_lqi);
|
||||
zigbee_mapper.addEdge(edge);
|
||||
}
|
||||
|
||||
ResponseAppend_P(PSTR("]}}"));
|
||||
@ -1138,6 +1163,7 @@ int32_t Z_Mgmt_Lqi_Bind_Rsp(int32_t res, const class SBuffer &buf, boolean lqi)
|
||||
break; // abort for any other value since we don't know the length of the field
|
||||
}
|
||||
|
||||
non_empty = true;
|
||||
if (i > 0) {
|
||||
ResponseAppend_P(PSTR(","));
|
||||
}
|
||||
@ -1157,7 +1183,8 @@ int32_t Z_Mgmt_Lqi_Bind_Rsp(int32_t res, const class SBuffer &buf, boolean lqi)
|
||||
MqttPublishPrefixTopicRulesProcess_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEE_MAP));
|
||||
|
||||
// Check if there are more values waiting, if so re-send a new request to get other values
|
||||
if (start + len < total) {
|
||||
// Only send a new request if the current was non-empty. This avoids an infinite loop if the device announces more slots that it actually has.
|
||||
if ((non_empty) && (start + len < total)) {
|
||||
// there are more values to read
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
Z_Send_State_or_Map(shortaddr, start + len, lqi ? ZDO_MGMT_LQI_REQ : ZDO_MGMT_BIND_REQ);
|
||||
|
@ -1052,6 +1052,26 @@ void CmndZbBindState(void) {
|
||||
CmndZbBindState_or_Map(false);
|
||||
}
|
||||
|
||||
void ZigbeeMapAllDevices(void) {
|
||||
// we can't abort a mapping in progress
|
||||
if (zigbee.mapping_in_progress) { return; }
|
||||
// defer sending ZbMap to each device
|
||||
zigbee_mapper.reset(); // clear all data in Zigbee mapper
|
||||
|
||||
const static uint32_t DELAY_ZBMAP = 2000; // wait for 1s between commands
|
||||
uint32_t wait_ms = DELAY_ZBMAP;
|
||||
zigbee.mapping_in_progress = true; // mark mapping in progress
|
||||
|
||||
zigbee_devices.setTimer(0x0000, 0, 0 /*wait_ms*/, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||
for (const auto & device : zigbee_devices.getDevices()) {
|
||||
zigbee_devices.setTimer(device.shortaddr, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||
wait_ms += DELAY_ZBMAP;
|
||||
}
|
||||
wait_ms += DELAY_ZBMAP*2;
|
||||
zigbee_devices.setTimer(BAD_SHORTADDR, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||
zigbee.mapping_end_time = wait_ms + millis();
|
||||
}
|
||||
|
||||
//
|
||||
// Command `ZbMap`
|
||||
// `ZbMap<x>` as index if it does not fit. If default, `1` starts at the beginning
|
||||
@ -1061,15 +1081,7 @@ void CmndZbMap(void) {
|
||||
RemoveSpace(XdrvMailbox.data);
|
||||
|
||||
if (strlen(XdrvMailbox.data) == 0) {
|
||||
// defer sending ZbMap to each device
|
||||
const static uint32_t DELAY_ZBMAP = 2000; // wait for 1s between commands
|
||||
uint32_t wait_ms = DELAY_ZBMAP;
|
||||
zigbee_devices.setTimer(0x0000, 0, 0 /*wait_ms*/, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||
for (const auto & device : zigbee_devices.getDevices()) {
|
||||
zigbee_devices.setTimer(device.shortaddr, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||
wait_ms += DELAY_ZBMAP;
|
||||
}
|
||||
zigbee_devices.setTimer(BAD_SHORTADDR, 0, wait_ms, 0, 0, Z_CAT_ALWAYS, 0 /* value = index */, &Z_Map);
|
||||
ZigbeeMapAllDevices();
|
||||
ResponseCmndDone();
|
||||
} else {
|
||||
CmndZbBindState_or_Map(true);
|
||||
@ -1317,8 +1329,8 @@ void CmndZbSave(void) {
|
||||
case -10:
|
||||
{ // reinit EEPROM
|
||||
ZFS::erase();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
saveZigbeeDevices();
|
||||
@ -1698,6 +1710,16 @@ extern "C" {
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
#define WEB_HANDLE_ZB_MAP "Zigbee Map"
|
||||
#define WEB_HANDLE_ZB_PERMIT_JOIN "Zigbee Permit Join"
|
||||
#define WEB_HANDLE_ZB_MAP_REFRESH "Zigbee Map Refresh"
|
||||
const char HTTP_BTN_ZB_BUTTONS[] PROGMEM =
|
||||
"<button onclick='la(\"&zbj=1\");'>" WEB_HANDLE_ZB_PERMIT_JOIN "</button>"
|
||||
"<p></p>"
|
||||
"<form action='zbm' method='get'><button>" WEB_HANDLE_ZB_MAP "</button></form>";
|
||||
const char HTTP_AUTO_REFRESH_PAGE[] PROGMEM = "<script>setTimeout(function(){location.reload();},1990);</script>";
|
||||
const char HTTP_BTN_ZB_MAP_REFRESH[] PROGMEM = "<p></p><form action='zbr' method='get'><button>" WEB_HANDLE_ZB_MAP_REFRESH "</button></form>";
|
||||
|
||||
void ZigbeeShow(bool json)
|
||||
{
|
||||
if (json) {
|
||||
@ -1879,11 +1901,67 @@ void ZigbeeShow(bool json)
|
||||
}
|
||||
}
|
||||
|
||||
WSContentSend_P(PSTR("</table>{t}")); // Terminate current multi column table and open new table
|
||||
WSContentSend_P(PSTR("</table>{t}<p></p>")); // Terminate current multi column table and open new table
|
||||
if (zigbee.permit_end_time) {
|
||||
// PermitJoin in progress
|
||||
WSContentSend_P(PSTR("<p><b>[ <span style='color:#080;'>Devices allowed to join</span> ]</b></p>")); // Terminate current multi column table and open new table
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Web handler to refresh the map, the redirect to show map
|
||||
void ZigbeeMapRefresh(void) {
|
||||
if ((!zigbee.init_phase) && (!zigbee.mapping_in_progress)) {
|
||||
ZigbeeMapAllDevices();
|
||||
}
|
||||
Webserver->sendHeader("Location","/zbm"); // Add a header to respond with a new location for the browser to go to the home page again
|
||||
Webserver->send(302);
|
||||
}
|
||||
|
||||
// Display a graphical representation of the Zigbee map using vis.js network
|
||||
void ZigbeeShowMap(void) {
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP "Zigbee Mapper"));
|
||||
|
||||
// if no map, then launch a new mapping
|
||||
if ((!zigbee.init_phase) && (!zigbee.mapping_ready) && (!zigbee.mapping_in_progress)) {
|
||||
ZigbeeMapAllDevices();
|
||||
}
|
||||
|
||||
WSContentStart_P(PSTR("Tasmota Zigbee Mapping"));
|
||||
WSContentSendStyle();
|
||||
|
||||
if (zigbee.init_phase) {
|
||||
WSContentSend_P(PSTR("Zigbee not started"));
|
||||
} else if (zigbee.mapping_in_progress) {
|
||||
int32_t mapping_remaining = 1 + (zigbee.mapping_end_time - millis()) / 1000;
|
||||
if (mapping_remaining < 0) { mapping_remaining = 0; }
|
||||
WSContentSend_P(PSTR("Mapping in progress (%d s. remaining)"), mapping_remaining);
|
||||
WSContentSend_P(HTTP_AUTO_REFRESH_PAGE);
|
||||
} else if (!zigbee.mapping_ready) {
|
||||
WSContentSend_P(PSTR("No mapping"));
|
||||
} else {
|
||||
WSContentSend_P(PSTR(
|
||||
"<script type=\"text/javascript\" src=\"https://unpkg.com/vis-network/standalone/umd/vis-network.min.js\"></script>"
|
||||
"<div id=\"mynetwork\" style=\"background-color:#fff;color:#000;width:800px;height:400px;border:1px solid lightgray;resize:both;\">Unable to load vis.js</div>"
|
||||
"<script type=\"text/javascript\">"
|
||||
"var container=document.getElementById(\"mynetwork\");"
|
||||
"var options={groups:{o:{shape:\"circle\",color:\"#d55\"},r:{shape:\"box\",color:\"#fb7\"},e:{shape:\"ellipse\",color:\"#adf\"}}};"
|
||||
"var data={"
|
||||
));
|
||||
|
||||
zigbee_mapper.dumpInternals();
|
||||
|
||||
WSContentSend_P(PSTR(
|
||||
"};"
|
||||
"var network=new vis.Network(container,data,options);</script>"
|
||||
));
|
||||
WSContentSend_P(HTTP_BTN_ZB_MAP_REFRESH);
|
||||
}
|
||||
WSContentSpaceButton(BUTTON_MAIN);
|
||||
WSContentStop();
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
@ -1920,12 +1998,17 @@ bool Xdrv23(uint8_t function)
|
||||
case FUNC_WEB_SENSOR:
|
||||
ZigbeeShow(false);
|
||||
break;
|
||||
#ifdef USE_ZIGBEE_EZSP
|
||||
// GUI xmodem
|
||||
case FUNC_WEB_ADD_HANDLER:
|
||||
#ifdef USE_ZIGBEE_EZSP
|
||||
WebServer_on(PSTR("/" WEB_HANDLE_ZIGBEE_XFER), HandleZigbeeXfer);
|
||||
break;
|
||||
#endif // USE_ZIGBEE_EZSP
|
||||
WebServer_on(PSTR("/zbm"), ZigbeeShowMap, HTTP_GET); // add web handler for Zigbee map
|
||||
WebServer_on(PSTR("/zbr"), ZigbeeMapRefresh, HTTP_GET); // add web handler for Zigbee map refresh
|
||||
break;
|
||||
case FUNC_WEB_ADD_MAIN_BUTTON:
|
||||
WSContentSend_P(HTTP_BTN_ZB_BUTTONS);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
case FUNC_PRE_INIT:
|
||||
ZigbeeInit();
|
||||
|
@ -160,7 +160,7 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index)
|
||||
if (Settings.shutter_set50percent[index] != 50) {
|
||||
return (percent <= 5) ? Settings.shuttercoeff[2][index] * percent*10 : (Settings.shuttercoeff[1][index] * percent + (Settings.shuttercoeff[0][index]*10))*10;
|
||||
} else {
|
||||
uint32_t realpos;
|
||||
int64_t realpos;
|
||||
// check against DIV 0
|
||||
for (uint32_t j = 0; j < 5; j++) {
|
||||
if (0 == Settings.shuttercoeff[j][index]) {
|
||||
@ -173,13 +173,15 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index)
|
||||
for (uint32_t k = 0; k < 5; k++) {
|
||||
if ((percent * 10) >= Settings.shuttercoeff[k][index]) {
|
||||
realpos = SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[k+1], 100);
|
||||
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("Realposition TEMP1: %d, %% %d, coeff %d"), realpos, percent, Settings.shuttercoeff[i][index]);
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Realposition TEMP1: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]);
|
||||
} else {
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Shutter[%d].open_max: %d"),index, Shutter[index].open_max);
|
||||
if (0 == k) {
|
||||
realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]), 10);
|
||||
realpos = SHT_DIV_ROUND(SHT_DIV_ROUND(percent * Shutter[index].open_max * calibrate_pos[k+1], Settings.shuttercoeff[k][index]), 10 );
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Realposition TEMP3: %d, %d %%, coeff %d"), realpos, percent, Settings.shuttercoeff[k][index]);
|
||||
} else {
|
||||
//uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100;
|
||||
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("Realposition TEMP2: %d, %% %d, coeff %d"), addon, (calibrate_pos[i+1] - calibrate_pos[i]), (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]));
|
||||
//uint32_t addon = ( percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]) / (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]) / 100;
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Realposition TEMP2: %d, %d %%, coeff %d"), addon, (calibrate_pos[k+1] - calibrate_pos[k]), (Settings.shuttercoeff[k][index] -Settings.shuttercoeff[k-1][index]));
|
||||
realpos += SHT_DIV_ROUND(SHT_DIV_ROUND((percent*10 - Settings.shuttercoeff[k-1][index] ) * Shutter[index].open_max * (calibrate_pos[k+1] - calibrate_pos[k]), Settings.shuttercoeff[k][index] - Settings.shuttercoeff[k-1][index]), 100);
|
||||
}
|
||||
break;
|
||||
@ -189,25 +191,26 @@ int32_t ShutterPercentToRealPosition(uint32_t percent, uint32_t index)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ShutterRealToPercentPosition(int32_t realpos, uint32_t index)
|
||||
uint8_t ShutterRealToPercentPosition(int64_t realpos, uint32_t index)
|
||||
{
|
||||
if (Settings.shutter_set50percent[index] != 50) {
|
||||
return (Settings.shuttercoeff[2][index] * 5 > realpos/10) ? SHT_DIV_ROUND(realpos/10, Settings.shuttercoeff[2][index]) : SHT_DIV_ROUND(realpos/10-Settings.shuttercoeff[0][index]*10, Settings.shuttercoeff[1][index]);
|
||||
} else {
|
||||
uint16_t realpercent;
|
||||
|
||||
uint64_t realpercent;
|
||||
for (uint32_t j = 0; j < 5; j++) {
|
||||
if (realpos >= Shutter[index].open_max * calibrate_pos[j+1] / 100) {
|
||||
realpercent = SHT_DIV_ROUND(Settings.shuttercoeff[j][index], 10);
|
||||
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("Realpercent TEMP1: %d, %% %d, coeff %d"), realpercent, realpos, Shutter_Open_Max[index] * calibrate_pos[i+1] / 100);
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Realpercent TEMP1: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100);
|
||||
} else {
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Shutter[%d].open_max: %d"),index, Shutter[index].open_max);
|
||||
if (0 == j) {
|
||||
realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * 10 * Settings.shuttercoeff[j][index], calibrate_pos[j+1]), Shutter[index].open_max);
|
||||
realpercent = SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * Settings.shuttercoeff[j][index], calibrate_pos[j+1]/10), Shutter[index].open_max);
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Realpercent TEMP3: %d %%, %d, coeff %d"), realpercent, realpos, Shutter[index].open_max * calibrate_pos[j+1] / 100);
|
||||
} else {
|
||||
//uint16_t addon = ( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) * 10 * (Settings.shuttercoeff[i][index] - Settings.shuttercoeff[i-1][index]) / (calibrate_pos[i+1] - calibrate_pos[i])/ Shutter_Open_Max[index];
|
||||
//uint16_t addon = ( percent*10 - Settings.shuttercoeff[i-1][index] ) * Shutter_Open_Max[index] * (calibrate_pos[i+1] - calibrate_pos[i]) / (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]) / 100;
|
||||
//AddLog_P(LOG_LEVEL_DEBUG, PSTR("Realpercent TEMP2: %d, delta %d, %% %d, coeff %d"), addon,( realpos - (Shutter_Open_Max[index] * calibrate_pos[i] / 100) ) , (calibrate_pos[i+1] - calibrate_pos[i])* Shutter_Open_Max[index]/100, (Settings.shuttercoeff[i][index] -Settings.shuttercoeff[i-1][index]));
|
||||
realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])), Shutter[index].open_max) ;
|
||||
//uint16_t addon = ( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) * 10 * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]) / (calibrate_pos[j+1] - calibrate_pos[j])/Shutter[index].open_max;
|
||||
//uint16_t addon = ( realpercent*10 - Settings.shuttercoeff[j-1][index] ) * Shutter[index].open_max * (calibrate_pos[j+1] - calibrate_pos[j]) / (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]) / 100;
|
||||
//AddLog_P(LOG_LEVEL_ERROR, PSTR("Realpercent TEMP2: %d %%, delta %d, %d, coeff %d"), addon,( realpos - (Shutter[index].open_max * calibrate_pos[j] / 100) ) , (calibrate_pos[j+1] - calibrate_pos[j])* Shutter[index].open_max/100, (Settings.shuttercoeff[j][index] -Settings.shuttercoeff[j-1][index]));
|
||||
realpercent += SHT_DIV_ROUND(SHT_DIV_ROUND((realpos - SHT_DIV_ROUND(Shutter[index].open_max * calibrate_pos[j], 100)) * (Settings.shuttercoeff[j][index] - Settings.shuttercoeff[j-1][index]), (calibrate_pos[j+1] - calibrate_pos[j])/10), Shutter[index].open_max) ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -430,10 +433,6 @@ void ShutterDecellerateForStop(uint8_t i)
|
||||
void ShutterPowerOff(uint8_t i) {
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Stop Shutter %d. Switchmode %d"), i,Shutter[i].switch_mode);
|
||||
ShutterDecellerateForStop(i);
|
||||
if (Shutter[i].direction !=0) {
|
||||
Shutter[i].direction = 0;
|
||||
delay(MOTOR_STOP_TIME);
|
||||
}
|
||||
switch (Shutter[i].switch_mode) {
|
||||
case SHT_SWITCH:
|
||||
if ((1 << (Settings.shutter_startrelay[i]-1)) & TasmotaGlobal.power) {
|
||||
@ -449,7 +448,7 @@ void ShutterPowerOff(uint8_t i) {
|
||||
if ((SRC_PULSETIMER == TasmotaGlobal.last_source || SRC_SHUTTER == TasmotaGlobal.last_source || SRC_WEBGUI == TasmotaGlobal.last_source)) {
|
||||
ExecuteCommandPowerShutter(cur_relay, 1, SRC_SHUTTER);
|
||||
// switch off direction relay to make it power less
|
||||
if ((1 << (Settings.shutter_startrelay[i])) & TasmotaGlobal.power) {
|
||||
if (((1 << (Settings.shutter_startrelay[i])) & TasmotaGlobal.power) && Settings.shutter_startrelay[i]+1 != cur_relay) {
|
||||
ExecuteCommandPowerShutter(Settings.shutter_startrelay[i]+1, 0, SRC_SHUTTER);
|
||||
}
|
||||
} else {
|
||||
@ -465,6 +464,10 @@ void ShutterPowerOff(uint8_t i) {
|
||||
ExecuteCommand(scmnd, SRC_BUTTON);
|
||||
break;
|
||||
}
|
||||
if (Shutter[i].direction !=0) {
|
||||
Shutter[i].direction = 0;
|
||||
delay(MOTOR_STOP_TIME);
|
||||
}
|
||||
}
|
||||
|
||||
void ShutterUpdatePosition(void)
|
||||
@ -616,7 +619,7 @@ void ShutterRelayChanged(void)
|
||||
break;
|
||||
default:
|
||||
TasmotaGlobal.last_source = SRC_SHUTTER; // avoid switch off in the next loop
|
||||
if (Shutter[i].direction != 0 ) ShutterPowerOff(i);
|
||||
if (Shutter[i].direction != 0 ) Shutter[i].target_position = Shutter[i].real_position;
|
||||
}
|
||||
switch (ShutterGlobal.position_mode) {
|
||||
// enum Shutterposition_mode {SHT_TIME, SHT_TIME_UP_DOWN, SHT_TIME_GARAGE, SHT_COUNTER, SHT_PWM_VALUE, SHT_PWM_TIME,};
|
||||
@ -981,15 +984,10 @@ void CmndShutterStop(void)
|
||||
if (Shutter[i].direction != 0) {
|
||||
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("SHT: Stop moving %d: dir: %d"), XdrvMailbox.index, Shutter[i].direction);
|
||||
|
||||
int32_t temp_realpos = ShutterCalculatePosition(i);
|
||||
XdrvMailbox.payload = ShutterRealToPercentPosition(temp_realpos, i);
|
||||
TasmotaGlobal.last_source = SRC_WEBGUI;
|
||||
CmndShutterPosition();
|
||||
} else {
|
||||
if (XdrvMailbox.command)
|
||||
ResponseCmndDone();
|
||||
}
|
||||
Shutter[i].target_position = Shutter[i].real_position;
|
||||
}
|
||||
if (XdrvMailbox.command)
|
||||
ResponseCmndDone();
|
||||
} else {
|
||||
if (XdrvMailbox.command)
|
||||
ResponseCmndIdxChar("Locked");
|
||||
|
@ -76,6 +76,7 @@ bool tap_handled = false;
|
||||
bool invert_power_button_bri_direction = false;
|
||||
bool button_pressed[3] = { false, false, false };
|
||||
bool button_held[3];
|
||||
bool button_unprocessed[3] = { false, false, false };
|
||||
#ifdef USE_PWM_DIMMER_REMOTE
|
||||
struct remote_pwm_dimmer remote_pwm_dimmers[MAX_PWM_DIMMER_KEYS];
|
||||
struct remote_pwm_dimmer * active_remote_pwm_dimmer;
|
||||
@ -284,8 +285,18 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
|
||||
if (pressed) {
|
||||
uint32_t now = millis();
|
||||
|
||||
// If this is about the power button, ...
|
||||
if (is_power_button) {
|
||||
// If the button was pressed and released but was not processed by support_button because the
|
||||
// button interval had not elapsed,
|
||||
if (button_unprocessed[button_index]) {
|
||||
mqtt_trigger = 5;
|
||||
#ifdef USE_PWM_DIMMER_REMOTE
|
||||
if (!active_remote_pwm_dimmer) mqtt_trigger += button_index;
|
||||
#endif // USE_PWM_DIMMER_REMOTE
|
||||
button_hold_time[button_index] = now + 750;
|
||||
}
|
||||
|
||||
// Otherwise, if this is about the power button, ...
|
||||
else if (is_power_button) {
|
||||
|
||||
// If we're not ignoring the power button and no other buttons are pressed, ...
|
||||
if (!ignore_power_button && buttons_pressed == 1) {
|
||||
@ -325,8 +336,8 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
|
||||
// If the up or down button was tapped while holding the power button before this, handle
|
||||
// the operation below.
|
||||
if (button_tapped) {
|
||||
handle_tap = true;
|
||||
button_hold_time[button_index] = now + 500;
|
||||
handle_tap = ignore_power_button = true;
|
||||
button_hold_time[button_index] = now + 750;
|
||||
}
|
||||
|
||||
// Otherwise, if the power is on and remote mode is enabled, adjust the brightness. Set the
|
||||
@ -568,7 +579,7 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
|
||||
// If the up or down button was tapped while holding the power button and the up or down button
|
||||
// is being held or was just released after not being held, handle the operation.
|
||||
if (handle_tap) {
|
||||
ignore_power_button = tap_handled = true;
|
||||
tap_handled = true;
|
||||
|
||||
// If the down button was tapped while holding the power button, send a device group update to
|
||||
// select the previous/next fixed color.
|
||||
@ -591,9 +602,10 @@ void PWMDimmerHandleButton(uint32_t button_index, bool pressed)
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
;
|
||||
}
|
||||
// If the down button was tapped while holding the power button, publish an MQTT Event Trigger#.
|
||||
// If the up button was tapped while holding the power button, publish an MQTT Event Trigger#.
|
||||
else {
|
||||
mqtt_trigger = (is_down_button ? 3 : 4);
|
||||
mqtt_trigger = 3;
|
||||
if (is_down_button) mqtt_trigger = 4;
|
||||
}
|
||||
}
|
||||
|
||||
@ -739,7 +751,15 @@ bool Xdrv35(uint8_t function)
|
||||
// increment the buttons pressed count.
|
||||
if (!button_pressed[button_index]) {
|
||||
button_pressed[button_index] = true;
|
||||
button_hold_time[button_index] = now + (button_index == power_button_index ? 500 : 250);
|
||||
uint32_t hold_delay = 250;
|
||||
if (button_index == power_button_index) {
|
||||
#ifdef USE_PWM_DIMMER_REMOTE
|
||||
if (!(active_remote_pwm_dimmer ? active_remote_pwm_dimmer->power_on : TasmotaGlobal.power)) hold_delay = 500;
|
||||
#else // USE_PWM_DIMMER_REMOTE
|
||||
if (!TasmotaGlobal.power) hold_delay = 500;
|
||||
#endif // USE_PWM_DIMMER_REMOTE
|
||||
}
|
||||
button_hold_time[button_index] = now + hold_delay;
|
||||
buttons_pressed++;
|
||||
if (buttons_pressed > 1) multibutton_in_progress = true;
|
||||
|
||||
@ -796,6 +816,16 @@ bool Xdrv35(uint8_t function)
|
||||
// Set a timer so FUNC_ANY_KEY ignores the button if support_button winds up sending a
|
||||
// key because of this.
|
||||
ignore_any_key_time = now + 500;
|
||||
|
||||
// If a multi-button operation is in progress or the button was pressed, released and
|
||||
// then held, tell support_button that we've handled it.
|
||||
result = true;
|
||||
Button.press_counter[button_index] = 0;
|
||||
if (buttons_pressed == 0) multibutton_in_progress = false;
|
||||
button_unprocessed[button_index] = false;
|
||||
}
|
||||
else {
|
||||
button_unprocessed[button_index] = true;
|
||||
}
|
||||
|
||||
// If the power button was just released, clear the flags associated with it.
|
||||
@ -806,12 +836,6 @@ bool Xdrv35(uint8_t function)
|
||||
}
|
||||
button_held[button_index] = false;
|
||||
}
|
||||
|
||||
// If a multi-button operation is in progress, tell support_button that we've handled it.
|
||||
if (multibutton_in_progress) {
|
||||
result = true;
|
||||
if (buttons_pressed == 0) multibutton_in_progress = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -819,7 +843,9 @@ bool Xdrv35(uint8_t function)
|
||||
{
|
||||
uint32_t state = (XdrvMailbox.payload >> 8) & 0xFF; // 0 = Off, 1 = On, 2 = Toggle, 3 = Hold, 10,11,12,13 and 14 for Button Multipress
|
||||
if ((state == 2 || state == 10) && ignore_any_key_time < millis()) {
|
||||
PWMDimmerHandleButton((XdrvMailbox.payload & 0xFF) - 1, false);
|
||||
uint32_t button_index = (XdrvMailbox.payload & 0xFF) - 1;
|
||||
button_unprocessed[button_index] = false;
|
||||
PWMDimmerHandleButton(button_index, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -289,33 +289,27 @@ void TelegramSendGetMe(void) {
|
||||
String TelegramExecuteCommand(const char *svalue) {
|
||||
String response = "";
|
||||
|
||||
uint32_t curridx = TasmotaGlobal.web_log_index;
|
||||
uint32_t curridx = TasmotaGlobal.log_buffer_pointer;
|
||||
ExecuteCommand(svalue, SRC_CHAT);
|
||||
if (TasmotaGlobal.web_log_index != curridx) {
|
||||
uint32_t counter = curridx;
|
||||
if (TasmotaGlobal.log_buffer_pointer != curridx) {
|
||||
response = F("{");
|
||||
bool cflg = false;
|
||||
do {
|
||||
char* tmp;
|
||||
size_t len;
|
||||
GetLog(counter, &tmp, &len);
|
||||
if (len) {
|
||||
// [14:49:36 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
|
||||
char* JSON = (char*)memchr(tmp, '{', len);
|
||||
if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
|
||||
size_t JSONlen = len - (JSON - tmp);
|
||||
if (JSONlen > sizeof(TasmotaGlobal.mqtt_data)) { JSONlen = sizeof(TasmotaGlobal.mqtt_data); }
|
||||
char stemp[JSONlen];
|
||||
strlcpy(stemp, JSON +1, JSONlen -2);
|
||||
if (cflg) { response += F(","); }
|
||||
response += stemp;
|
||||
cflg = true;
|
||||
}
|
||||
uint32_t index = curridx;
|
||||
char* line;
|
||||
size_t len;
|
||||
while (GetLog(Settings.weblog_level, &index, &line, &len)) {
|
||||
// [14:49:36.123 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}] > [{"POWER":"OFF"}]
|
||||
char* JSON = (char*)memchr(line, '{', len);
|
||||
if (JSON) { // Is it a JSON message (and not only [15:26:08 MQT: stat/wemos5/POWER = O])
|
||||
size_t JSONlen = len - (JSON - line);
|
||||
if (JSONlen > sizeof(TasmotaGlobal.mqtt_data)) { JSONlen = sizeof(TasmotaGlobal.mqtt_data); }
|
||||
char stemp[JSONlen];
|
||||
strlcpy(stemp, JSON +1, JSONlen -2);
|
||||
if (cflg) { response += F(","); }
|
||||
response += stemp;
|
||||
cflg = true;
|
||||
}
|
||||
counter++;
|
||||
counter &= 0xFF;
|
||||
if (!counter) counter++; // Skip 0 as it is not allowed
|
||||
} while (counter != TasmotaGlobal.web_log_index);
|
||||
}
|
||||
response += F("}");
|
||||
} else {
|
||||
response = F("{\"" D_RSLT_WARNING "\":\"" D_ENABLE_WEBLOG_FOR_RESPONSE "\"}");
|
||||
|
@ -90,16 +90,16 @@ AudioGeneratorTalkie *talkie = nullptr;
|
||||
#define TWATCH_DAC_IIS_DOUT 3
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
#undef TWATCH_DAC_IIS_BCK
|
||||
#undef TWATCH_DAC_IIS_WS
|
||||
#undef TWATCH_DAC_IIS_DOUT
|
||||
#ifndef TWATCH_DAC_IIS_BCK
|
||||
#undef TWATCH_DAC_IIS_BCK
|
||||
#define TWATCH_DAC_IIS_BCK 26
|
||||
#endif
|
||||
#ifndef TWATCH_DAC_IIS_WS
|
||||
#undef TWATCH_DAC_IIS_WS
|
||||
#define TWATCH_DAC_IIS_WS 25
|
||||
#endif
|
||||
#ifndef TWATCH_DAC_IIS_DOUT
|
||||
#undef TWATCH_DAC_IIS_DOUT
|
||||
#define TWATCH_DAC_IIS_DOUT 33
|
||||
#endif
|
||||
#endif // ESP32
|
||||
|
@ -626,9 +626,9 @@ bool ShdSendVersion(void)
|
||||
void ShdGetSettings(void)
|
||||
{
|
||||
char parameters[32];
|
||||
Shd.req_brightness = 0;
|
||||
// Shd.req_brightness = 0;
|
||||
Shd.leading_edge = 0;
|
||||
Shd.req_fade_rate = 0;
|
||||
// Shd.req_fade_rate = 0;
|
||||
Shd.warmup_brightness = 0;
|
||||
Shd.warmup_time = 0;
|
||||
if (strstr(SettingsText(SET_SHD_PARAM), ",") != nullptr)
|
||||
@ -636,9 +636,9 @@ void ShdGetSettings(void)
|
||||
#ifdef SHELLY_DIMMER_DEBUG
|
||||
AddLog_P(LOG_LEVEL_INFO, PSTR(SHD_LOGNAME "Loading params: %s"), SettingsText(SET_SHD_PARAM));
|
||||
#endif // SHELLY_DIMMER_DEBUG
|
||||
Shd.req_brightness = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 1));
|
||||
// Shd.req_brightness = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 1));
|
||||
Shd.leading_edge = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 2));
|
||||
Shd.req_fade_rate = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 3));
|
||||
// Shd.req_fade_rate = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 3));
|
||||
Shd.warmup_brightness = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 4));
|
||||
Shd.warmup_time = atoi(subStr(parameters, SettingsText(SET_SHD_PARAM), ",", 5));
|
||||
}
|
||||
|
266
tasmota/xdrv_84_core2.ino
Normal file
266
tasmota/xdrv_84_core2.ino
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
xdrv_84_core2.ino - ESP32 m5stack core2 support for Tasmota
|
||||
|
||||
Copyright (C) 2020 Gerhard Mutz and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* remaining work:
|
||||
|
||||
i2s microphone, at least as loudness sensor
|
||||
rtc use after reboot, sync with internet on regular intervals.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
|
||||
#include <AXP192.h>
|
||||
#include <MPU6886.h>
|
||||
#include <BM8563_RTC.h>
|
||||
#include <i2c_bus.h>
|
||||
#include <soc/rtc.h>
|
||||
|
||||
#define XDRV_84 84
|
||||
|
||||
struct CORE2_globs {
|
||||
AXP192 Axp;
|
||||
MPU6886 Mpu;
|
||||
BM8563_RTC Rtc;
|
||||
bool ready;
|
||||
bool tset;
|
||||
uint32_t shutdownseconds;
|
||||
uint8_t shutdowndelay;
|
||||
|
||||
} core2_globs;
|
||||
|
||||
struct CORE2_ADC {
|
||||
float vbus_v;
|
||||
float batt_v;
|
||||
float temp;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t z;
|
||||
} core2_adc;
|
||||
|
||||
// cause SC card is needed by scripter
|
||||
void CORE2_Module_Init(void) {
|
||||
|
||||
// m5stack uses pin 38 not selectable in tasmota
|
||||
SPI.setFrequency(40000000);
|
||||
SPI.begin(18, 38, 23, -1);
|
||||
// establish power chip on wire1 SDA 21, SCL 22
|
||||
core2_globs.Axp.begin();
|
||||
I2cSetActiveFound(AXP_ADDR, "AXP192");
|
||||
|
||||
core2_globs.Axp.SetAdcState(true);
|
||||
|
||||
core2_globs.Mpu.Init();
|
||||
I2cSetActiveFound(MPU6886_ADDRESS, "MPU6886");
|
||||
|
||||
core2_globs.Rtc.begin();
|
||||
I2cSetActiveFound(RTC_ADRESS, "RTC");
|
||||
|
||||
core2_globs.ready = true;
|
||||
}
|
||||
|
||||
|
||||
void CORE2_Init(void) {
|
||||
|
||||
}
|
||||
|
||||
void CORE2_audio_power(bool power) {
|
||||
core2_globs.Axp.SetSpkEnable(power);
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_CORE2[] PROGMEM =
|
||||
"{s}VBUS Voltage" "{m}%s V" "{e}"
|
||||
"{s}BATT Voltage" "{m}%s V" "{e}"
|
||||
"{s}Chip Temperature" "{m}%s C" "{e}";
|
||||
#ifdef USE_MPU6886
|
||||
const char HTTP_CORE2_MPU[] PROGMEM =
|
||||
"{s}MPU x" "{m}%d mg" "{e}"
|
||||
"{s}MPU y" "{m}%d mg" "{e}"
|
||||
"{s}MPU z" "{m}%d mg" "{e}";
|
||||
#endif // USE_MPU6886
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
|
||||
void CORE2_loop(uint32_t flg) {
|
||||
}
|
||||
|
||||
void CORE2_WebShow(uint32_t json) {
|
||||
|
||||
char vstring[32];
|
||||
char bvstring[32];
|
||||
char tstring[32];
|
||||
dtostrfd(core2_adc.vbus_v, 3, vstring);
|
||||
dtostrfd(core2_adc.batt_v, 3, bvstring);
|
||||
dtostrfd(core2_adc.temp, 2, tstring);
|
||||
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"CORE2\":{\"VBV\":%s,\"BV\":%s,\"CT\":%s"), vstring, bvstring, tstring);
|
||||
|
||||
#ifdef USE_MPU6886
|
||||
ResponseAppend_P(PSTR(",\"MPUX\":%d,\"MPUY\":%d,\"MPUZ\":%d"), core2_adc.x, core2_adc.y, core2_adc.z);
|
||||
#endif
|
||||
ResponseJsonEnd();
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_CORE2, vstring, bvstring, tstring);
|
||||
|
||||
#ifdef USE_MPU6886
|
||||
WSContentSend_PD(HTTP_CORE2_MPU, core2_adc.x, core2_adc.y, core2_adc.z);
|
||||
#endif // USE_MPU6886
|
||||
}
|
||||
}
|
||||
|
||||
const char CORE2_Commands[] PROGMEM = "CORE2|"
|
||||
"SHUTDOWN";
|
||||
|
||||
void (* const CORE2_Command[])(void) PROGMEM = {
|
||||
&CORE2_Shutdown};
|
||||
|
||||
|
||||
void CORE2_Shutdown(void) {
|
||||
if (XdrvMailbox.payload >= 30) {
|
||||
core2_globs.shutdownseconds = XdrvMailbox.payload;
|
||||
core2_globs.shutdowndelay = 10;
|
||||
}
|
||||
ResponseCmndNumber(XdrvMailbox.payload -2);
|
||||
}
|
||||
|
||||
void CORE2_DoShutdown(void) {
|
||||
SettingsSaveAll();
|
||||
RtcSettingsSave();
|
||||
core2_globs.Rtc.clearIRQ();
|
||||
core2_globs.Rtc.SetAlarmIRQ(core2_globs.shutdownseconds);
|
||||
delay(10);
|
||||
core2_globs.Axp.PowerOff();
|
||||
}
|
||||
|
||||
extern uint8_t tbstate[3];
|
||||
|
||||
float core2_setaxppin(uint32_t sel, uint32_t val) {
|
||||
switch (sel) {
|
||||
case 0:
|
||||
core2_globs.Axp.SetLed(val);
|
||||
break;
|
||||
case 1:
|
||||
core2_globs.Axp.SetLDOEnable(3, val);
|
||||
break;
|
||||
case 2:
|
||||
if (val<1 || val>3) val = 1;
|
||||
return tbstate[val - 1] & 1;
|
||||
break;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void core2_disp_pwr(uint8_t on) {
|
||||
core2_globs.Axp.SetDCDC3(on);
|
||||
}
|
||||
|
||||
// display dimmer ranges from 0-15
|
||||
// very little effect
|
||||
void core2_disp_dim(uint8_t dim) {
|
||||
uint16_t voltage = 2200;
|
||||
|
||||
voltage += ((uint32_t)dim*1200)/15;
|
||||
core2_globs.Axp.SetLcdVoltage(voltage);
|
||||
|
||||
|
||||
// core2_globs.Axp.ScreenBreath(dim);
|
||||
|
||||
}
|
||||
|
||||
void CORE2_EverySecond(void) {
|
||||
if (core2_globs.ready) {
|
||||
CORE2_GetADC();
|
||||
|
||||
if (RtcTime.year>2000 && core2_globs.tset==false) {
|
||||
RTC_TimeTypeDef RTCtime;
|
||||
RTCtime.Hours = RtcTime.hour;
|
||||
RTCtime.Minutes = RtcTime.minute;
|
||||
RTCtime.Seconds = RtcTime.second;
|
||||
core2_globs.Rtc.SetTime(&RTCtime);
|
||||
core2_globs.tset = true;
|
||||
}
|
||||
|
||||
if (core2_globs.shutdowndelay) {
|
||||
core2_globs.shutdowndelay--;
|
||||
if (!core2_globs.shutdowndelay) {
|
||||
CORE2_DoShutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// currents are not supported by hardware implementation
|
||||
void CORE2_GetADC(void) {
|
||||
core2_adc.vbus_v = core2_globs.Axp.GetVBusVoltage();
|
||||
core2_adc.batt_v = core2_globs.Axp.GetBatVoltage();
|
||||
core2_adc.temp = core2_globs.Axp.GetTempInAXP192();
|
||||
#ifdef USE_MPU6886
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
core2_globs.Mpu.getAccelData(&x, &y, &z);
|
||||
core2_adc.x=x*1000;
|
||||
core2_adc.y=y*1000;
|
||||
core2_adc.z=z*1000;
|
||||
#endif // USE_MPU6886
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xdrv84(uint8_t function) {
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
|
||||
case FUNC_WEB_SENSOR:
|
||||
#ifdef USE_WEBSERVER
|
||||
CORE2_WebShow(0);
|
||||
#endif
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
CORE2_WebShow(1);
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = DecodeCommand(CORE2_Commands, CORE2_Command);
|
||||
break;
|
||||
case FUNC_MODULE_INIT:
|
||||
CORE2_Module_Init();
|
||||
break;
|
||||
case FUNC_INIT:
|
||||
CORE2_Init();
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
CORE2_EverySecond();
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
CORE2_loop(1);
|
||||
break;
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_M5STACK_CORE2
|
||||
#endif // ESP32
|
@ -20,7 +20,7 @@
|
||||
//#ifdef USE_SPI
|
||||
#ifdef USE_SPI
|
||||
#ifdef USE_DISPLAY
|
||||
#ifdef USE_DISPLAY_ILI9341_2
|
||||
#if (defined(USE_DISPLAY_ILI9341_2) || defined(USE_DISPLAY_ILI9342))
|
||||
|
||||
#define XDSP_13 13
|
||||
|
||||
@ -42,9 +42,13 @@ extern uint8_t *buffer;
|
||||
extern uint8_t color_type;
|
||||
ILI9341_2 *ili9341_2;
|
||||
|
||||
#ifdef USE_FT5206
|
||||
#include <FT5206.h>
|
||||
#undef FT6336_address
|
||||
#define FT6336_address 0x38
|
||||
uint8_t ili9342_ctouch_counter = 0;
|
||||
#endif // USE_FT5206
|
||||
|
||||
#undef BACKPLANE_PIN
|
||||
#define BACKPLANE_PIN 4
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
@ -54,6 +58,7 @@ void ILI9341_2_InitDriver()
|
||||
Settings.display_model = XDSP_13;
|
||||
}
|
||||
|
||||
|
||||
if (XDSP_13 == Settings.display_model) {
|
||||
|
||||
if (Settings.display_width != ILI9341_2_TFTWIDTH) {
|
||||
@ -70,13 +75,17 @@ void ILI9341_2_InitDriver()
|
||||
fg_color = ILI9341_2_WHITE;
|
||||
bg_color = ILI9341_2_BLACK;
|
||||
|
||||
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
ili9341_2 = new ILI9341_2(5, -2, 15, -2);
|
||||
#else
|
||||
// init renderer, may use hardware spi, however we use SSPI defintion because SD card uses SPI definition (2 spi busses)
|
||||
if (PinUsed(GPIO_SSPI_CS) && PinUsed(GPIO_OLED_RESET) && PinUsed(GPIO_BACKLIGHT) && PinUsed(GPIO_SSPI_MOSI) && PinUsed(GPIO_SSPI_MISO) && PinUsed(GPIO_SSPI_SCLK) && PinUsed(GPIO_SSPI_DC)) {
|
||||
ili9341_2 = new ILI9341_2(Pin(GPIO_SSPI_CS), Pin(GPIO_SSPI_MOSI), Pin(GPIO_SSPI_MISO), Pin(GPIO_SSPI_SCLK), Pin(GPIO_OLED_RESET), Pin(GPIO_SSPI_DC), Pin(GPIO_BACKLIGHT));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ili9341_2->init(Settings.display_width,Settings.display_height);
|
||||
renderer = ili9341_2;
|
||||
renderer->DisplayInit(DISPLAY_INIT_MODE,Settings.display_size,Settings.display_rotate,Settings.display_font);
|
||||
@ -92,9 +101,79 @@ void ILI9341_2_InitDriver()
|
||||
|
||||
color_type = COLOR_COLOR;
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_FT5206
|
||||
// start digitizer with fixed adress and pins for esp32
|
||||
#define SDA_2 21
|
||||
#define SCL_2 22
|
||||
Wire1.begin(SDA_2, SCL_2, 400000);
|
||||
Touch_Init(Wire1);
|
||||
#endif // USE_FT5206
|
||||
#endif // ESP32
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void core2_disp_pwr(uint8_t on);
|
||||
void core2_disp_dim(uint8_t dim);
|
||||
|
||||
void ili9342_bpwr(uint8_t on) {
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
core2_disp_pwr(on);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ili9342_dimm(uint8_t dim) {
|
||||
#ifdef USE_M5STACK_CORE2
|
||||
core2_disp_dim(dim);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ESP32
|
||||
#ifdef USE_FT5206
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
|
||||
void ili9342_RotConvert(int16_t *x, int16_t *y) {
|
||||
|
||||
int16_t temp;
|
||||
if (renderer) {
|
||||
uint8_t rot=renderer->getRotation();
|
||||
switch (rot) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
temp=*y;
|
||||
*y=renderer->height()-*x;
|
||||
*x=temp;
|
||||
break;
|
||||
case 2:
|
||||
*x=renderer->width()-*x;
|
||||
*y=renderer->height()-*y;
|
||||
break;
|
||||
case 3:
|
||||
temp=*y;
|
||||
*y=*x;
|
||||
*x=renderer->width()-temp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check digitizer hit
|
||||
void ili9342_CheckTouch() {
|
||||
ili9342_ctouch_counter++;
|
||||
if (2 == ili9342_ctouch_counter) {
|
||||
// every 100 ms should be enough
|
||||
ili9342_ctouch_counter = 0;
|
||||
Touch_Check(ili9342_RotConvert);
|
||||
}
|
||||
}
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
#endif // USE_FT5206
|
||||
#endif // ESP32
|
||||
|
||||
|
||||
/*********************************************************************************************/
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
@ -111,6 +190,15 @@ bool Xdsp13(uint8_t function)
|
||||
case FUNC_DISPLAY_MODEL:
|
||||
result = true;
|
||||
break;
|
||||
#ifdef USE_FT5206
|
||||
#ifdef USE_TOUCH_BUTTONS
|
||||
case FUNC_DISPLAY_EVERY_50_MSECOND:
|
||||
if (FT5206_found) {
|
||||
ili9342_CheckTouch();
|
||||
}
|
||||
break;
|
||||
#endif // USE_TOUCH_BUTTONS
|
||||
#endif // USE_FT5206
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -47,7 +47,11 @@ void (* const Ws2812Command[])(void) PROGMEM = {
|
||||
|
||||
#include <NeoPixelBus.h>
|
||||
|
||||
#if (USE_WS2812_CTYPE == NEO_GRB)
|
||||
#if (USE_WS2812_HARDWARE == NEO_HW_P9813)
|
||||
typedef P9813BgrFeature selectedNeoFeatureType;
|
||||
#undef USE_WS2812_DMA
|
||||
#undef USE_WS2812_INVERTED
|
||||
#elif (USE_WS2812_CTYPE == NEO_GRB)
|
||||
typedef NeoGrbFeature selectedNeoFeatureType;
|
||||
#elif (USE_WS2812_CTYPE == NEO_BRG)
|
||||
typedef NeoBrgFeature selectedNeoFeatureType;
|
||||
@ -105,7 +109,9 @@ void (* const Ws2812Command[])(void) PROGMEM = {
|
||||
|
||||
#else // No USE_WS2812_INVERTED
|
||||
|
||||
#if (USE_WS2812_HARDWARE == NEO_HW_WS2812X)
|
||||
#if (USE_WS2812_HARDWARE == NEO_HW_P9813)
|
||||
typedef P9813Method selectedNeoSpeedType;
|
||||
#elif (USE_WS2812_HARDWARE == NEO_HW_WS2812X)
|
||||
typedef NeoEsp8266BitBangWs2812xMethod selectedNeoSpeedType;
|
||||
#elif (USE_WS2812_HARDWARE == NEO_HW_SK6812)
|
||||
typedef NeoEsp8266BitBangSk6812Method selectedNeoSpeedType;
|
||||
@ -472,10 +478,14 @@ void Ws2812ShowScheme(void)
|
||||
|
||||
void Ws2812ModuleSelected(void)
|
||||
{
|
||||
#if (USE_WS2812_HARDWARE == NEO_HW_P9813)
|
||||
if (PinUsed(GPIO_P9813_CLK) && PinUsed(GPIO_P9813_DAT)) { // RGB led
|
||||
strip = new NeoPixelBus<selectedNeoFeatureType, selectedNeoSpeedType>(WS2812_MAX_LEDS, Pin(GPIO_P9813_CLK), Pin(GPIO_P9813_DAT));
|
||||
#else
|
||||
if (PinUsed(GPIO_WS2812)) { // RGB led
|
||||
|
||||
// For DMA, the Pin is ignored as it uses GPIO3 due to DMA hardware use.
|
||||
strip = new NeoPixelBus<selectedNeoFeatureType, selectedNeoSpeedType>(WS2812_MAX_LEDS, Pin(GPIO_WS2812));
|
||||
#endif // NEO_HW_P9813
|
||||
strip->Begin();
|
||||
|
||||
Ws2812Clear();
|
||||
|
@ -24,8 +24,13 @@
|
||||
*
|
||||
* Action LSC SmartLed (GreenRedBlue)
|
||||
* {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18}
|
||||
* {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,4064,0,4032,0,0,0],"FLAG":0,"BASE":18}
|
||||
* Polux E14 (BlueGreenRed) - Notice GPIO00 = 9 (Switch1)
|
||||
* {"NAME":"Polux RGBCW E14","GPIO":[9,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18}
|
||||
* Polux E14 (BlueGreenRed)
|
||||
* {"NAME":"Polux RGBCW E14","GPIO":[0,0,0,0,0,0,0,0,4065,0,4032,0,0,0],"FLAG":0,"BASE":18}
|
||||
* LE LampUX 907001-US
|
||||
* {"NAME":"LE LampUX 907001-US","GPIO":[0,0,0,0,0,0,0,0,4066,0,4032,0,0,0],"FLAG":0,"BASE":18}
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XLGT_04 4
|
||||
@ -53,14 +58,12 @@
|
||||
#define SM2135_55MA 0x09
|
||||
#define SM2135_60MA 0x0A
|
||||
|
||||
enum Sm2135Color { SM2135_WCGRB, SM2135_WCBGR };
|
||||
|
||||
// RGB current CW current
|
||||
const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_15MA; // See https://github.com/arendst/Tasmota/issues/6495#issuecomment-549121683
|
||||
enum Sm2135Color { SM2135_WCGRB, SM2135_WCBGR, SM2135_WCGRBHI, SM2135_WCBGRHI };
|
||||
|
||||
struct SM2135 {
|
||||
uint8_t clk = 0;
|
||||
uint8_t data = 0;
|
||||
uint8_t current;
|
||||
uint8_t model = SM2135_WCGRB;
|
||||
} Sm2135;
|
||||
|
||||
@ -135,50 +138,69 @@ bool Sm2135SetChannels(void) {
|
||||
uint8_t *cur_col = (uint8_t*)XdrvMailbox.data;
|
||||
uint8_t data[6];
|
||||
|
||||
Sm2135Start(SM2135_ADDR_MC);
|
||||
Sm2135Write(SM2135_CURRENT);
|
||||
if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) {
|
||||
Sm2135Write(SM2135_CW);
|
||||
Sm2135Stop();
|
||||
delay(1);
|
||||
Sm2135Start(SM2135_ADDR_C);
|
||||
Sm2135Write(cur_col[4]); // Warm
|
||||
Sm2135Write(cur_col[3]); // Cold
|
||||
} else {
|
||||
uint32_t light_type = 3; // RGB and CW
|
||||
if (Sm2135.model < 2) {
|
||||
if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) {
|
||||
light_type = 1; // CW only
|
||||
} else {
|
||||
light_type = 2; // RGB only
|
||||
}
|
||||
}
|
||||
if (light_type &2) { // Set RGB
|
||||
Sm2135Start(SM2135_ADDR_MC);
|
||||
Sm2135Write(Sm2135.current);
|
||||
Sm2135Write(SM2135_RGB);
|
||||
if (SM2135_WCBGR == Sm2135.model) {
|
||||
if (Sm2135.model &1) { // SM2135_WCBGR
|
||||
Sm2135Write(cur_col[2]); // Blue
|
||||
Sm2135Write(cur_col[1]); // Green
|
||||
Sm2135Write(cur_col[0]); // Red
|
||||
} else {
|
||||
} else { // SM2135_WCGRB
|
||||
Sm2135Write(cur_col[1]); // Green
|
||||
Sm2135Write(cur_col[0]); // Red
|
||||
Sm2135Write(cur_col[2]); // Blue
|
||||
}
|
||||
Sm2135Stop();
|
||||
}
|
||||
if (light_type &1) { // Set CW
|
||||
Sm2135Start(SM2135_ADDR_MC);
|
||||
Sm2135Write(Sm2135.current);
|
||||
Sm2135Write(SM2135_CW);
|
||||
Sm2135Stop();
|
||||
delay(1);
|
||||
Sm2135Start(SM2135_ADDR_C);
|
||||
Sm2135Write(cur_col[4]); // Warm
|
||||
Sm2135Write(cur_col[3]); // Cold
|
||||
Sm2135Stop();
|
||||
}
|
||||
Sm2135Stop();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Sm2135ModuleSelected(void)
|
||||
{
|
||||
if (PinUsed(GPIO_SM2135_CLK) && PinUsed(GPIO_SM2135_DAT)) {
|
||||
if (PinUsed(GPIO_SM2135_CLK) && PinUsed(GPIO_SM2135_DAT, GPIO_ANY)) {
|
||||
Sm2135.clk = Pin(GPIO_SM2135_CLK);
|
||||
Sm2135.data = Pin(GPIO_SM2135_DAT);
|
||||
Sm2135.data = Pin(GPIO_SM2135_DAT, GPIO_ANY);
|
||||
|
||||
Sm2135.model = SM2135_WCGRB;
|
||||
Sm2135.model = GetPin(Sm2135.data) - AGPIO(GPIO_SM2135_DAT); // 0 .. 3
|
||||
if (PinUsed(GPIO_SWT1)) {
|
||||
Sm2135.model = SM2135_WCBGR;
|
||||
pinMode(Pin(GPIO_SWT1), INPUT); // Discard GPIO_SWT functionality
|
||||
SetPin(Pin(GPIO_SWT1), AGPIO(GPIO_NONE));
|
||||
}
|
||||
|
||||
// RGB current CW current
|
||||
Sm2135.current = (SM2135_20MA << 4) | SM2135_15MA; // See https://github.com/arendst/Tasmota/issues/6495#issuecomment-549121683
|
||||
if (Sm2135.model > SM2135_WCBGR) {
|
||||
Sm2135.current = (SM2135_20MA << 4) | SM2135_30MA;
|
||||
}
|
||||
|
||||
Sm2135Init();
|
||||
|
||||
TasmotaGlobal.light_type = LT_RGBWC;
|
||||
TasmotaGlobal.light_driver = XLGT_04;
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 (%s) Found"), (SM2135_WCBGR == Sm2135.model) ? PSTR("BGR") : PSTR("GRB"));
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("LGT: SM2135 (%s-%s current) Found"),
|
||||
(SM2135_WCBGR == (Sm2135.model &1)) ? PSTR("BGR") : PSTR("GRB"), (Sm2135.model > SM2135_WCBGR) ? PSTR("High") : PSTR("Low"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,12 +27,15 @@
|
||||
#ifdef ESP8266
|
||||
#define ANALOG_RESOLUTION 10 // 12 = 4095, 11 = 2047, 10 = 1023
|
||||
#define ANALOG_RANGE 1023 // 4095 = 12, 2047 = 11, 1023 = 10
|
||||
#define ANALOG_PERCENT 10 // backward compatible div10 range
|
||||
#endif // ESP8266
|
||||
#ifdef ESP32
|
||||
#undef ANALOG_RESOLUTION
|
||||
#define ANALOG_RESOLUTION 12 // 12 = 4095, 11 = 2047, 10 = 1023
|
||||
#undef ANALOG_RANGE
|
||||
#define ANALOG_RANGE 4095 // 4095 = 12, 2047 = 11, 1023 = 10
|
||||
#undef ANALOG_PERCENT
|
||||
#define ANALOG_PERCENT ((ANALOG_RANGE + 50) / 100) // approximation to 1% ADC range
|
||||
#endif // ESP32
|
||||
|
||||
#define TO_CELSIUS(x) ((x) - 273.15)
|
||||
@ -259,9 +262,9 @@ void AdcEvery250ms(void) {
|
||||
#endif
|
||||
if (ADC_INPUT == Adc[idx].type) {
|
||||
uint16_t new_value = AdcRead(Adc[idx].pin, 5);
|
||||
if ((new_value < Adc[idx].last_value -10) || (new_value > Adc[idx].last_value +10)) {
|
||||
if ((new_value < Adc[idx].last_value -ANALOG_PERCENT) || (new_value > Adc[idx].last_value +ANALOG_PERCENT)) {
|
||||
Adc[idx].last_value = new_value;
|
||||
uint16_t value = Adc[idx].last_value / 10;
|
||||
uint16_t value = Adc[idx].last_value / ANALOG_PERCENT;
|
||||
Response_P(PSTR("{\"ANALOG\":{\"A%ddiv10\":%d}}"), idx + offset, (value > 99) ? 100 : value);
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
|
@ -38,7 +38,9 @@
|
||||
#define W1_WRITE_SCRATCHPAD 0x4E
|
||||
#define W1_READ_SCRATCHPAD 0xBE
|
||||
|
||||
#ifndef DS18X20_MAX_SENSORS // DS18X20_MAX_SENSORS fallback to 8 if not defined in user_config_override.h
|
||||
#define DS18X20_MAX_SENSORS 8
|
||||
#endif
|
||||
|
||||
const char kDs18x20Types[] PROGMEM = "DS18x20|DS18S20|DS1822|DS18B20|MAX31850";
|
||||
|
||||
|
@ -52,7 +52,7 @@ bool DhtWaitState(uint32_t sensor, uint32_t level)
|
||||
unsigned long timeout = micros() + 100;
|
||||
while (digitalRead(Dht[sensor].pin) != level) {
|
||||
if (TimeReachedUsec(timeout)) {
|
||||
PrepLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE),
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_DHT D_TIMEOUT_WAITING_FOR " %s " D_PULSE),
|
||||
(level) ? D_START_SIGNAL_HIGH : D_START_SIGNAL_LOW);
|
||||
return false;
|
||||
}
|
||||
|
@ -69,7 +69,8 @@ const char HTTP_MGC_3130_SNS[] PROGMEM =
|
||||
"{s}" "%s" "{m}%s{e}"
|
||||
"{s}" "HwRev" "{m}%u.%u{e}"
|
||||
"{s}" "loaderVer" "{m}%u.%u{e}"
|
||||
"{s}" "platVer" "{m}%u{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
"{s}" "platVer" "{m}%u{e}"
|
||||
"{s}" "NoisePower" "{m}%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
|
||||
@ -152,17 +153,18 @@ union MGC3130_Union{
|
||||
float SDData[4]; // signal deviation
|
||||
} out;
|
||||
struct {
|
||||
uint8_t header[3];
|
||||
uint8_t header[4];
|
||||
// payload
|
||||
uint8_t valid;
|
||||
uint8_t valid; // 0xAA is valid
|
||||
uint8_t hwRev[2];
|
||||
uint8_t parameterStartAddr;
|
||||
uint8_t loaderVersion[2];
|
||||
uint8_t loaderPlatform;
|
||||
uint8_t fwStartAddr;
|
||||
uint8_t fwStartAddr; // should be 0x20
|
||||
char fwVersion[120];
|
||||
} fw;
|
||||
struct{
|
||||
uint8_t header[4];
|
||||
uint8_t id;
|
||||
uint8_t size;
|
||||
uint16_t error;
|
||||
@ -180,7 +182,7 @@ int16_t MGC3130_rotValue, MGC3130_lastSentRotValue = 0;
|
||||
uint16_t MGC3130_lastSentX, MGC3130_lastSentY, MGC3130_lastSentZ = 0;
|
||||
|
||||
uint8_t hwRev[2], loaderVersion[2], loaderPlatform = 0;
|
||||
char MGC3130_firmwareInfo[20];
|
||||
float MGC3130_noisePower = -1;
|
||||
|
||||
uint8_t MGC3130_touchTimeout = 0;
|
||||
uint16_t MGC3130_touchCounter = 1; // measure how long you touch the surface in loop cycles
|
||||
@ -194,6 +196,7 @@ uint8_t MGC3130_mode = 1; // 1-gesture; 2-airwheel; 3-position
|
||||
uint8_t MGC3130autoCal[] = {0x10, 0x00, 0x00, 0xA2, 0x80, 0x00 , 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
uint8_t MGC3130disableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
|
||||
uint8_t MGC3130enableAirwheel[] = {0x10, 0x00, 0x00, 0xA2, 0x90, 0x00 , 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00};
|
||||
uint8_t MGC3130enableAll[] = {0x10, 0x00, 0x00, 0xA2, 0xA0, 0x00 , 0x00, 0x00, 0x3f, 0x18, 0x00, 0x00, 0x3f, 0x18, 0x00, 0x00};
|
||||
|
||||
void MGC3130_handleSensorData(){
|
||||
if ( MGC_data.out.outputConfigMask.touchInfo && MGC3130_touchTimeout == 0){
|
||||
@ -220,6 +223,9 @@ void MGC3130_handleSensorData(){
|
||||
MqttPublishSensor();
|
||||
}
|
||||
}
|
||||
if(MGC_data.out.systemInfo.noisePowerValid){
|
||||
MGC3130_noisePower = MGC_data.out.noisePower;
|
||||
}
|
||||
}
|
||||
|
||||
void MGC3130_sendMessage(uint8_t data[], uint8_t length){
|
||||
@ -394,7 +400,7 @@ void MGC3130_handleAirWheel(){
|
||||
}
|
||||
|
||||
void MGC3130_handleSystemStatus(){
|
||||
//Serial.println("Got System status");
|
||||
AddLog_P(LOG_LEVEL_DEBUG,PSTR("MGC3130: system_status: response to ID:%02x, error code: %04x"),MGC_data.status.id, MGC_data.status.error);
|
||||
}
|
||||
|
||||
bool MGC3130_receiveMessage(){
|
||||
@ -407,16 +413,15 @@ bool MGC3130_receiveMessage(){
|
||||
MGC3130_handleSystemStatus();
|
||||
break;
|
||||
case MGC3130_FW_VERSION:
|
||||
hwRev[0] = MGC_data.fw.hwRev[1];
|
||||
hwRev[1] = MGC_data.fw.hwRev[0];
|
||||
loaderVersion[0] = MGC_data.fw.loaderVersion[0];
|
||||
loaderVersion[1] = MGC_data.fw.loaderVersion[1];
|
||||
hwRev[1] = MGC_data.fw.hwRev[1];
|
||||
hwRev[0] = MGC_data.fw.hwRev[0];
|
||||
loaderVersion[1] = MGC_data.fw.loaderVersion[0];
|
||||
loaderVersion[0] = MGC_data.fw.loaderVersion[1];
|
||||
loaderPlatform = MGC_data.fw.loaderPlatform;
|
||||
snprintf_P(MGC3130_firmwareInfo, sizeof(MGC3130_firmwareInfo), PSTR("FW: %s"), MGC_data.fw.fwVersion);
|
||||
MGC3130_firmwareInfo[20] = '\0';
|
||||
// Serial.print(MGC3130_firmwareInfo);
|
||||
AddLog_P(LOG_LEVEL_INFO,PSTR("MGC3130: GestIC:%s"),MGC_data.fw.fwVersion);
|
||||
break;
|
||||
}
|
||||
MGC_data.out.id = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -424,11 +429,12 @@ bool MGC3130_receiveMessage(){
|
||||
|
||||
bool MGC3130_readData()
|
||||
{
|
||||
static uint8_t _lastCounter = 0;
|
||||
bool success = false;
|
||||
if (!digitalRead(MGC3130_xfer)){
|
||||
pinMode(MGC3130_xfer, OUTPUT);
|
||||
digitalWrite(MGC3130_xfer, LOW);
|
||||
Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)32); // request usual data output
|
||||
Wire.requestFrom(MGC3130_I2C_ADDR, (uint16_t)132); // request maximal data output
|
||||
|
||||
MGC_data.buffer[0] = 4; // read at least header, but update after first read anyway
|
||||
unsigned char i = 0;
|
||||
@ -438,6 +444,14 @@ bool MGC3130_readData()
|
||||
}
|
||||
digitalWrite(MGC3130_xfer, HIGH);
|
||||
pinMode(MGC3130_xfer, INPUT);
|
||||
uint8_t _mismatch = MGC_data.out.counter - _lastCounter;
|
||||
if(_mismatch != 1){
|
||||
if(i>4 && MGC_data.out.id != MGC3130_FW_VERSION){
|
||||
AddLog_P(LOG_LEVEL_DEBUG,PSTR("MGC3130: missed a packet, mismatch: %u"), _mismatch - 1);
|
||||
AddLogBuffer(LOG_LEVEL_DEBUG,MGC_data.buffer,i);
|
||||
}
|
||||
}
|
||||
_lastCounter = MGC_data.out.counter;
|
||||
success = true;
|
||||
}
|
||||
return success;
|
||||
@ -537,7 +551,9 @@ void MGC3130_show(bool json)
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform );
|
||||
char _noise[FLOATSZ];
|
||||
dtostrfd(MGC3130_noisePower, 2, _noise);
|
||||
WSContentSend_PD(HTTP_MGC_3130_SNS, MGC3130stype, status_chr, hwRev[0], hwRev[1], loaderVersion[0], loaderVersion[1], loaderPlatform, _noise);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
@ -552,6 +568,7 @@ void MGC3130_show(bool json)
|
||||
* Sensor36 | 1 | Gesture Mode
|
||||
* Sensor36 | 2 | Airwheel Mode
|
||||
* Sensor36 | 3 | Position Mode with x,y,z - z must be higher than half of the max. sensing height
|
||||
* Sensor36 | 4 | Enable all data for debugging (noise level in web GUI)
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool MGC3130CommandSensor()
|
||||
@ -573,8 +590,12 @@ bool MGC3130CommandSensor()
|
||||
case 3: // position & touch
|
||||
MGC3130_mode = 3;
|
||||
MGC3130_sendMessage(MGC3130disableAirwheel,16);
|
||||
break;
|
||||
break;
|
||||
case 4: // enable all readings for noise level for web GUI
|
||||
MGC3130_sendMessage(MGC3130enableAll,16);
|
||||
break;
|
||||
}
|
||||
Response_P(PSTR("{\"MGC3130\":{\"mode\":%d}}"), MGC3130_mode);
|
||||
return serviced;
|
||||
}
|
||||
|
||||
@ -614,4 +635,4 @@ bool Xsns36(uint8_t function)
|
||||
return result;
|
||||
}
|
||||
#endif // USE_MGC3130
|
||||
#endif // USE_I2C
|
||||
#endif // USE_I2C
|
||||
|
@ -24,6 +24,61 @@
|
||||
|
||||
#define XSNS_75 75
|
||||
|
||||
const char *UnitfromType(const char *type) // find unit for measurment type
|
||||
{
|
||||
if (strcmp(type, "time") == 0)
|
||||
{
|
||||
return "_seconds";
|
||||
}
|
||||
if (strcmp(type, "temperature") == 0 || strcmp(type, "dewpoint") == 0)
|
||||
{
|
||||
return "_celsius";
|
||||
}
|
||||
if (strcmp(type, "pressure") == 0)
|
||||
{
|
||||
return "_hpa";
|
||||
}
|
||||
if (strcmp(type, "voltage") == 0)
|
||||
{
|
||||
return "_volts";
|
||||
}
|
||||
if (strcmp(type, "current") == 0)
|
||||
{
|
||||
return "_amperes";
|
||||
}
|
||||
if (strcmp(type, "mass") == 0)
|
||||
{
|
||||
return "_grams";
|
||||
}
|
||||
if (strcmp(type, "carbondioxide") == 0)
|
||||
{
|
||||
return "_ppm";
|
||||
}
|
||||
if (strcmp(type, "humidity") == 0)
|
||||
{
|
||||
return "_percentage";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *FormatMetricName(const char *metric) // cleanup spaces and uppercases for Prmetheus metrics conventions
|
||||
{
|
||||
char *formated = (char *)malloc(strlen(metric)+1);
|
||||
uint32_t cnt = 0;
|
||||
for (cnt; cnt < strlen(metric)+1; cnt++)
|
||||
{
|
||||
if (metric[cnt] == ' ')
|
||||
{
|
||||
formated[cnt] = '_';
|
||||
}
|
||||
else
|
||||
{
|
||||
formated[cnt] = tolower(metric[cnt]);
|
||||
}
|
||||
}
|
||||
return formated;
|
||||
}
|
||||
|
||||
void HandleMetrics(void)
|
||||
{
|
||||
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||
@ -75,19 +130,68 @@ void HandleMetrics(void)
|
||||
WSContentSend_P(PSTR("# TYPE energy_power_kilowatts_total counter\nenergy_power_kilowatts_total %s\n"), parameter);
|
||||
#endif
|
||||
|
||||
/*
|
||||
// Alternative method using the complete sensor JSON data
|
||||
// For prometheus it may need to be decoded to # TYPE messages
|
||||
for (uint32_t device = 0; device < TasmotaGlobal.devices_present; device++) {
|
||||
power_t mask = 1 << device;
|
||||
WSContentSend_P(PSTR("# TYPE relay%d_state gauge\nrelay%d_state %d\n"), device+1, device+1, (TasmotaGlobal.power & mask));
|
||||
}
|
||||
|
||||
ResponseClear();
|
||||
MqttShowSensor();
|
||||
char json[strlen(TasmotaGlobal.mqtt_data) +1];
|
||||
MqttShowSensor(); //Pull sensor data
|
||||
char json[strlen(TasmotaGlobal.mqtt_data)+1];
|
||||
snprintf_P(json, sizeof(json), TasmotaGlobal.mqtt_data);
|
||||
|
||||
// Do your Prometheus specific processing here.
|
||||
// Look at function DisplayAnalyzeJson() in file xdrv_13_display.ino as an example how to decode the JSON message
|
||||
|
||||
WSContentSend_P(json);
|
||||
*/
|
||||
String jsonStr = json;
|
||||
JsonParser parser((char *)jsonStr.c_str());
|
||||
JsonParserObject root = parser.getRootObject();
|
||||
if (root)
|
||||
{ // did JSON parsing went ok?
|
||||
for (auto key1 : root)
|
||||
{
|
||||
JsonParserToken value1 = key1.getValue();
|
||||
if (value1.isObject())
|
||||
{
|
||||
JsonParserObject Object2 = value1.getObject();
|
||||
for (auto key2 : Object2)
|
||||
{
|
||||
JsonParserToken value2 = key2.getValue();
|
||||
if (value2.isObject())
|
||||
{
|
||||
JsonParserObject Object3 = value2.getObject();
|
||||
for (auto key3 : Object3)
|
||||
{
|
||||
const char *value = key3.getValue().getStr(nullptr);
|
||||
if (value != nullptr && isdigit(value[0]))
|
||||
{
|
||||
const char *sensor = FormatMetricName(key2.getStr()); //cleanup sensor name
|
||||
const char *type = FormatMetricName(key3.getStr()); //cleanup sensor type
|
||||
const char *unit = UnitfromType(type); //grab base unit corresponding to type
|
||||
WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s%s gauge\ntasmota_sensors_%s%s{sensor=\"%s\"} %s\n"), type, unit, type, unit, sensor, value); //build metric as "# TYPE tasmota_sensors_%type%_%unit% gauge\ntasmotasensors_%type%_%unit%{sensor=%sensor%"} %value%""
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *value = value2.getStr(nullptr);
|
||||
if (value != nullptr && isdigit(value[0]))
|
||||
{
|
||||
const char *sensor = FormatMetricName(key1.getStr());
|
||||
const char *type = FormatMetricName(key2.getStr());
|
||||
const char *unit = UnitfromType(type);
|
||||
WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s%s gauge\ntasmota_sensors_%s%s{sensor=\"%s\"} %s\n"), type, unit, type, unit, sensor, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *value = value1.getStr(nullptr);
|
||||
if (value != nullptr && isdigit(value[0] && strcmp(key1.getStr(), "Time") != 0)) //remove false 'time' metric
|
||||
{
|
||||
const char *sensor = FormatMetricName(key1.getStr());
|
||||
WSContentSend_P(PSTR("# TYPE tasmota_sensors_%s gauge\ntasmota_sensors{sensor=\"%s\"} %s\n"), sensor, sensor, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WSContentEnd();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user