Merge pull request #3 from arendst/development

Update to 6.5.0.4
This commit is contained in:
Jason2866 2019-04-05 08:34:17 +02:00 committed by GitHub
commit e75f023349
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
200 changed files with 8683 additions and 17545 deletions

View File

@ -4,39 +4,61 @@ about: Create a report to help us improve
---
**IMPORTANT NOTICE**
If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses.
<GUIDE>
**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED**
<This BUG issue template is meant to REPORT Tasmota software BUGS ONLY>
<Please DO NOT OPEN AN ISSUE:>
<If your Tasmota version is not the latest, please update before posting. Your issue might be already solved. Latest precompiled bins of Tasmota can be downloaded from http://thehackbox.org/tasmota/>
<If your issue is a flashing issue, please address that to the Tasmota Support Chat>
<If your issue is compilation problem, please address that to the Tasmota Support Chat>
<If your issue has been addresed before (duplicated issue), please ask in the original issue>
<If your issue is wifi problem or mqtt problem, please try first the steps provided in troubleshooting of the wiki>
**Describe the bug**
### BUG DESCRIPTION
_A clear and concise description of what the bug is._
_Also, make sure these boxes are checked [x] before submitting your issue - Thank you!_
- [ ] _Searched the problem in issues and in the wiki_
- [ ] _Hardware used_ :
- [ ] _Development/Compiler/Upload tools used_ :
- [ ] _If a pre-compiled release or development binary was used, which one?_ :
- [ ] _You have tried latest release or development binaries?_ :
- [ ] _Provide the output of command_``status 0`` :
### REQUESTED INFORMATION
_Make sure these boxes are checked before submitting your issue. Thank you_
**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED**
- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md)
- [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues)
- [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting)
- [ ] 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 (i.e. Sonoff Basic) : _____
- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?)
- [ ] Development IDE - Compiler / Upload tools used : ____ / ____
- [ ] Provide the output of command ``status 0`` :
```
STATUS 0 OUTPUT HERE - DO NOT DELETE THE MARKERS ABOVE AND BELOW THIS LINE
STATUS 0 OUTPUT HERE:
```
- [ ] Provide the output of console when you experience your issue if apply :
_(Please use_ ``weblog 4`` _for more debug information)_
```
CONSOLE OUTPUT HERE:
```
**To Reproduce**
### TO REPRODUCE
_Steps to reproduce the behavior:_
**Expected behavior**
### EXPECTED BEHAVIOUR
_A clear and concise description of what you expected to happen._
**Screenshots**
### SCREENSHOTS
_If applicable, add screenshots to help explain your problem._
**Additional context**
### ADDITIONAL CONTEXT
_Add any other context about the problem here._

View File

@ -4,24 +4,47 @@ about: Users Troubleshooting Help
---
**IMPORTANT NOTICE**
If you do not complete the template below it is likely that your issue will not be addressed. When providing information about your issue please be as extensive as possible so that it can be solved by as little as possible responses.
<GUIDE>
<This troubleshooting issue template is meant to help Tasmota users with difficult problems. It is aimed to be opened if using the wiki and the support chat could not solve the issue. The Github Issue tracker is NOT a general discussion forum>
<Please DO NOT OPEN AN ISSUE:>
<If you have general questions or you need help on Tasmota usage, go to the Tasmota support chat>
<If your Tasmota version is not the latest, please update before posting. Your issue might be already solved. Latest precompiled bins of Tasmota can be downloaded from http://thehackbox.org/tasmota/>
<If your issue is a new device, please use the Tasmota Template Feature. See wiki for that>
<If your issue is a flashing issue, please address that to the Tasmota Support Chat>
<If your issue is compilation problem, please address that to the Tasmota Support Chat>
<If your issue has been addresed before (duplicated issue), please ask in the original issue>
<If your issue is wifi problem or mqtt problem, please try first the steps provided in troubleshooting of the wiki>
### ISSUE DESCRIPTION - TROUBLESHOOTING
_A clear description of what the issue is and be as extensive as possible_
### REQUESTED INFORMATION
_Make sure these boxes are checked before submitting your issue. Thank you_
**FAILURE TO COMPLETE THE REQUESTED INFORMATION WILL RESULT IN YOUR ISSUE BEING CLOSED**
Make sure these boxes are checked [x] before submitting your issue - Thank you!
- [ ] Read the [Contributing Guide and Policy](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md) and [the Code of Conduct](https://github.com/arendst/Sonoff-Tasmota/blob/development/CODE_OF_CONDUCT.md)
- [ ] Searched the problem in issues (https://github.com/arendst/Sonoff-Tasmota/issues)
- [ ] Searched the problem in the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting)
- [ ] Searched the problem in the forum (https://groups.google.com/d/forum/sonoffusers)
- [ ] Searched the problem in the chat (https://discord.gg/Ks2Kzd4)
- [ ] Development/Compiler/Upload tools used :
- [ ] Hardware used :
- [ ] If a pre-compiled release or development binary was used, which one? :
- [ ] You have tried latest release or development binaries? :
- [ ] Device used (i.e. Sonoff Basic) : _____
- [ ] Tasmota binary firmware version number used : ____ / (pre-compiled or self-compiled ?)
- [ ] Development IDE - Compiler / Upload tools used : ____ / ____
- [ ] Provide the output of command ``status 0`` :
```
STATUS 0 OUTPUT HERE
```
STATUS 0 OUTPUT HERE:
```
- [ ] Provide the output of console when you experience your issue if apply :
_(Please use_ ``weblog 4`` _for more debug information)_
```
CONSOLE OUTPUT HERE:
```
**(Please, remember to close the issue when the problem has been addressed)**

11
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,11 @@
## Description:
**Related issue (if applicable):** fixes #<Sonoff-Tasmota issue number goes here>
## Checklist:
- [ ] The pull request is done against the latest dev branch
- [ ] Only relevant files were touched (Also remember to update _changelog.ino_ file)
- [ ] Only one feature/fix was added per PR.
- [ ] The code change is tested and works.
- [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass**
- [ ] I accept the [CLA](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).

6
.github/stale.yml vendored
View File

@ -1,9 +1,9 @@
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 45
daysUntilStale: 25
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 15
daysUntilClose: 5
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
@ -37,4 +37,4 @@ closeComment: >
limitPerRun: 30
# Limit to only `issues` or `pulls`
only: issues
#only: issues

2
API.md
View File

@ -23,6 +23,8 @@ FUNC_JSON_APPEND | | | | x | | Extend tele
FUNC_WEB_APPEND | | | | x | | Extend webgui ajax info
FUNC_SAVE_BEFORE_RESTART | | | | x | | Just before a planned restart
FUNC_COMMAND | x | | x | x | | When a command is not recognized
FUNC_COMMAND_DRIVER | x | 6.4.1.21 | x | | | When command Driver\<id\> is executed
FUNC_COMMAND_SENSOR | x | 6.4.1.21 | | x | | When command Sensor\<id\> is executed
FUNC_MQTT_SUBSCRIBE | | 5.12.0k | x | | | At end of MQTT subscriptions
FUNC_MQTT_INIT | | 5.12.0k | x | | | Once at end of MQTT connection
FUNC_MQTT_DATA | x | 5.12.0k | x | | | Before decoding command

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at https://sidweb.nl/cms3/en/contact. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

113
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,113 @@
# Contributing to Sonoff-Tasmota
**Any contribution helps our team and makes Tasmota better for the entire community!**
Everybody is welcome and invited to contribute to Sonoff-Tasmota Project by:
* Testing newly released features and reporting issues.
* Providing Pull Requests (Features, Proof of Concepts, Language files or Fixes)
* Contributing missing documentation for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Contributing)
This document describes rules that are in effect for this repository, meant for handling issues by contributors in the issue tracker and PRs.
## Opening New Issues
**Issue tracker is NOT a general discussion forum!**
1. Opening an issue means that a problem exists in the code and should be addressed by the project contributors.
2. When opening an issue, it is required to fill out the presented template. The requested information is important! If the template is ignored or insufficient info about the issue is provided, the issue may be closed.
3. Questions of type "How do I..." or "Can you please help me with..." or "Can Tasmota do..." WILL NOT be handled here. Such questions should be directed at a discussion forum or to the Tasmota Support Chat. All issues of this type will be closed with a simple reference to this contributing policy.
4. Issues about topics already handled in the documentation will be closed in a similar manner.
5. Issues for unmerged PRs will be closed. If there is an issue with a PR, the explanation should be added to the PR itself.
6. Issues with accompanied investigation that shows the root of the problem should be given priority.
7. Duplicate issues will be closed.
## Triaging of Issues/PR's
1. Any contributor to the project can participate in the triaging process, if he/she chooses to do so.
2. An issue that needs to be closed, either due to not complying with this policy, or for other reasons, should be closed by a contributor.
3. Issues that are accepted should be marked with appropriate labels.
4. Issues that could impact functionality for many users should be considered severe.
5. Issues caused by the SDK or chip should not be marked severe, as there usually isnt much to be done. Common sense should be applied when deciding. Such issues should be documented in the Wiki, for reference by users.
6. Issues with feature requests should be discussed for viability/desirability.
7. Feature requests or changes that are meant to address a very specific/limited use case, especially if at the expense of increased code complexity, may be denied, or may be required to be redesigned, generalized, or simplified.
8. Feature requests that are not accompanied by a PR:
* could be closed immediately (denied).
* could be closed after some predetermined period of time (left as candidate for somebody to pick up).
9. In some cases, feedback may be requested from the issue reporter, either as additional info for clarification, additional testing, or other. If no feedback is provided, the issue may be closed by a contributor or after 30 days by the STALE bot.
## Pull requests
A Pull Request (PR) is the process where code modifications are managed in GitHub.
The process is straight-forward.
- Read [How to get faster PR reviews](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#best-practices-for-faster-reviews) by Kubernetes (but skip step 0)
- Fork the Sonoff-Tasmota Repository [git repository](https://github.com/arendst/Sonoff-Tasmota).
- Write/Change the code in your Fork for a new feature, bug fix, new sensor, optimization, etc.
- Ensure tests work.
- Create a Pull Request against the [**dev**](https://github.com/arendst/Sonoff-Tasmota/tree/dev) branch of Sonoff-Tasmota.
1. All pull requests must be done against the dev branch.
2. Only relevant files should be touched (Also beware if your editor has auto-formatting feature enabled).
3. Only one feature/fix should be added per PR.
4. If adding a new functionality (new hardware, new library support) not related to an existing component move it to it's own modules (.ino file).
5. PRs that don't compile (break Travis) or cause coding errors will not be merged. Please fix the issue. Same goes for PRs that are raised against older commit in dev - you might need to rebase and resolve conflicts.
6. All pull requests should undergo peer review by at least one contributor other than the creator, excepts for the owner.
7. All pull requests should consider updates to the documentation.
8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority.
9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged.
10. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA.
11. Pull requests that don't meet the above will be denied and closed.
--------------------------------------
## Contributor License Agreement (CLA)
```
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the GPL-3.0 license; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the GPL-3.0 license; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it) is maintained indefinitely
and may be redistributed consistent with this project or the open
source license(s) involved.
```
This Contributor License Agreement (CLA) was adopted on April 1st, 2019.
The text of this license is available under the [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). It is based on the Linux [Developer Certificate Of Origin](http://elinux.org/Developer_Certificate_Of_Origin), but is modified to explicitly use the GPL-3.0 license and not mention sign-off (due to GitHub.com keeps an historial, with your user name, of PRs' commits and all editions on PR's comments).
To accept the CLA it is required to put a x between [ ] on `[ ] I accept the CLA` in the PR template when submitting it. The [ ] is an opt-in box, so you have to manually accept it.
**Why a CLA ?**
_"A Contributor Licence Agreement (CLA) is strongly recommended when accepting third party contributions to an open development project, such as an open source software project. In order to redistribute contributions, it is necessary to ensure that the project has the necessary rights to do so. A Contributor Licence Agreement is a lightweight agreement, signed by the copyright holder, that grants the necessary rights for the contribution to be redistributed as part of the project."_ [OSS Watch](http://oss-watch.ac.uk/resources/cla)
A CLA is a legal document in which you state _you are entitled to contribute the code/documentation/translation to the project_ youre contributing to and that _you are willing to have it used in distributions and derivative works_. This means that should there be any kind of legal issue in the future as to the origins and ownership of any particular piece of code, then that project has the necessary forms on file from the contributor(s) saying they were permitted to make this contribution.
CLA is a safety because it also ensures that once you have provided a contribution, you cannot try to withdraw permission for its use at a later date. People can therefore use that software, confident that they will not be asked to stop using pieces of the code at a later date.
A __license__ grants "outbound" rights to the user of project.
A __CLA__ enables a contributor to grant "inbound" rights to a project.
<Other>
<A table should be maintained for relating maintainers and components. When triaging, this is essential to figure out if someone in particular should be consulted about specific changes.>
<A stable release cadence should be established, e.g.: every month.>

View File

@ -1,6 +1,6 @@
## Sonoff-Tasmota
Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web**, **timers**, 'Over The Air' (**OTA**) firmware updates and **sensors support**, allowing control under **Serial**, **HTTP**, **MQTT** and **KNX**, so as to be used on **Smart Home Systems**. Written for Arduino IDE and PlatformIO.
Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO.
[![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest)
[![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest)
@ -15,10 +15,10 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute!
See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information.
In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/
In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest), the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/
### Development
[![Dev Version](https://img.shields.io/badge/development%20version-6.4.1.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota)
[![Dev Version](https://img.shields.io/badge/development%20version-6.5.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://thehackbox.org/tasmota/)
[![Build Status](https://img.shields.io/travis/arendst/Sonoff-Tasmota.svg)](https://travis-ci.org/arendst/Sonoff-Tasmota)
@ -29,12 +29,12 @@ The development codebase is checked hourly for changes and if new commits have b
### Disclaimer
:warning: **DANGER OF ELECTROCUTION** :warning:
A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth to risk yourself, your family and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC.
A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth risk to yourself, your family, and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC.
We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site.
### Note
Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them..
Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them.
### Quick Install
Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki.
@ -64,7 +64,7 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade
See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for more information.<br />
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum.<br />
See [Chat](https://discord.gg/Ks2Kzd4) for more user experience.
Visit [Discord Chat](https://discord.gg/Ks2Kzd4) for discussions and troubleshooting.
The following devices are supported:
- [iTead Sonoff Basic (R2)](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html)
@ -113,6 +113,7 @@ You can contribute to Sonoff-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 for features and devices on our [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki)
[![donate](https://img.shields.io/badge/donate-PayPal-blue.svg)](https://paypal.me/tasmota)
@ -128,14 +129,15 @@ Libraries used with Sonoff-Tasmota are:
- [Adafruit SSD1306](https://github.com/adafruit/Adafruit_SSD1306)
- [Adafruit GFX](https://github.com/adafruit/Adafruit-GFX-Library)
- [ArduinoJson](https://arduinojson.org/)
- [arduino mqtt](https://github.com/256dpi/arduino-mqtt)
- [Bosch BME680](https://github.com/BoschSensortec/BME680_driver)
- [C2 Programmer](http://app.cear.ufpb.br/~lucas.hartmann/tag/efm8bb1/)
- [esp-epaper-29-ws-20171230-gemu](https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib)
- [esp-knx-ip](https://github.com/envy/esp-knx-ip)
- FrogmoreScd30
- [I2Cdevlib](https://github.com/jrowberg/i2cdevlib)
- [IRremoteEsp8266](https://github.com/markszabo/IRremoteESP8266)
- [JobaTsl2561](https://github.com/joba-1/Joba_Tsl2561)
- [LinkedList](https://github.com/ivanseidel/LinkedList)
- [Liquid Cristal](https://github.com/marcoschwartz/LiquidCrystal_I2C)
- [MultiChannelGasSensor](http://wiki.seeedstudio.com/Grove-Multichannel_Gas_Sensor/)
- [NeoPixelBus](https://github.com/Makuna/NeoPixelBus)
@ -169,7 +171,8 @@ People helping to keep the show on the road:
- Andre Thomas for providing [thehackbox](http://thehackbox.org/tasmota/) OTA support and daily development builds
- Joel Stein and digiblur for their Tuya research and driver
- Frogmore42 and Jason2866 for providing many issue answers
- Many more providing Tips, Pocs or PRs
- Blakadder for editing the wiki and providing template management
- Many more providing Tips, Wips, Pocs or PRs
### License

View File

@ -7,16 +7,14 @@ See [wiki migration path](https://github.com/arendst/Sonoff-Tasmota/wiki/Upgrade
4. Migrate to **Sonoff-Tasmota 6.x**
## Release notes
### Core version 2.3.0 vs 2.4.2
This release is based on ESP8266/Arduino library core 2.3.0 (again) as some people encountered wifi related issues on core 2.4.2. For others core 2.4.2 is working just fine. Both version are available from http://thehackbox.org/tasmota/release/
### Change in default initial configuration tool
Firmware binary **sonoff-classic.bin** supports **WifiManager, Wps and SmartConfig** for initial configuration. The default tool is **Wps**.
To save memory space all other binaries support **WifiManager only**.
See _changelog.ino how to enable them again.
- Define WIFI_CONFIG_TOOL now contains the default behaviour once a SSID has been configured.
- If no SSID is configured making a wifi connection impossible the new define WIFI_CONFIG_NO_SSID will be used.
- While define WIFI_CONFIG_NO_SSID is set to WIFI_WPSCONFIG in my_user_config.h the compiler will check for define USE_WPS and if not enabled WIFI_CONFIG_NO_SSID will default to WIFI_MANAGER using the webserver. If define USE_WEBSERVER is also not enabled WIFI_CONFIG_NO_SSID will default to WIFI_SMARTCONFIG. If define USE_SMARTCONFIG is also not enabled WIFI_CONFIG_NO_SSID will default to a new option WIFI_SERIAL allowing to enter wifi parameters to serial which is always possible.
## Supported Modules
The following hardware modules are supported.
@ -82,180 +80,204 @@ Module | Description
58 PS-16-DZ | PS-16-DZ Wifi dimmer for Incandescent Lights and Led
59 Teckin US | Teckin US and ZooZee SA102 Wifi Smart Switch with Energy Monitoring
60 Manzoku strip | Manzoku Wifi Smart Power Strip with four Relays
61 OBI Socket 2 | OBI 2 Wifi Smart Socket
62 YTF IR Bridge | YTF Infra Red Wifi Bridge
63 Digoo DG-SP202 | Digoo DG-SP202 Dual Wifi Smart Switch with Energy Monitoring
64 KA10 | Smanergy KA10 Wifi Smart Wall Switch with Energy Monitoring
65 Luminea ZX2820 | Luminea ZX2820 Wifi Smart Switch with Energy Monitoring
66 Mi Desk Lamp | Mi Desk Lamp with rotary switch and Wifi
67 SP10 | Tuya SP10 Wifi Smart Switch with Energy Monitoring
68 WAGA CHCZ02MB | WAGA life CHCZ02MB Wifi Smart Switch with Energy Monitoring
69 SYF05 | Sunyesmart SYF05 RGBWW Wifi Led Bulb
## Provided Binary Downloads
The following binary downloads have been compiled with ESP8266/Arduino library core version **2.4.2** patched with the Alexa fix.
The following binary downloads have been compiled with ESP8266/Arduino library core version **2.3.0**.
- **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**.
- **sonoff-classic.bin** = The Classic version allows **initial installation** using either WifiManager, Wps or SmartConfig.
- **sonoff.bin** = The Sonoff version without Wps and SmartConfig configuration but adds more sensors.
- **sonoff.bin** = The Sonoff version without Wps and SmartConfig configuration but adds more sensors. **RECOMMENDED RELEASE BINARY**
- **sonoff-basic.bin** = The Basic version without Wps and SmartConfig configuration and most sensors.
- **sonoff-classic.bin** = The Classic version allows initial installation using either WifiManager, Wps or SmartConfig.
- **sonoff-BG.bin** to **sonoff-TW.bin** = The Sonoff version without Wps and SmartConfig configuration in different languages.
- **sonoff-sensors.bin** = The Sensors version without Wps and SmartConfig configuration but adds even more useful sensors.
- **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration but adds display support.
- **sonoff-knx.bin** = The Knx version without Wps and SmartConfig configuration and some other features but adds KNX support.
- **sonoff-sensors.bin** = The Sensors version without Wps and SmartConfig configuration but adds even more useful sensors.
- **sonoff-display.bin** = The Display version without Wps and SmartConfig configuration and Energy Monitoring but adds display support.
- **sonoff-minimal.bin** = The Minimal version allows intermediate OTA uploads to support larger versions and does NOT change any persistent parameter. This version **should NOT be used for initial installation**.
Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/release/020402/
### Available Features and Sensors
| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | Remarks
|--------------------------------|---------|-------|---------|--------|------|---------|--------
| ESP/Arduino lib v2.3.0 | 346k | 429k | 482k | 504k | 522k | 535k |
| ESP/Arduino lib v2.4.2 | 366k | 446k | 496k | 522k | 538k | 551k | No wifi sleep
| | | | | | | |
| MY_LANGUAGE en-GB | x | x | x | x | x | x |
| MQTT_LIBRARY_TYPE PUBSUBCLIENT | x | x | x | x | x | x |
| USE_WPS | - | - | x | - | - | - | WPS
| USE_SMARTCONFIG | - | - | x | - | - | - | SmartConfig
| USE_ARDUINO_OTA | - | - | - | - | - | - |
| USE_DOMOTICZ | - | - | x | x | x | x |
| USE_HOME_ASSISTANT | - | - | - | x | x | x |
| USE_MQTT_TLS | - | - | - | - | - | - |
| USE_KNX | - | - | - | - | x | - |
| USE_WEBSERVER | x | x | x | x | x | x | WifiManager
| USE_EMULATION | - | x | x | x | - | x |
| USE_DISCOVERY | - | - | x | x | x | x |
| WEBSERVER_ADVERTISE | - | - | x | x | x | x |
| MQTT_HOST_DISCOVERY | - | - | x | x | x | x |
| USE_TIMERS | - | x | - | x | x | x |
| USE_TIMERS_WEB | - | x | - | x | x | x |
| USE_SUNRISE | - | x | - | x | x | x |
| USE_RULES | - | x | - | x | x | x |
| | | | | | |
| USE_ADC_VCC | x | x | x | x | x | - |
| USE_DS18B20 | - | - | - | - | - | - | Single sensor
| USE_DS18x20 | - | - | x | x | x | x | Multiple sensors
| USE_DS18x20_LEGACY | - | - | - | - | - | - | Multiple sensors
| | | | | | | |
| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors |
| USE_I2C | - | - | - | x | x | x |
| USE_SHT | - | - | - | x | x | x |
| USE_HTU | - | - | - | x | x | x |
| USE_BMP | - | - | - | x | x | x |
| USE_BME680 | - | - | - | - | - | x |
| USE_BH1750 | - | - | - | x | x | x |
| USE_VEML6070 | - | - | - | - | - | x |
| USE_ADS1115 | - | - | - | - | - | x |
| USE_ADS1115_I2CDEV | - | - | - | - | - | - |
| USE_INA219 | - | - | - | - | - | x |
| USE_SHT3X | - | - | - | x | x | x |
| USE_TSL2561 | - | - | - | - | - | x |
| USE_MGS | - | - | - | - | - | x |
| USE_SGP30 | - | - | - | x | x | x |
| USE_SI1145 | - | - | - | - | - | x |
| USE_LM75AD | - | - | - | x | x | x |
| USE_APDS9960 | - | - | - | - | - | - |
| USE_MCP230xx | - | - | - | - | - | - |
| USE_PCA9685 | - | - | - | - | - | - |
| USE_MPR121 | - | - | - | - | - | - |
| USE_CCS811 | - | - | - | - | - | - |
| USE_MPU6050 | - | - | - | - | - | - |
| USE_DS3231 | - | - | - | - | - | - |
| USE_MGC3130 | - | - | - | - | - | - |
| | | | | | | |
| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors |
| USE_SPI | - | - | - | - | - | - |
| USE_MHZ19 | - | - | - | x | x | x |
| USE_SENSEAIR | - | - | - | x | x | x |
| USE_PMS5003 | - | - | - | x | x | x |
| USE_NOVA_SDS | - | - | - | x | x | x |
| USE_PZEM004T | - | - | - | x | x | x |
| USE_PZEM_AC | - | - | - | x | x | x |
| USE_PZEM_DC | - | - | - | x | x | x |
| USE_MCP39F501 | - | x | - | x | x | x |
| USE_SERIAL_BRIDGE | - | - | - | x | x | x |
| USE_SDM120 | - | - | - | - | - | x |
| USE_SDM630 | - | - | - | - | - | x |
| USE_MP3_PLAYER | - | - | - | - | - | x |
| USE_TUYA_DIMMER | - | x | - | x | x | x |
| USE_ARMTRONIX_DIMMERS | - | x | - | x | x | x |
| USE_PS_16_DZ | - | x | - | x | x | x |
| USE_AZ7798 | - | - | - | - | - | - |
| USE_IR_REMOTE | - | - | - | x | x | x |
| USE_IR_HVAC | - | - | - | - | - | x |
| USE_IR_RECEIVE | - | - | - | x | x | x |
| USE_WS2812 | - | - | x | x | x | x |
| USE_WS2812_DMA | - | - | - | - | - | - |
| USE_ARILUX_RF | - | - | - | x | x | x |
| USE_SR04 | - | - | - | x | x | x |
| USE_TM1638 | - | - | - | - | - | x |
| USE_HX711 | - | - | - | x | x | x |
| USE_RF_FLASH | - | - | - | x | x | x |
| USE_TX20_WIND_SENSOR | - | - | - | x | x | x |
| USE_RC_SWITCH | - | - | - | x | x | x |
| USE_RF_SENSOR | - | - | - | - | - | x | AlectoV2 only
| USE_DISPLAY | - | - | - | - | - | - |
| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks
|-----------------------|---------|-------|---------|--------|------|---------|---------|--------
| MY_LANGUAGE en-GB | x | x | x | x | x | x | x |
| USE_WPS | - | - | x | - | - | - | - | WPS
| USE_SMARTCONFIG | - | - | x | - | - | - | - | SmartConfig
| USE_ARDUINO_OTA | - | - | - | - | - | - | - |
| USE_DOMOTICZ | - | - | x | x | x | x | - |
| USE_HOME_ASSISTANT | - | - | - | x | x | x | - |
| USE_MQTT_TLS | - | - | - | - | - | - | - |
| USE_KNX | - | - | - | - | x | - | - |
| USE_WEBSERVER | x | x | x | x | x | x | x | WifiManager
| USE_EMULATION | - | x | x | x | - | x | - |
| USE_DISCOVERY | - | - | x | x | x | x | x |
| WEBSERVER_ADVERTISE | - | - | x | x | x | x | x |
| MQTT_HOST_DISCOVERY | - | - | x | x | x | x | x |
| USE_TIMERS | - | x | - | x | x | x | x |
| USE_TIMERS_WEB | - | x | - | x | x | x | x |
| USE_SUNRISE | - | x | - | x | x | x | x |
| USE_RULES | - | x | - | x | x | x | x |
| USE_EXPRESSION | - | - | - | - | - | - | - |
| | | | | | | | |
| USE_ADC_VCC | x | x | x | x | x | - | x |
| USE_DS18B20 | - | - | - | - | - | - | - | Single sensor
| USE_DS18x20 | - | - | x | x | x | x | x | Multiple sensors
| USE_DS18x20_LEGACY | - | - | - | - | - | - | - | Multiple sensors
| | | | | | | | |
| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks
| USE_I2C | - | - | - | x | x | x | x |
| USE_SHT | - | - | - | x | x | x | x |
| USE_HTU | - | - | - | x | x | x | x |
| USE_BMP | - | - | - | x | x | x | x |
| USE_BME680 | - | - | - | - | - | x | - |
| USE_BH1750 | - | - | - | x | x | x | x |
| USE_VEML6070 | - | - | - | - | - | x | - |
| USE_ADS1115 | - | - | - | - | - | x | - |
| USE_ADS1115_I2CDEV | - | - | - | - | - | - | - |
| USE_INA219 | - | - | - | - | - | x | - |
| USE_SHT3X | - | - | - | x | x | x | x |
| USE_TSL2561 | - | - | - | - | - | x | - |
| USE_MGS | - | - | - | - | - | x | - |
| USE_SGP30 | - | - | - | x | x | x | x |
| USE_SI1145 | - | - | - | - | - | - | - |
| USE_LM75AD | - | - | - | x | x | x | x |
| USE_APDS9960 | - | - | - | - | - | - | - |
| USE_MCP230xx | - | - | - | - | - | - | - |
| USE_PCA9685 | - | - | - | - | - | - | - |
| USE_MPR121 | - | - | - | - | - | - | - |
| USE_CCS811 | - | - | - | - | - | - | - |
| USE_MPU6050 | - | - | - | - | - | - | - |
| USE_DS3231 | - | - | - | - | - | - | - |
| USE_MGC3130 | - | - | - | - | - | - | - |
| USE_MAX44009 | - | - | - | - | - | - | - |
| USE_SCD30 | - | - | - | - | - | x | - |
| | | | | | | | |
| Feature or Sensor | minimal | basic | classic | sonoff | knx | sensors | display | Remarks
| USE_SPI | - | - | - | - | - | - | x |
| USE_MHZ19 | - | - | - | x | x | x | x |
| USE_SENSEAIR | - | - | - | x | x | x | x |
| USE_PMS5003 | - | - | - | x | x | x | x |
| USE_NOVA_SDS | - | - | - | x | x | x | x |
| USE_ENERGY_SENSOR | - | x | x | x | x | x | - |
| USE_PZEM004T | - | - | - | x | x | x | - |
| USE_PZEM_AC | - | - | - | x | x | x | - |
| USE_PZEM_DC | - | - | - | x | x | x | - |
| USE_MCP39F501 | - | x | - | x | x | x | - |
| USE_SERIAL_BRIDGE | - | - | - | x | x | x | x |
| USE_SDM120 | - | - | - | - | - | x | - |
| USE_SDM630 | - | - | - | - | - | x | - |
| USE_MP3_PLAYER | - | - | - | - | - | x | - |
| USE_TUYA_DIMMER | - | x | - | x | x | x | x |
| USE_ARMTRONIX_DIMMERS | - | x | - | x | x | x | x |
| USE_PS_16_DZ | - | x | - | x | x | x | x |
| USE_AZ7798 | - | - | - | - | - | - | - |
| USE_PN532_HSU | - | - | - | - | - | x | - |
| USE_IR_REMOTE | - | - | - | x | x | x | x |
| USE_IR_HVAC | - | - | - | - | - | x | - |
| USE_IR_RECEIVE | - | - | - | x | x | x | x |
| USE_WS2812 | - | - | x | x | x | x | x |
| USE_WS2812_DMA | - | - | - | - | - | - | - |
| USE_ARILUX_RF | - | - | - | x | x | x | - |
| USE_SR04 | - | - | - | x | x | x | x |
| USE_TM1638 | - | - | - | - | - | x | - |
| USE_HX711 | - | - | - | x | x | x | x |
| USE_RF_FLASH | - | - | - | x | x | x | - |
| USE_TX20_WIND_SENSOR | - | - | - | x | x | x | x |
| USE_RC_SWITCH | - | - | - | x | x | x | x |
| USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only
| USE_SM16716 | - | x | x | x | x | x | x |
| USE_HRE | - | - | - | - | - | x | - |
| USE_DISPLAY | - | - | - | - | - | - | x |
| USE_DISPLAY_LCD | - | - | - | - | - | - | x |
| USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x |
| USE_DISPLAY_MATRIX | - | - | - | - | - | - | x |
| USE_DISPLAY_ILI9341 | - | - | - | - | - | - | x |
| USE_DISPLAY_EPAPER_29 | - | - | - | - | - | - | x | Disabled for core 2.3.0
## Changelog
Version 6.4.1 20181225
* Change RAM usage BMP/BME I2C sensors
* Change FallbackTopic from cmnd/\<mqttclient\>/ to cmnd/\<mqttclient\>_fb/ to discriminate from Topic (#1528)
* Change FallbackTopic detection (#4706)
* Change Hass discovery to short MQTT messages as used by Hass 0.81 and up (#4711)
* Change MQTT GUI password handling (#4723)
* Fix possible dtostrf buffer overflows by increasing buffers
* Fix wifi strongest signal detection (#4704)
* Fix Alexa "this value is outside the range of the device". Needs power cycle and Alexa deletion/discovery cycle. (#3159, #4712)
* Add Slovak language file (#4663)
* Add support for AZ-Instrument 7798 CO2 meter/datalogger (#4672)
* Add define WIFI_SOFT_AP_CHANNEL in my_user_config.h to set Soft Access Point Channel number between 1 and 13 as used by Wifi Manager web GUI (#4673)
* Add define USE_MQTT_TLS_CA_CERT for checking MQTT TLS against root ca using Let's Encrypt cert from sonoff_letsencrypt.h - not supported with core 2.3.0 (#4703)
Version 6.4.0 20181217
* Change GUI Configure Module by using AJAX for data fetch to cut page size (and memory use) by 40%.
In case of web page errors clear your browser cache or do Page Reload (F5 or Ctrl+R)
* Change enforcing flashmode dout but it is still mandatory
* Change bootcount update (being first) flash write to 10 seconds after restart
* Change display and epaper drivers
* Change command WebSend Host header field from IP address to hostname (#4331)
* Change log buffer size from 512 to 520 to accommodate http sensor data (#4354)
* Change default WIFI_CONFIG_TOOL from WIFI_WAIT to WIFI_RETRY in my_user_config.h (#4400)
* Change webgui refresh time delay for Save Settings and local OTA Upload (#4423)
* Change SR-04 driver to use NewPing library (#4488)
* Change MCP230xx driver to support interrupt retention over teleperiod (#4547)
* Change support for MPU6050 using DMP (#4581)
* Fix unintended function overload of WifiState
* Fix wifi connection errors using wifi disconnect and ESP.reset instead of ESP.restart
* Fix Sonoff Pow R2 and Sonoff S31 Serial interface hang caused by Sonoff Basic R2 driver delay implementation (and possibly core bug)
* Fix MQTT connection error after restart
* Fix wifi re-scan connection baseline
* Fix possible strncat buffer overflows
* Fix intermittent Pzem sensor energy overflow calculation error
* Fix shelly2 ghost switching caused by lack of pull-up inputs (#4255)
* Fix hardware serial pin configuration. To keep using hardware serial swap current Rx/Tx pin configuration only (#4280)
* Fix MqttRetry values above 255 seconds (#4424)
* Fix WifiManager functionality on initial installation (#4433)
* Fix ArduinoOTA for Core 2.5.0 (#4620)
* Add minutes to commands Timezone to allow all possible world timezones
* Add more strict checks for GPIO selections
* Add code image and optional commit number to version
* Add dynamic delay to main loop providing time for wifi background tasks
* Add additional start-up delay during initial wifi connection
* Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver
* Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver
* Add user definition of defines WIFI_RSSI_THRESHOLD (default 10) and WIFI_RESCAN_MINUTES (default 44)
* Add command SetOption58 0/1 to enable IR raw data info in JSON message (#2116)
* Add command IRSend \<frequency\>|0,\<rawdata1\>,\<rawdata2\>,.. to allow raw data transmission (#2116)
* Add command SetOption56 0/1 to enable wifi network scan and select highest RSSI (#3173)
* Add command SetOption57 0/1 to enable wifi network re-scan every 44 minutes with a rssi threshold of 10 to select highest RSSI (#3173)
* Add support for SDM220 (#3610)
* Add default sleep 1 to sonoff-basic to lower energy consumption (#4217)
* Add wifi status to Tuya (#4221)
* Add delays to reduce CPU usage at boot time (#4233)
* Add command SetOption24 0/1 to select pressure unit as hPa or mmHg (#4241)
* Add optional hardware serial when GPIO13(Rx) and GPIO15(Tx) are selected removing hardware serial from GPIO01(Tx) and GPIO03(Rx) (#4288)
* Add support for Gosund SP1 v2.3 Power Socket with Energy Monitoring (#4297)
* Add support for Armtronix dimmers. See wiki for info (#4321)
* Add to command WebSend option to send a direct path when command starts with a slash (#4329)
* Add support for LG HVac and IrRemote (#4377)
* Add initial support for Hass sensor discovery (#4380)
* Add support for Fujitsu HVac and IrRemote (#4387)
* Add support for I2C MGC3130 Electric Field Effect sensor by Christian Baars (#3774, #4404)
* Add command CalcRes to set number of decimals (0 - 7) used in commands ADD, SUB, MULT and SCALE (#4420)
* Add CPU average load to state message (#4431)
* Add command SetOption59 0/1 to change state topic from tele/STATE to stat/RESULT (#4450)
* Add support for SM Smart Wifi Dimmer PS-16-DZ (#4465)
* Add support for Teckin US Power Socket with Energy Monitoring (#4481)
* Add command SetOption60 0/1 to select dynamic sleep (0) or sleep (1) (#4497)
* Add support for iFan02 Fanspeed in Domoticz using a selector (#4517)
* Add support for GPIO02 for newer Sonoff Basic (#4518)
* Add Announce Switches to MQTT Discovery (#4531)
* Add support for Manzoku Power Strip (#4590)
Version 6.5.0 20190319
* Remove commands SetOption14 and SetOption63 as it has been superseded by command Interlock
* Remove command SetOption35 0-255 for mDNS start-up delay (#4793)
* Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474)
* Change webserver content handling from single String to small Chunks increasing RAM
* Change code use of boolean to bool and byte to uint8_t
* Change code uint8_t flags to bool flags
* Change sonoff_template.h layout regarding optional module flags like ADC0
* Change sonoff_template.h module lay-out by removing non-configurable GPIOs
* Change button driver making it modular
* Change switch driver making it modular and introduce input filter (#4665, #4724)
* Change switch input detection by optimizing switch debounce (#4724)
* Change web authentication (#4865)
* Change image name BE_MINIMAL to FIRMWARE_MINIMAL and USE_xyz to FIRMWARE_xyz (#5106)
* Change GUI weblog from XML to plain text solving possible empty screens (#5154)
* Fix most compiler warnings
* Fix Display exception 28 when JSON value is NULL received
* Fix epaper driver (#4785)
* Fix HAss Sensor Discovery Software Watchdog restart (#4831, #4988)
* Fix allowable MAX_RULE_VARS to 16 (#4933)
* Fix mDNS addService (#4938, #4951)
* Fix HAss discovery of MHZ19(B) sensors (#4992)
* Fix some exceptions and watchdogs due to lack of stack space (#5215)
* Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242)
* Fix command WebSend intermittent results (#5273, #5304)
* Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417)
* Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373)
* Fix DS18S20 temperature calculation (#5375)
* Fix float calculations in range from 0 to -1 (#5386)
* Fix exception on GUI Configure Logging and Configure Other (#5424)
* Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors
* Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131)
* Add command SSerialSend5 \<hexdata\> to SerialBridge
* Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#4910, #5014)
* Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371)
* Add command WifiConfig 7 to allow reset of device in AP mode without admin password (#5297)
* Add command SetOption36 to control boot loop default restoration (#4645, #5063)
* Add command SetOption37 for RGBCW color mapping (#5326)
* Add command SetOption55 0/1 and define MDNS_ENABLE to disable/enable mDNS (#4793, #4923)
* Add command SetOption62 0/1 to disable retain on Button or Switch hold messages (#5299)
* Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring
* Add support for commands in sensor drivers
* Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764)
* Add support for Near Field Communication (NFC) controller PN532 using Serial (#4791, #5162)
* Add support for OBI Power Socket 2 (#4829)
* Add support for YTF IR Bridge (#4855)
* Add support for Mi LED Desk Lamp with rotary switch (#4887)
* Add support for Digoo DG-SP202 Smart Socket with Energy monitoring (#4891)
* Add support for MAX44009 Ambient Light sensor (#4907)
* Add support for inverted buttons and inverted buttons without pullup (#4914)
* Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921)
* Add support for multiple ADS1115 I2C devices (#5083)
* Add support for online template change using command Template or GUI Configure Other (#5177)
* Add support for Korean language translations (#5344)
* Add support for sensor SCD30 (#5434)
* Add parameter CFG_HOLDER to status 1 message (#5206)
* Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name
* Add Resolution property to Status 3 report providing previous SetOption second value property
* Add property MqttCount to status 6 message representing number of Mqtt re-connections
* Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections
* Add property Downtime to state and status 11 message representing the duration of wifi connection loss
* Add variable %timestamp% to rules (#4749)
* Add rule support for "==", "!=" ">=" and "<=" (#5122)
* Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210)
* Add Power status functionality to LED2 when configured leaving LED1 for Link status indication
* Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff Pow and many Tuya based devices
* Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2
* Add online template configuration using both commands and Configure Template menu option in GUI
* Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947)
* Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738)
* Add button control when no relay configured (#4682)
* Add startup delay of 4 seconds to button control (#4829)
* Add core version conditional compile options to provided PWM files (#4917)
* Add resiliency to saved Settings (#5065)
* Add MHZ19 Temperature as Domoticz Temperature selection (#5128)
* Add HAss status sensor (#5139)
* Add status message to former declined group commands (#5145)
* Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431)

22
SUPPORT.md Normal file
View File

@ -0,0 +1,22 @@
# Sonoff-Tasmota Support
If you're looking for support on **Sonoff-Tasmota** there are some options available:
### Documentation:
* [Wiki Pages](https://github.com/arendst/Sonoff-Tasmota/wiki): For information on how to Flash Tasmota, configure and use it.
* [Troubleshooting Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Troubleshooting): For information on common problems and solutions.
* [Commands Information](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands): For information on all the commands supported by Tasmota.
### 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.
* [Search in Issues](https://github.com/arendst/Sonoff-Tasmota/issues): You might find an answer to your question by searching current or closed issues.
### Developers' Community:
* [Bug Report](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Bug_report.md): For reporting Bugs of Tasmota Software.
* [Feature Request](https://github.com/arendst/Sonoff-Tasmota/issues/new?template=Feature_request.md): For requesting features/functions to Tasmota Software.
* [Troubleshooting](https://github.com/arendst/Sonoff-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/Sonoff-Tasmota/issues/new/choose): As a last resort, you can open 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.

View File

@ -3,7 +3,7 @@ Sonoff-Tasmota uses Device or Module information to control peripherals connecte
Starting with version 6.4.1.16 Sonoff-Tasmota Modules can be extended by users online using a template. To provide easy processing by Sonoff-Tasmota a user template is written as JSON text and could look like this:
{"NAME":"UserModule1","GPIO":[17,243,29,244,7,201,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}
{"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}
The four properties with UPPERCASE property names have the following functionality:
@ -74,7 +74,7 @@ Template | 0 | Copy active module template to user template
Template | 1 .. 69 | Copy hard-coded module template to user template
The following command will store a complete template based on the Generic module
``Template {"NAME":"UserModule1","GPIO":[17,243,29,244,7,201,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}``
``Template {"NAME":"UserModule1","GPIO":[17,148,29,149,7,255,255,255,138,255,139,255,255],"FLAG":0,"BASE":18}``
The following command will update the name of a stored template
``Template {"NAME":"UserModule2"}``

File diff suppressed because it is too large Load Diff

View File

@ -1,156 +0,0 @@
# ESP8266 platform
# ------------------------------
# For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
name=ESP8266 Boards (2.5.0-beta2)
version=2.5.0-beta2
runtime.tools.signing={runtime.platform.path}/tools/signing.py
compiler.warning_flags=-w
compiler.warning_flags.none=-w
compiler.warning_flags.default=
compiler.warning_flags.more=-Wall
compiler.warning_flags.all=-Wall -Wextra
build.lwip_lib=-llwip_gcc
build.lwip_include=lwip/include
build.lwip_flags=-DLWIP_OPEN_SRC
build.vtable_flags=-DVTABLES_IN_FLASH
#build.exception_flags=-fexceptions
build.exception_flags=-fno-exceptions
#build.stdcpp_lib=-lstdc++
build.stdcpp_lib=-lstdc++-nox
#build.float=-u _printf_float -u _scanf_float
build.float=
build.led=
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
compiler.c.cmd=xtensa-lx106-elf-gcc
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 {build.exception_flags} -ffunction-sections -fdata-sections {build.exception_flags}
compiler.S.cmd=xtensa-lx106-elf-gcc
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
compiler.cpp.cmd=xtensa-lx106-elf-g++
compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags}
compiler.as.cmd=xtensa-lx106-elf-as
compiler.ar.cmd=xtensa-lx106-elf-ar
compiler.ar.flags=cru
compiler.elf2hex.cmd=esptool
compiler.elf2hex.flags=
compiler.size.cmd=xtensa-lx106-elf-size
compiler.esptool.cmd=esptool
compiler.esptool.cmd.windows=esptool.exe
# This can be overriden in boards.txt
build.extra_flags=-DESP8266
# These can be overridden in platform.local.txt
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
compiler.S.extra_flags=
compiler.cpp.extra_flags=
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=
## generate file with git version number
## needs bash, git, and echo
recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
## windows-compatible version without git
recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows
## Build the app.ld linker file
recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile S files
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
## Create eeprom
recipe.objcopy.eep.pattern=
## Create hex
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
# No signing on Windows
recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern.windows=
## Save hex
recipe.output.tmp_file={build.project_name}.bin
recipe.output.save_file={build.project_name}.{build.variant}.bin
## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).*
recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
# ------------------------------
tools.esptool.cmd=esptool
tools.esptool.cmd.windows=esptool.exe
tools.esptool.path={runtime.tools.esptool.path}
tools.esptool.network_cmd=python
tools.esptool.network_cmd.windows=python.exe
tools.esptool.upload.protocol=esp
tools.esptool.upload.params.verbose=-vv
tools.esptool.upload.params.quiet=
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
tools.mkspiffs.cmd=mkspiffs
tools.mkspiffs.cmd.windows=mkspiffs.exe
tools.mkspiffs.path={runtime.tools.mkspiffs.path}
tools.espupload.cmd=python
tools.espupload.cmd.windows=python.exe
tools.espupload.path={runtime.platform.path}/tools
tools.espupload.upload.protocol=espupload
tools.espupload.upload.params.verbose=
tools.espupload.upload.params.quiet=
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"

View File

@ -1330,8 +1330,8 @@ cw01.upload.resetmethod=nodemcu
cw01.menu.CrystalFreq.26=26 MHz
cw01.menu.CrystalFreq.40=40 MHz
cw01.menu.CrystalFreq.40.build.extra_flags=-DF_CRYSTAL=40000000 -DESP8266
cw01.build.flash_mode=qio
cw01.build.flash_flags=-DFLASHMODE_QIO
cw01.build.flash_mode=dio
cw01.build.flash_flags=-DFLASHMODE_DIO
cw01.build.flash_freq=40
cw01.menu.eesz.4M=4M (no SPIFFS)
cw01.menu.eesz.4M.build.flash_size=4M
@ -6119,4 +6119,3 @@ espectro.menu.baud.512000.windows=512000
espectro.menu.baud.512000.upload.speed=512000
espectro.menu.baud.921600=921600
espectro.menu.baud.921600.upload.speed=921600

View File

@ -1,154 +1,155 @@
# ESP8266 platform
# ------------------------------
# For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
name=ESP8266 Boards (2.5.0-beta3)
version=2.5.0-beta3
runtime.tools.signing={runtime.platform.path}/tools/signing.py
compiler.warning_flags=-w
compiler.warning_flags.none=-w
compiler.warning_flags.default=
compiler.warning_flags.more=-Wall
compiler.warning_flags.all=-Wall -Wextra
build.lwip_lib=-llwip_gcc
build.lwip_include=lwip/include
build.lwip_flags=-DLWIP_OPEN_SRC
build.vtable_flags=-DVTABLES_IN_FLASH
build.exception_flags=-fno-exceptions
build.stdcpp_lib=-lstdc++
#build.float=-u _printf_float -u _scanf_float
build.float=
build.led=
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
compiler.c.cmd=xtensa-lx106-elf-gcc
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags}
compiler.S.cmd=xtensa-lx106-elf-gcc
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
compiler.cpp.cmd=xtensa-lx106-elf-g++
compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags}
compiler.as.cmd=xtensa-lx106-elf-as
compiler.ar.cmd=xtensa-lx106-elf-ar
compiler.ar.flags=cru
compiler.elf2hex.cmd=esptool
compiler.elf2hex.flags=
compiler.size.cmd=xtensa-lx106-elf-size
compiler.esptool.cmd=esptool
compiler.esptool.cmd.windows=esptool.exe
# This can be overriden in boards.txt
build.extra_flags=-DESP8266
# These can be overridden in platform.local.txt
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
compiler.S.extra_flags=
compiler.cpp.extra_flags=
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=
## generate file with git version number
## needs bash, git, and echo
recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
## windows-compatible version without git
recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows
## Build the app.ld linker file
recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile S files
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
## Create eeprom
recipe.objcopy.eep.pattern=
## Create hex
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
# No signing on Windows
recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern.windows=
## Save hex
recipe.output.tmp_file={build.project_name}.bin
recipe.output.save_file={build.project_name}.{build.variant}.bin
## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).*
recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
# ------------------------------
tools.esptool.cmd=esptool
tools.esptool.cmd.windows=esptool.exe
tools.esptool.path={runtime.tools.esptool.path}
tools.esptool.network_cmd=python
tools.esptool.network_cmd.windows=python.exe
tools.esptool.upload.protocol=esp
tools.esptool.upload.params.verbose=-vv
tools.esptool.upload.params.quiet=
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
tools.mkspiffs.cmd=mkspiffs
tools.mkspiffs.cmd.windows=mkspiffs.exe
tools.mkspiffs.path={runtime.tools.mkspiffs.path}
tools.espupload.cmd=python
tools.espupload.cmd.windows=python.exe
tools.espupload.path={runtime.platform.path}/tools
tools.espupload.upload.protocol=espupload
tools.espupload.upload.params.verbose=
tools.espupload.upload.params.quiet=
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"
# ESP8266 platform
# ------------------------------
# For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
name=ESP8266 Boards (2.5.0)
version=2.5.0
runtime.tools.xtensa-lx106-elf-gcc.path={runtime.platform.path}/tools/xtensa-lx106-elf
runtime.tools.esptool.path={runtime.platform.path}/tools/esptool
runtime.tools.signing={runtime.platform.path}/tools/signing.py
compiler.warning_flags=-w
compiler.warning_flags.none=-w
compiler.warning_flags.default=
compiler.warning_flags.more=-Wall
compiler.warning_flags.all=-Wall -Wextra
build.lwip_lib=-llwip_gcc
build.lwip_include=lwip/include
build.lwip_flags=-DLWIP_OPEN_SRC
build.vtable_flags=-DVTABLES_IN_FLASH
build.exception_flags=-fno-exceptions
build.stdcpp_lib=-lstdc++
#build.float=-u _printf_float -u _scanf_float
build.float=
build.led=
compiler.path={runtime.tools.xtensa-lx106-elf-gcc.path}/bin/
compiler.sdk.path={runtime.platform.path}/tools/sdk
compiler.libc.path={runtime.platform.path}/tools/sdk/libc/xtensa-lx106-elf
compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ "-I{compiler.sdk.path}/include" "-I{compiler.sdk.path}/{build.lwip_include}" "-I{compiler.libc.path}/include" "-I{build.path}/core"
compiler.c.cmd=xtensa-lx106-elf-gcc
compiler.c.flags=-c {compiler.warning_flags} -Os -g -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -std=gnu99 -ffunction-sections -fdata-sections {build.exception_flags}
compiler.S.cmd=xtensa-lx106-elf-gcc
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls
compiler.c.elf.flags=-g {compiler.warning_flags} -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.libc.path}/lib" "-T{build.flash_ld}" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -laxtls -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
compiler.cpp.cmd=xtensa-lx106-elf-g++
compiler.cpp.flags=-c {compiler.warning_flags} -Os -g -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 -std=c++11 -MMD -ffunction-sections -fdata-sections {build.exception_flags}
compiler.as.cmd=xtensa-lx106-elf-as
compiler.ar.cmd=xtensa-lx106-elf-ar
compiler.ar.flags=cru
compiler.elf2hex.cmd=esptool
compiler.elf2hex.flags=
compiler.size.cmd=xtensa-lx106-elf-size
compiler.esptool.cmd=esptool
compiler.esptool.cmd.windows=esptool.exe
# This can be overriden in boards.txt
build.extra_flags=-DESP8266
# These can be overridden in platform.local.txt
compiler.c.extra_flags=
compiler.c.elf.extra_flags=
compiler.S.extra_flags=
compiler.cpp.extra_flags=
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=
## generate file with git version number
## needs bash, git, and echo
recipe.hooks.core.prebuild.1.pattern=python "{runtime.tools.signing}" --mode header --publickey "{build.source.path}/public.key" --out "{build.path}/core/Updater_Signing.h"
recipe.hooks.core.prebuild.2.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_VER 0x`git --git-dir {runtime.platform.path}/.git rev-parse --short=8 HEAD 2>/dev/null || echo ffffffff` >{build.path}/core/core_version.h"
recipe.hooks.core.prebuild.3.pattern=bash -c "mkdir -p {build.path}/core && echo \#define ARDUINO_ESP8266_GIT_DESC `cd "{runtime.platform.path}"; git describe --tags 2>/dev/null || echo unix-{version}` >>{build.path}/core/core_version.h"
## windows-compatible version without git
recipe.hooks.core.prebuild.1.pattern.windows=cmd.exe /c rem cannot sign on windows
recipe.hooks.core.prebuild.2.pattern.windows=cmd.exe /c mkdir {build.path}\core & (echo #define ARDUINO_ESP8266_GIT_VER 0x00000000 & echo #define ARDUINO_ESP8266_GIT_DESC win-{version} ) > {build.path}\core\core_version.h
recipe.hooks.core.prebuild.3.pattern.windows=cmd.exe /c if exist {build.source.path}\public.key echo #error Cannot automatically build signed binaries on Windows > {build.path}\core\Updater_Signing.h
## Build the app.ld linker file
recipe.hooks.linking.prelink.1.pattern="{compiler.path}{compiler.c.cmd}" -CC -E -P {build.vtable_flags} "{runtime.platform.path}/tools/sdk/ld/eagle.app.v6.common.ld.h" -o "{build.path}/local.eagle.app.v6.common.ld"
## Compile c files
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile c++ files
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Compile S files
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} {build.lwip_flags} {build.debug_port} {build.debug_level} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" {build.led} {build.flash_flags} {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
## Combine gc-sections, archives, and objects
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {build.exception_flags} -Wl,-Map "-Wl,{build.path}/{build.project_name}.map" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group "-L{build.path}"
## Create eeprom
recipe.objcopy.eep.pattern=
## Create hex
#recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
recipe.objcopy.hex.1.pattern="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern=python "{runtime.tools.signing}" --mode sign --privatekey "{build.source.path}/private.key" --bin "{build.path}/{build.project_name}.bin" --out "{build.path}/{build.project_name}.bin.signed"
# No signing on Windows
recipe.objcopy.hex.1.pattern.windows="{runtime.tools.esptool.path}/{compiler.esptool.cmd}" -eo "{runtime.platform.path}/bootloaders/eboot/eboot.elf" -bo "{build.path}/{build.project_name}.bin" -bm {build.flash_mode} -bf {build.flash_freq} -bz {build.flash_size} -bs .text -bp 4096 -ec -eo "{build.path}/{build.project_name}.elf" -bs .irom0.text -bs .text -bs .data -bs .rodata -bc -ec
recipe.objcopy.hex.2.pattern.windows=
## Save hex
recipe.output.tmp_file={build.project_name}.bin
recipe.output.save_file={build.project_name}.{build.variant}.bin
## Compute size
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
recipe.size.regex=^(?:\.irom0\.text|\.text|\.data|\.rodata|)\s+([0-9]+).*
recipe.size.regex.data=^(?:\.data|\.rodata|\.bss)\s+([0-9]+).*
#recipe.size.regex.eeprom=^(?:\.eeprom)\s+([0-9]+).*
# ------------------------------
tools.esptool.cmd=esptool
tools.esptool.cmd.windows=esptool.exe
tools.esptool.path={runtime.tools.esptool.path}
tools.esptool.network_cmd=python
tools.esptool.network_cmd.windows=python.exe
tools.esptool.upload.protocol=esp
tools.esptool.upload.params.verbose=-vv
tools.esptool.upload.params.quiet=
tools.esptool.upload.pattern="{path}/{cmd}" {upload.verbose} -cd {upload.resetmethod} -cb {upload.speed} -cp "{serial.port}" {upload.erase_cmd} -ca 0x00000 -cf "{build.path}/{build.project_name}.bin"
tools.esptool.upload.network_pattern="{network_cmd}" "{runtime.platform.path}/tools/espota.py" -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
tools.mkspiffs.cmd=mkspiffs
tools.mkspiffs.cmd.windows=mkspiffs.exe
tools.mkspiffs.path={runtime.tools.mkspiffs.path}
tools.espupload.cmd=python
tools.espupload.cmd.windows=python.exe
tools.espupload.path={runtime.platform.path}/tools
tools.espupload.upload.protocol=espupload
tools.espupload.upload.params.verbose=
tools.espupload.upload.params.quiet=
tools.espupload.upload.pattern="{cmd}" "{path}/espupload.py" -f "{build.path}/{build.project_name}.bin"

View File

@ -0,0 +1,653 @@
/*
# Copyright (c) 2019 Frogmore42
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <Wire.h>
#include <math.h>
#include <stdio.h>
#include <twi.h>
#include <FrogmoreScd30.h>
#define COMMAND_SCD30_CONTINUOUS_MEASUREMENT 0x0010
#define COMMAND_SCD30_MEASUREMENT_INTERVAL 0x4600
#define COMMAND_SCD30_GET_DATA_READY 0x0202
#define COMMAND_SCD30_READ_MEASUREMENT 0x0300
#define COMMAND_SCD30_CALIBRATION_TYPE 0x5306
#define COMMAND_SCD30_FORCED_RECALIBRATION_FACTOR 0x5204
#define COMMAND_SCD30_TEMPERATURE_OFFSET 0x5403
#define COMMAND_SCD30_ALTITUDE_COMPENSATION 0x5102
#define COMMAND_SCD30_SOFT_RESET 0xD304
#define COMMAND_SCD30_GET_FW_VERSION 0xD100
#define COMMAND_SCD30_STOP_MEASUREMENT 0x0104
#define SCD30_DATA_REGISTER_BYTES 2
#define SCD30_DATA_REGISTER_WITH_CRC 3
#define SCD30_MEAS_BYTES 18
#ifdef SCD30_DEBUG
enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
char scd30log_data[180];
#endif
void FrogmoreScd30::begin(TwoWire *pWire, uint8_t i2cAddress)
{
this->i2cAddress = i2cAddress;
if (pWire == NULL)
{
this->pWire = &Wire;
}
else
{
this->pWire = pWire;
}
co2NewDataLocation = -1; // indicates there is no data, so the 1st data point needs to fill up the median filter
this->pWire->setClockStretchLimit(200000);
this->ambientPressure = 0;
}
void FrogmoreScd30::begin(uint8_t i2cAddress)
{
begin(NULL, i2cAddress);
}
void FrogmoreScd30::begin(TwoWire *pWire)
{
begin(pWire, SCD30_ADDRESS);
}
void FrogmoreScd30::begin(void)
{
begin(NULL, SCD30_ADDRESS);
}
/*---------------------------------------------------------------------------
Function : opt_med5() In : pointer to array of 5 values
Out : a uint16_t which is the middle value of the sorted array
Job : optimized search of the median of 5 values
Notice : found on sci.image.processing cannot go faster unless assumptions are made on the nature of the input signal.
---------------------------------------------------------------------------*/
#define PIX_SORT(a,b) { if ((a)>(b)) PIX_SWAP((a),(b)); }
#define PIX_SWAP(a,b) { uint16_t temp=(a);(a)=(b);(b)=temp; }
uint16_t opt_med5(uint16_t * p)
{
PIX_SORT(p[0], p[1]);
PIX_SORT(p[3], p[4]);
PIX_SORT(p[0], p[3]);
PIX_SORT(p[1], p[4]);
PIX_SORT(p[1], p[2]);
PIX_SORT(p[2], p[3]);
PIX_SORT(p[1], p[2]);
return(p[2]);
}
// twi_status() attempts to read out any data left that is holding SDA low, so a new transaction can take place
// something like (http://www.forward.com.au/pfod/ArduinoProgramming/I2C_ClearBus/index.html)
int FrogmoreScd30::clearI2CBus(void)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "clearI2CBus");
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
return (twi_status());
}
#ifdef SCD30_DEBUG
void FrogmoreScd30::AddLog(uint8_t loglevel)
{
if (loglevel <= LOG_LEVEL_INFO)
{
Serial.printf("%s\r\n", scd30log_data);
}
}
#endif
uint8_t FrogmoreScd30::computeCRC8(uint8_t data[], uint8_t len)
// Computes the CRC that the SCD30 uses
{
uint8_t crc = 0xFF; //Init with 0xFF
for (uint8_t x = 0 ; x < len ; x++)
{
crc ^= data[x]; // XOR-in the next input byte
for (uint8_t i = 0 ; i < 8 ; i++)
{
if ((crc & 0x80) != 0)
crc = (uint8_t)((crc << 1) ^ 0x31);
else
crc <<= 1;
}
}
return crc; //No output reflection
}
// Sends stream of bytes to device
int FrogmoreScd30::sendBytes(void *pInput, uint8_t len)
{
uint8_t *pBytes = (uint8_t *) pInput;
int result;
uint8_t errorBytes = 0; // number of bytes that had an error in transmission
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendBytes: data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", pBytes[0], pBytes[1], pBytes[2], pBytes[3], pBytes[4], pBytes[5], pBytes[6], pBytes[7], pBytes[8]);
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
pWire->beginTransmission(this->i2cAddress);
errorBytes = len - (pWire->write(pBytes, len));
result = pWire->endTransmission();
if (errorBytes || result)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendBytes: errorBytes: %d | Wire.end: %d", errorBytes, result);
AddLog(LOG_LEVEL_INFO);
#endif
}
result <<= 8; // leave room for error bytes number
result |= errorBytes; // low byte has number of bytes that were not written correctly
return (result);
}
// Gets a number of bytes from device
int FrogmoreScd30::getBytes(void *pOutput, uint8_t len)
{
uint8_t *pBytes = (uint8_t *) pOutput;
uint8_t result;
result = pWire->requestFrom(this->i2cAddress, len);
if (len != result)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30GetBytes: wire request expected %d got: %d", len, result);
AddLog(LOG_LEVEL_INFO);
#endif
return (ERROR_SCD30_NOT_ENOUGH_BYTES_ERROR);
}
if (pWire->available())
{
for (int x = 0; x < len; x++)
{
pBytes[x] = pWire->read();
}
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30GetBytes: data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", pBytes[0], pBytes[1], pBytes[2], pBytes[3], pBytes[4], pBytes[5], pBytes[6], pBytes[7], pBytes[8]);
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
return (ERROR_SCD30_NO_ERROR);
}
return (ERROR_SCD30_UNKNOWN_ERROR);
}
//Sends just a command, no arguments, no CRC
int FrogmoreScd30::sendCommand(uint16_t command)
{
uint8_t data[2];
data[0] = command >> 8;
data[1] = command & 0xFF;
int error = sendBytes(data, sizeof(data));
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendCommand: Scd30SendBytes failed: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
}
return (error);
}
//Sends a command along with arguments and CRC
int FrogmoreScd30::sendCommandArguments(uint16_t command, uint16_t arguments)
{
uint8_t data[5];
data[0] = command >> 8;
data[1] = command & 0xFF;
data[2] = arguments >> 8;
data[3] = arguments & 0xFF;
data[4] = computeCRC8(&data[2], 2); //Calc CRC on the arguments only, not the command
int error = sendBytes(data, sizeof(data));
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30SendCommandArguments: Scd30SendBytes failed: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
}
return (error);
}
int FrogmoreScd30::get16BitRegCheckCRC(void* pInput, uint16_t *pData)
{
uint8_t *pBytes = (uint8_t *) pInput;
uint8_t expectedCRC = computeCRC8(pBytes, SCD30_DATA_REGISTER_BYTES);
if (expectedCRC != pBytes[SCD30_DATA_REGISTER_BYTES])
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30get16BitRegCheckCRC: expected: 0x%02X, but got: 0x%02X", expectedCRC, pBytes[SCD30_DATA_REGISTER_BYTES]);
AddLog(LOG_LEVEL_INFO);
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30get16BitRegCheckCRC: data: 0x%02X, 0x%02X, 0x%02X", pBytes[0], pBytes[1], pBytes[2]);
AddLog(LOG_LEVEL_INFO);
#endif
return (ERROR_SCD30_CRC_ERROR);
}
*pData = (uint16_t) pBytes[0] << 8 | pBytes[1]; // data from SCD30 is Big-Endian
return (ERROR_SCD30_NO_ERROR);
}
// gets 32 bits, (2) 16-bit chunks, and validates the CRCs
//
int FrogmoreScd30::get32BitRegCheckCRC(void *pInput, float *pData)
{
uint16_t tempU16High;
uint16_t tempU16Low;
uint8_t *pBytes = (uint8_t *) pInput;
uint32_t rawInt = 0;
int error = get16BitRegCheckCRC(pBytes, &tempU16High);
if (error) {
return (error);
}
error = get16BitRegCheckCRC(pBytes + SCD30_DATA_REGISTER_WITH_CRC, &tempU16Low);
if (error) {
return (error);
}
// data from SCD is Big-Endian
rawInt |= tempU16High;
rawInt <<= 16;
rawInt |= tempU16Low;
*pData = * (float *) &rawInt;
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "get32BitRegCheckCRC: got: tempUs 0x%lX, %lX", tempU16High, tempU16Low);
AddLog(LOG_LEVEL_DEBUG);
#endif
if (isnan(*pData) || isinf(*pData))
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "get32BitRegCheckCRC: not a floating point number: rawInt 0x%lX", rawInt);
AddLog(LOG_LEVEL_INFO);
#endif
return (ERROR_SCD30_NOT_A_NUMBER_ERROR);
}
return (ERROR_SCD30_NO_ERROR);
}
//Gets two bytes (and check CRC) from SCD30
int FrogmoreScd30::readRegister(uint16_t registerAddress, uint16_t* pData)
{
int error = sendCommand(registerAddress);
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadRegister: SendCommand error: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
delay(1); // the SCD30 uses clock streching to give it time to prepare data, waiting here makes it work
uint8_t data[SCD30_DATA_REGISTER_WITH_CRC];
error = getBytes(data, sizeof(data));
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadRegister: Scd30GetBytes error: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
uint16 regValue;
error = get16BitRegCheckCRC(data, &regValue);
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadRegister: Scd30get16BitRegCheckCRC error: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
*pData = regValue;
return (ERROR_SCD30_NO_ERROR);
}
int FrogmoreScd30::softReset(void)
{
return (sendCommand(COMMAND_SCD30_SOFT_RESET));
}
int FrogmoreScd30::getAltitudeCompensation(uint16_t *pHeight_meter)
{
return (readRegister(COMMAND_SCD30_ALTITUDE_COMPENSATION, pHeight_meter));
}
int FrogmoreScd30::getAmbientPressure(uint16_t *pAirPressure_mbar)
{
*pAirPressure_mbar = ambientPressure;
return (ERROR_SCD30_NO_ERROR);
}
int FrogmoreScd30::getCalibrationType(uint16_t *pIsAuto)
{
uint16_t value = 0;
int error = readRegister(COMMAND_SCD30_CALIBRATION_TYPE, &value);
if (!error)
{
*pIsAuto = value != 0;
}
return (error);
}
int FrogmoreScd30::getFirmwareVersion(uint8_t *pMajor, uint8_t *pMinor)
{
uint16_t value;
int error = readRegister(COMMAND_SCD30_GET_FW_VERSION, &value);
if (!error)
{
*pMajor = value >> 8;
*pMinor = value & 0xFF;
}
return (error);
}
int FrogmoreScd30::getForcedRecalibrationFactor(uint16_t *pCo2_ppm)
{
return (readRegister(COMMAND_SCD30_FORCED_RECALIBRATION_FACTOR, pCo2_ppm));
}
int FrogmoreScd30::getMeasurementInterval(uint16_t *pTime_sec)
{
return (readRegister(COMMAND_SCD30_MEASUREMENT_INTERVAL, pTime_sec));
}
int FrogmoreScd30::getTemperatureOffset(float *pOffset_degC)
{
uint16_t value;
int error = readRegister(COMMAND_SCD30_TEMPERATURE_OFFSET, &value);
if (!error)
{
// result is in centi-degrees, need to convert to degrees
*pOffset_degC = (float) value / 100.0;
}
return (error);
}
int FrogmoreScd30::getTemperatureOffset(uint16_t *pOffset_centiDegC)
{
uint16_t value;
int error = readRegister(COMMAND_SCD30_TEMPERATURE_OFFSET, &value);
if (!error)
{
// result is in centi-degrees, need to convert to degrees
*pOffset_centiDegC = value;
}
return (error);
}
int FrogmoreScd30::setAltitudeCompensation(uint16_t height_meter)
{
return (sendCommandArguments(COMMAND_SCD30_ALTITUDE_COMPENSATION, height_meter));
}
int FrogmoreScd30::setAmbientPressure(uint16_t airPressure_mbar)
{
ambientPressure = airPressure_mbar;
return (beginMeasuring(ambientPressure));
}
int FrogmoreScd30::setAutoSelfCalibration(void)
{
bool isAuto = true;
return (setCalibrationType(isAuto));
}
int FrogmoreScd30::setCalibrationType(bool isAuto)
{
bool value = !!isAuto; // using NOT operator twice makes sure value is 0 or 1
return (sendCommandArguments(COMMAND_SCD30_CALIBRATION_TYPE, value));
}
int FrogmoreScd30::setForcedRecalibrationFactor(uint16_t co2_ppm)
{
return (sendCommandArguments(COMMAND_SCD30_FORCED_RECALIBRATION_FACTOR, co2_ppm));
}
int FrogmoreScd30::setManualCalibration(void)
{
bool isAuto = false;
return (setCalibrationType(isAuto));
}
int FrogmoreScd30::setMeasurementInterval(uint16_t time_sec)
{
if (time_sec < 2) time_sec = 2;
if (time_sec > 1800) time_sec = 1800;
return (sendCommandArguments(COMMAND_SCD30_MEASUREMENT_INTERVAL, time_sec));
}
int FrogmoreScd30::setTemperatureOffset(float offset_degC)
{
uint16_t offset_centiDegC;
if (offset_degC >= 0)
{
offset_centiDegC = (uint16_t) offset_degC * 100;
return (sendCommandArguments(COMMAND_SCD30_TEMPERATURE_OFFSET, offset_centiDegC));
}
else
{
return (ERROR_SCD30_INVALID_VALUE);
}
}
int FrogmoreScd30::setTemperatureOffset(uint16_t offset_centiDegC)
{
return (sendCommandArguments(COMMAND_SCD30_TEMPERATURE_OFFSET, offset_centiDegC));
}
int FrogmoreScd30::beginMeasuring(void)
{
return (beginMeasuring(ambientPressure));
}
int FrogmoreScd30::beginMeasuring(uint16_t airPressure_mbar)
{
ambientPressure = airPressure_mbar;
return(sendCommandArguments(COMMAND_SCD30_CONTINUOUS_MEASUREMENT, ambientPressure));
}
int FrogmoreScd30::isDataAvailable(bool *pIsAvailable)
{
uint16_t isDataAvailable = false;
int error = readRegister(COMMAND_SCD30_GET_DATA_READY, &isDataAvailable);
if (!error)
{
*pIsAvailable = isDataAvailable != 0;
}
return (error);
}
int FrogmoreScd30::readMeasurement(
uint16 *pCO2_ppm,
uint16 *pCO2EAvg_ppm,
float *pTemperature,
float *pHumidity
)
{
bool isAvailable = false;
int error = 0;
float tempCO2;
float tempHumidity;
float tempTemperature;
error = isDataAvailable(&isAvailable);
if (error)
{
return (error);
}
if (!isAvailable)
{
return (ERROR_SCD30_NO_DATA);
}
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: have data");
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
error = sendCommand(COMMAND_SCD30_READ_MEASUREMENT);
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: send command failed: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
delay(1); // the SCD30 uses clock streching to give it time to prepare data, waiting here makes it work
uint8_t bytes[SCD30_MEAS_BYTES];
// there are (6) 16-bit values, each with a CRC in the measurement data
// the chip does not seem to like sending this data, except all at once
error = getBytes(bytes, SCD30_MEAS_BYTES);
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30GetBytes command failed: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30GetBytes data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8]);
AddLog(LOG_LEVEL_DEBUG_MORE);
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30GetBytes data: 0x %02X %02X %02X | 0x %02X %02X %02X | 0x %02X %02X %02X", bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], bytes[16], bytes[17]);
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
error = get32BitRegCheckCRC(&bytes[0], &tempCO2);
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30Get32BitsCheckCRC 1st command failed: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
error = get32BitRegCheckCRC(&bytes[6], &tempTemperature);
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30Get32BitsCheckCRC 2nd command failed: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
error = get32BitRegCheckCRC(&bytes[12], &tempHumidity);
if (error)
{
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: Scd30Get32BitsCheckCRC 3rd command failed: 0x%lX", error);
AddLog(LOG_LEVEL_INFO);
#endif
return (error);
}
if (tempCO2 == 0)
{
return (ERROR_SCD30_CO2_ZERO);
}
if (co2NewDataLocation < 0)
{
co2EAverage = tempCO2;
for (int x = 0; x < SCD30_MEDIAN_FILTER_SIZE; x++)
{
co2History[x] = tempCO2;
co2NewDataLocation = 1;
}
}
else
{
co2History[co2NewDataLocation++] = tempCO2;
if (co2NewDataLocation >= SCD30_MEDIAN_FILTER_SIZE)
{
co2NewDataLocation = 0;
}
}
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: co2History: %ld, %ld, %ld, %ld, %ld", co2History[0], co2History[1], co2History[2], co2History[3], co2History[4]);
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
// copy array since the median filter function will re-arrange it
uint16_t temp[SCD30_MEDIAN_FILTER_SIZE];
for (int x = 0; x < SCD30_MEDIAN_FILTER_SIZE; x++)
{
temp[x] = co2History[x];
}
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: temp: %ld, %ld, %ld, %ld, %ld", temp[0], temp[1], temp[2], temp[3], temp[4]);
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
*pCO2_ppm = opt_med5(temp);
#ifdef SCD30_DEBUG
snprintf_P(scd30log_data, sizeof(scd30log_data), "Scd30ReadMeasurement: CO2_ppm: %ld", *pCO2_ppm);
AddLog(LOG_LEVEL_DEBUG_MORE);
#endif
if (pCO2EAvg_ppm)
{
int16_t delta = (int16_t) *pCO2_ppm - (int16_t) co2EAverage;
int16_t change = delta / 32;
co2EAverage += change;
#if 0
uint16_t remain = co2EAverage % 5;
uint16_t dividend = co2EAverage / 5;
uint16_t co2EAReported = dividend * 5;
if (remain > 2)
{
co2EAReported += 5;
}
*pCO2EAvg_ppm = co2EAReported;
#else
*pCO2EAvg_ppm = co2EAverage;
#endif
}
*pTemperature = tempTemperature;
*pHumidity = tempHumidity;
return (ERROR_SCD30_NO_ERROR);
}
int FrogmoreScd30::stopMeasuring(void)
{
return (sendCommand(COMMAND_SCD30_STOP_MEASUREMENT));
}

View File

@ -0,0 +1,105 @@
/*
# Copyright (c) 2019 Frogmore42
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include "Arduino.h"
//#define SCD30_DEBUG
#define SCD30_ADDRESS 0x61
#define ERROR_SCD30_NO_ERROR 0
#define ERROR_SCD30_NO_DATA 0x80000000
#define ERROR_SCD30_CO2_ZERO 0x90000000
#define ERROR_SCD30_UNKNOWN_ERROR 0x1000000
#define ERROR_SCD30_CRC_ERROR 0x2000000
#define ERROR_SCD30_NOT_ENOUGH_BYTES_ERROR 0x3000000
#define ERROR_SCD30_NOT_FOUND_ERROR 0x4000000
#define ERROR_SCD30_NOT_A_NUMBER_ERROR 0x5000000
#define ERROR_SCD30_INVALID_VALUE 0x6000000
#define SCD30_MEDIAN_FILTER_SIZE 5
class FrogmoreScd30
{
public:
FrogmoreScd30() {};
// Constructors
// the SCD30 only lists a single i2c address, so not necesary to specify
//
void begin(void);
void begin(uint8_t _i2cAddress);
void begin(TwoWire *pWire);
void begin(TwoWire *pWire, uint8_t _i2cAddress);
int softReset(void);
int clearI2CBus(void); // this is a HARD reset of the IC2 bus to restore communication, it will disrupt the bus
int getAltitudeCompensation(uint16_t *pHeight_meter);
int getAmbientPressure(uint16_t *pAirPressure_mbar);
int getCalibrationType(uint16_t *pIsAuto);
int getFirmwareVersion(uint8_t *pMajor, uint8_t *pMinor);
int getForcedRecalibrationFactor(uint16_t *pCo2_ppm);
int getMeasurementInterval(uint16_t *pTime_sec);
int getTemperatureOffset(float *pOffset_degC);
int getTemperatureOffset(uint16_t *pOffset_centiDegC);
int setAltitudeCompensation(uint16_t height_meter);
int setAmbientPressure(uint16_t airPressure_mbar);
int setAutoSelfCalibration(void);
int setCalibrationType(bool isAuto);
int setForcedRecalibrationFactor(uint16_t co2_ppm);
int setManualCalibration(void);
int setMeasurementInterval(uint16_t time_sec);
int setTemperatureOffset(float offset_degC);
int setTemperatureOffset(uint16_t offset_centiDegC);
int beginMeasuring(void);
int beginMeasuring(uint16_t airPressure_mbar); // also sets ambient pressure offset in mbar/hPascal
int isDataAvailable(bool *pIsAvailable);
int readMeasurement(
uint16 *pCO2_ppm,
uint16 *pCO2EAvg_ppm,
float *pTemperature,
float *pHumidity
);
int stopMeasuring(void);
private:
uint8_t i2cAddress;
TwoWire *pWire;
uint16_t ambientPressure;
uint16_t co2AvgExtra;
uint16_t co2History[SCD30_MEDIAN_FILTER_SIZE];
uint16_t co2EAverage;
int8_t co2NewDataLocation; // location to put new CO2 data for median filter
uint8_t computeCRC8(uint8_t data[], uint8_t len);
int sendBytes(void *pInput, uint8_t len);
int getBytes(void *pOutput, uint8_t len);
int sendCommand(uint16_t command);
int sendCommandArguments(uint16_t command, uint16_t arguments);
int get16BitRegCheckCRC(void* pInput, uint16_t* pData);
int get32BitRegCheckCRC(void* pInput, float* pData);
int readRegister(uint16_t registerAddress, uint16_t* pData);
#ifdef SCD30_DEBUG
void AddLog(uint8_t loglevel);
#endif
};

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 Joël Gähwiler
Copyright (c) 2015 Ivan Seidel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -0,0 +1,325 @@
/*
LinkedList.h - V1.1 - Generic LinkedList implementation
Works better with FIFO, because LIFO will need to
search the entire List to find the last one;
For instructions, go to https://github.com/ivanseidel/LinkedList
Created by Ivan Seidel Gomes, March, 2013.
Released into the public domain.
*/
#ifndef LinkedList_h
#define LinkedList_h
#include <stddef.h>
template<class T>
struct ListNode
{
T data;
ListNode<T> *next;
};
template <typename T>
class LinkedList{
protected:
int _size;
ListNode<T> *root;
ListNode<T> *last;
// Helps "get" method, by saving last position
ListNode<T> *lastNodeGot;
int lastIndexGot;
// isCached should be set to FALSE
// everytime the list suffer changes
bool isCached;
ListNode<T>* getNode(int index);
public:
LinkedList();
~LinkedList();
/*
Returns current size of LinkedList
*/
virtual int size();
/*
Adds a T object in the specified index;
Unlink and link the LinkedList correcly;
Increment _size
*/
virtual bool add(int index, T);
/*
Adds a T object in the end of the LinkedList;
Increment _size;
*/
virtual bool add(T);
/*
Adds a T object in the start of the LinkedList;
Increment _size;
*/
virtual bool unshift(T);
/*
Set the object at index, with T;
Increment _size;
*/
virtual bool set(int index, T);
/*
Remove object at index;
If index is not reachable, returns false;
else, decrement _size
*/
virtual T remove(int index);
/*
Remove last object;
*/
virtual T pop();
/*
Remove first object;
*/
virtual T shift();
/*
Get the index'th element on the list;
Return Element if accessible,
else, return false;
*/
virtual T get(int index);
/*
Clear the entire array
*/
virtual void clear();
};
// Initialize LinkedList with false values
template<typename T>
LinkedList<T>::LinkedList()
{
root=NULL;
last=NULL;
_size=0;
lastNodeGot = root;
lastIndexGot = 0;
isCached = false;
}
// Clear Nodes and free Memory
template<typename T>
LinkedList<T>::~LinkedList()
{
ListNode<T>* tmp;
while(root!=NULL)
{
tmp=root;
root=root->next;
delete tmp;
}
last = NULL;
_size=0;
isCached = false;
}
/*
Actualy "logic" coding
*/
template<typename T>
ListNode<T>* LinkedList<T>::getNode(int index){
int _pos = 0;
ListNode<T>* current = root;
// Check if the node trying to get is
// immediatly AFTER the previous got one
if(isCached && lastIndexGot <= index){
_pos = lastIndexGot;
current = lastNodeGot;
}
while(_pos < index && current){
current = current->next;
_pos++;
}
// Check if the object index got is the same as the required
if(_pos == index){
isCached = true;
lastIndexGot = index;
lastNodeGot = current;
return current;
}
return false;
}
template<typename T>
int LinkedList<T>::size(){
return _size;
}
template<typename T>
bool LinkedList<T>::add(int index, T _t){
if(index >= _size)
return add(_t);
if(index == 0)
return unshift(_t);
ListNode<T> *tmp = new ListNode<T>(),
*_prev = getNode(index-1);
tmp->data = _t;
tmp->next = _prev->next;
_prev->next = tmp;
_size++;
isCached = false;
return true;
}
template<typename T>
bool LinkedList<T>::add(T _t){
ListNode<T> *tmp = new ListNode<T>();
tmp->data = _t;
tmp->next = NULL;
if(root){
// Already have elements inserted
last->next = tmp;
last = tmp;
}else{
// First element being inserted
root = tmp;
last = tmp;
}
_size++;
isCached = false;
return true;
}
template<typename T>
bool LinkedList<T>::unshift(T _t){
if(_size == 0)
return add(_t);
ListNode<T> *tmp = new ListNode<T>();
tmp->next = root;
tmp->data = _t;
root = tmp;
_size++;
isCached = false;
return true;
}
template<typename T>
bool LinkedList<T>::set(int index, T _t){
// Check if index position is in bounds
if(index < 0 || index >= _size)
return false;
getNode(index)->data = _t;
return true;
}
template<typename T>
T LinkedList<T>::pop(){
if(_size <= 0)
return T();
isCached = false;
if(_size >= 2){
ListNode<T> *tmp = getNode(_size - 2);
T ret = tmp->next->data;
delete(tmp->next);
tmp->next = NULL;
last = tmp;
_size--;
return ret;
}else{
// Only one element left on the list
T ret = root->data;
delete(root);
root = NULL;
last = NULL;
_size = 0;
return ret;
}
}
template<typename T>
T LinkedList<T>::shift(){
if(_size <= 0)
return T();
if(_size > 1){
ListNode<T> *_next = root->next;
T ret = root->data;
delete(root);
root = _next;
_size --;
isCached = false;
return ret;
}else{
// Only one left, then pop()
return pop();
}
}
template<typename T>
T LinkedList<T>::remove(int index){
if (index < 0 || index >= _size)
{
return T();
}
if(index == 0)
return shift();
if (index == _size-1)
{
return pop();
}
ListNode<T> *tmp = getNode(index - 1);
ListNode<T> *toDelete = tmp->next;
T ret = toDelete->data;
tmp->next = tmp->next->next;
delete(toDelete);
_size--;
isCached = false;
return ret;
}
template<typename T>
T LinkedList<T>::get(int index){
ListNode<T> *tmp = getNode(index);
return (tmp ? tmp->data : T());
}
template<typename T>
void LinkedList<T>::clear(){
while(size() > 0)
shift();
}
#endif

View File

@ -0,0 +1,171 @@
# LinkedList
This library was developed targeting **`Arduino`** applications. However, works just great with any C++.
Implementing a buffer for objects takes time. If we are not in the mood, we just create an `array[1000]` with enough size.
The objective of this library is to create a pattern for projects.
If you need to use a List of: `int`, `float`, `objects`, `Lists` or `Wales`. **This is what you are looking for.**
With a simple but powerful caching algorithm, you can get subsequent objects much faster than usual. Tested without any problems with Lists bigger than 2000 members.
## Installation
1. [Download](https://github.com/ivanseidel/LinkedList/archive/master.zip) the Latest release from gitHub.
2. Unzip and modify the Folder name to "LinkedList" (Remove the '-version')
3. Paste the modified folder on your Library folder (On your `Libraries` folder inside Sketchbooks or Arduino software).
4. Reopen the Arduino software.
**If you are here, because another Library requires this class, just don't waste time reading bellow. Install and ready.**
-------------------------
## Getting started
### The `LinkedList` class
In case you don't know what a LinkedList is and what it's used for, take a quick look at [Wikipedia::LinkedList](https://en.wikipedia.org/wiki/Linked_list) before continuing.
#### To declare a LinkedList object
```c++
// Instantiate a LinkedList that will hold 'integer'
LinkedList<int> myLinkedList = LinkedList<int>();
// Or just this
LinkedList<int> myLinkedList;
// But if you are instantiating a pointer LinkedList...
LinkedList<int> *myLinkedList = new LinkedList<int>();
// If you want a LinkedList with any other type such as 'MyClass'
// Make sure you call delete(MyClass) when you remove!
LinkedList<MyClass> *myLinkedList = new LinkedList<MyClass>();
```
#### Getting the size of the linked list
```c++
// To get the size of a linked list, make use of the size() method
int theSize = myList.size();
// Notice that if it's pointer to the linked list, you should use -> instead
int theSize = myList->size();
```
#### Adding elements
```c++
// add(obj) method will insert at the END of the list
myList.add(myObject);
// add(index, obj) method will try to insert the object at the specified index
myList.add(0, myObject); // Add at the beginning
myList.add(3, myObject); // Add at index 3
// unshift(obj) method will insert the object at the beginning
myList.unshift(myObject);
```
#### Getting elements
```c++
// get(index) will return the element at index
// (notice that the start element is 0, not 1)
// Get the FIRST element
myObject = myList.get(0);
// Get the third element
myObject = myList.get(2);
// Get the LAST element
myObject = myList.get(myList.size() - 1);
```
#### Changing elements
```c++
// set(index, obj) method will change the object at index to obj
// Change the first element to myObject
myList.set(0, myObject);
// Change the third element to myObject
myList.set(2, myObject);
// Change the LAST element of the list
myList.set(myList.size() - 1, myObject);
```
#### Removing elements
```c++
// remove(index) will remove and return the element at index
// Remove the first object
myList.remove(0);
// Get and Delete the third element
myDeletedObject = myList.remove(2);
// pop() will remove and return the LAST element
myDeletedObject = myList.pop();
// shift() will remove and return the FIRST element
myDeletedObject = myList.shift();
// clear() will erase the entire list, leaving it with 0 elements
// NOTE: Clear wont DELETE/FREE memory from Pointers, if you
// are using Classes/Poiners, manualy delete and free those.
myList.clear();
```
------------------------
## Library Reference
### `ListNode` struct
- `T` `ListNode::data` - The object data
- `ListNode<T>` `*next` - Pointer to the next Node
### `LinkedList` class
**`boolean` methods returns if succeeded**
- `LinkedList<T>::LinkedList()` - Constructor.
- `LinkedList<T>::~LinkedList()` - Destructor. Clear Nodes to minimize memory. Does not free pointer memory.
- `int` `LinkedList<T>::size()` - Returns the current size of the list.
- `bool` `LinkedList<T>::add(T)` - Add element T at the END of the list.
- `bool` `LinkedList<T>::add(int index, T)` - Add element T at `index` of the list.
- `bool` `LinkedList<T>::unshift(T)` - Add element T at the BEGINNING of the list.
- `bool` `LinkedList<T>::set(int index, T)` - Set the element at `index` to T.
- `T` `LinkedList<T>::remove(int index)` - Remove element at `index`. Return the removed element. Does not free pointer memory
- `T` `LinkedList<T>::pop()` - Remove the LAST element. Return the removed element.
- `T` `LinkedList<T>::shift()` - Remove the FIRST element. Return the removed element.
- `T` `LinkedList<T>::get(int index)` - Return the element at `index`.
- `void` `LinkedList<T>::clear()` - Removes all elements. Does not free pointer memory.
- **protected** `int` `LinkedList<T>::_size` - Holds the cached size of the list.
- **protected** `ListNode<T>` `LinkedList<T>::*root` - Holds the root node of the list.
- **protected** `ListNode<T>` `LinkedList<T>::*last` - Holds the last node of the list.
- **protected** `ListNode<T>*` `LinkedList<T>::getNode(int index)` - Returns the `index` node of the list.
### Version History
* `1.1 (2013-07-20)`: Cache implemented. Getting subsequent objects is now O(N). Before, O(N^2).
* `1.0 (2013-07-20)`: Original release
![LinkedList](https://d2weczhvl823v0.cloudfront.net/ivanseidel/LinkedList/trend.png)

View File

@ -0,0 +1,81 @@
/*
LinkedList Example
Link: http://github.com/ivanseidel/LinkedList
Example Created by
Tom Stewart, github.com/tastewar
Edited by:
Ivan Seidel, github.com/ivanseidel
*/
#include <LinkedList.h>
// Let's define a new class
class Animal {
public:
char *name;
bool isMammal;
};
char catname[]="kitty";
char dogname[]="doggie";
char emuname[]="emu";
LinkedList<Animal*> myAnimalList = LinkedList<Animal*>();
void setup()
{
Serial.begin(9600);
Serial.println("Hello!" );
// Create a Cat
Animal *cat = new Animal();
cat->name = catname;
cat->isMammal = true;
// Create a dog
Animal *dog = new Animal();
dog->name = dogname;
dog->isMammal = true;
// Create a emu
Animal *emu = new Animal();
emu->name = emuname;
emu->isMammal = false; // just an example; no offense to pig lovers
// Add animals to list
myAnimalList.add(cat);
myAnimalList.add(emu);
myAnimalList.add(dog);
}
void loop() {
Serial.print("There are ");
Serial.print(myAnimalList.size());
Serial.print(" animals in the list. The mammals are: ");
int current = 0;
Animal *animal;
for(int i = 0; i < myAnimalList.size(); i++){
// Get animal from list
animal = myAnimalList.get(i);
// If its a mammal, then print it's name
if(animal->isMammal){
// Avoid printing spacer on the first element
if(current++)
Serial.print(", ");
// Print animal name
Serial.print(animal->name);
}
}
Serial.println(".");
while (true); // nothing else to do, loop forever
}

View File

@ -0,0 +1,58 @@
/*
LinkedList Example
Link: http://github.com/ivanseidel/LinkedList
Example Created by
Tom Stewart, github.com/tastewar
Edited by:
Ivan Seidel, github.com/ivanseidel
*/
#include <LinkedList.h>
LinkedList<int> myList = LinkedList<int>();
void setup()
{
Serial.begin(9600);
Serial.println("Hello!");
// Add some stuff to the list
int k = -240,
l = 123,
m = -2,
n = 222;
myList.add(n);
myList.add(0);
myList.add(l);
myList.add(17);
myList.add(k);
myList.add(m);
}
void loop() {
int listSize = myList.size();
Serial.print("There are ");
Serial.print(listSize);
Serial.print(" integers in the list. The negative ones are: ");
// Print Negative numbers
for (int h = 0; h < listSize; h++) {
// Get value from list
int val = myList.get(h);
// If the value is negative, print it
if (val < 0) {
Serial.print(" ");
Serial.print(val);
}
}
while (true); // nothing else to do, loop forever
}

View File

@ -0,0 +1,28 @@
#######################################
# Syntax Coloring
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
LinkedList KEYWORD1
ListNode KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
size KEYWORD2
add KEYWORD2
unshift KEYWORD2
set KEYWORD2
remove KEYWORD2
pop KEYWORD2
shift KEYWORD2
get KEYWORD2
clear KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -0,0 +1,12 @@
{
"name": "LinkedList",
"keywords": "pattern",
"description": "A fully implemented LinkedList (int, float, objects, Lists or Wales) made to work with Arduino projects",
"repository":
{
"type": "git",
"url": "https://github.com/ivanseidel/LinkedList.git"
},
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -0,0 +1,9 @@
name=LinkedList
version=1.2.3
author=Ivan Seidel <ivanseidel@gmail.com>
maintainer=Ivan Seidel <ivanseidel@gmail.com>
sentence=A fully implemented LinkedList made to work with Arduino projects
paragraph=The objective of this library is to create a pattern for projects. If you need to use a List of: int, float, objects, Lists or Wales. This is what you are looking for.
category=Data Processing
url=https://github.com/ivanseidel/LinkedList
architectures=*

View File

@ -48,7 +48,11 @@ extern "C"
#include "ets_sys.h"
#include "user_interface.h"
// Workaround STAGE compile error
#include <core_version.h>
#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)
void rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id, uint32_t reg_add, uint32_t Msb, uint32_t Lsb, uint32_t indata);
#endif
}
struct slc_queue_item
@ -74,7 +78,7 @@ public:
class NeoEsp8266DmaSpeed800Kbps
{
public:
const static uint32_t I2sClockDivisor = 3;
const static uint32_t I2sClockDivisor = 3;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ResetTimeUs = 50;
};
@ -82,7 +86,7 @@ public:
class NeoEsp8266DmaSpeed400Kbps
{
public:
const static uint32_t I2sClockDivisor = 6;
const static uint32_t I2sClockDivisor = 6;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ResetTimeUs = 50;
};
@ -100,7 +104,7 @@ const uint8_t c_I2sPin = 3; // due to I2S hardware, the pin used is restricted t
template<typename T_SPEED> class NeoEsp8266DmaMethodBase
{
public:
NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize)
NeoEsp8266DmaMethodBase(uint16_t pixelCount, size_t elementSize)
{
uint16_t dmaPixelSize = c_dmaBytesPerPixelBytes * elementSize;
@ -269,7 +273,7 @@ public:
private:
static NeoEsp8266DmaMethodBase* s_this; // for the ISR
size_t _pixelsSize; // Size of '_pixels' buffer
size_t _pixelsSize; // Size of '_pixels' buffer
uint8_t* _pixels; // Holds LED color values
uint32_t _i2sBufferSize; // total size of _i2sBuffer
@ -310,7 +314,7 @@ private:
slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA;
// data block has pending data waiting to send, prepare it
// point last state block to top
// point last state block to top
(finished_item + 1)->next_link_ptr = (uint32_t)(s_this->_i2sBufDesc);
s_this->_dmaState = NeoDmaState_Sending;
@ -367,7 +371,7 @@ private:
}
};
template<typename T_SPEED>
template<typename T_SPEED>
NeoEsp8266DmaMethodBase<T_SPEED>* NeoEsp8266DmaMethodBase<T_SPEED>::s_this;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedWs2813> NeoEsp8266DmaWs2813Method;

View File

@ -1,28 +0,0 @@
# C++ objects and libs
*.slo
*.lo
*.o
#*.a
*.la
*.lai
*.so
*.dll
*.dylib
#Makefile
*-build-*
build-*
*.autosave
# .log files (usually created by QtTest - thanks to VestniK)
*.log
# Editors temporary files
*~
#OSX
.DS_Store
._*

View File

@ -1,8 +0,0 @@
MQTT
====
A Wrapper around mqtt for Arduino to be used with esp8266 modules.
It wraps a slightly modified version of mqtt for esp8266 ported by Tuan PM.
Original code for esp: https://github.com/tuanpmt/esp_mqtt
Original code for contiki: https://github.com/esar/contiki-mqtt

View File

@ -1,102 +0,0 @@
#include <ESP8266WiFi.h>
#include <MQTT.h>
void myDataCb(String& topic, String& data);
void myPublishedCb();
void myDisconnectedCb();
void myConnectedCb();
#define CLIENT_ID "client1"
// create MQTT object
MQTT myMqtt(CLIENT_ID, "192.168.0.1", 1883);
//
const char* ssid = "ssid";
const char* password = "ssid_password";
//
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Connecting to MQTT server");
// setup callbacks
myMqtt.onConnected(myConnectedCb);
myMqtt.onDisconnected(myDisconnectedCb);
myMqtt.onPublished(myPublishedCb);
myMqtt.onData(myDataCb);
Serial.println("connect mqtt...");
myMqtt.connect();
delay(10);
}
//
void loop() {
int value = analogRead(A0);
String topic("/");
topic += CLIENT_ID;
topic += "/value";
String valueStr(value);
// publish value to topic
boolean result = myMqtt.publish(topic, valueStr);
delay(1000);
}
/*
*
*/
void myConnectedCb()
{
Serial.println("connected to MQTT server");
}
void myDisconnectedCb()
{
Serial.println("disconnected. try to reconnect...");
delay(500);
myMqtt.connect();
}
void myPublishedCb()
{
//Serial.println("published.");
}
void myDataCb(String& topic, String& data)
{
Serial.print(topic);
Serial.print(": ");
Serial.println(data);
}

View File

@ -1,97 +0,0 @@
#include <ESP8266WiFi.h>
#include <TasmotaMqtt.h>
// This needs testing
void myDataCb(char* topic, uint8_t* data, unsigned int data_len);
void myPublishedCb();
void myDisconnectedCb();
void myConnectedCb();
#define CLIENT_ID "client3"
#define TOPIC "/client1/value"
// create MQTT
TasmotaMqtt myMqtt();
const char* ssid = "ssid";
const char* password = "ssid_password";
//
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("Connecting to MQTT server");
myMqtt.InitConnection("192.168.0.1", 1883);
myMqtt.InitClient(CLIENT_ID, "", "");
myMqtt.InitLWT("/lwt", "offline");
// setup callbacks
myMqtt.OnConnected(myConnectedCb);
myMqtt.OnDisconnected(myDisconnectedCb);
myMqtt.OnPublished(myPublishedCb);
myMqtt.OnData(myDataCb);
Serial.println("connect mqtt...");
myMqtt.Connect();
Serial.println("subscribe to topic...");
myMqtt.Subscribe(TOPIC);
delay(10);
}
//
void loop() {
}
/*
*
*/
void myConnectedCb()
{
Serial.println("connected to MQTT server");
}
void myDisconnectedCb()
{
Serial.println("disconnected. try to reconnect...");
delay(500);
myMqtt.Connect();
}
void myPublishedCb()
{
//Serial.println("published.");
}
void myDataCb(char* topic, uint8_t* data, unsigned int data_len)
{
Serial.print(topic);
Serial.print(": ");
Serial.println(data);
}

View File

@ -1,39 +0,0 @@
#######################################
# Syntax Coloring Map For Test
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
TasmotaMqtt.h KEYWORD1
TasmotaMqtt KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
InitConnection KEYWORD2
InitClient KEYWORD2
InitLWT KEYWORD2
Connect KEYWORD2
Disconnect KEYWORD2
Connected KEYWORD2
Publish KEYWORD2
Subscribe KEYWORD2
#general
OnConnected KEYWORD2
OnDisconnected KEYWORD2
OnData KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -1,9 +0,0 @@
name=TasmotaMqtt
version=1.0.0
author=Theo Arends
maintainer=Theo Arends <theo@arends.com>
sentence=A Wrapper around mqtt for Arduino to be used with esp8266 modules.
paragraph=It wraps a slightly modified version of mqtt for esp8266 ported by Tuan PM. Original code for esp: https://github.com/tuanpmt/esp_mqtt Original code for contiki: https://github.com/esar/contiki-mqtt
category=Communication
url=
architectures=esp8266

View File

@ -1,194 +0,0 @@
/*
TasmotaMqtt.cpp - Wrapper for mqtt for esp8266 by Tuan PM for Tasmota
Copyright (C) 2018 Theo Arends and Ingo Randolf
This library 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/>.
*/
#include "TasmotaMqtt.h"
#include "user_interface.h"
#include "osapi.h"
#include "os_type.h"
/*********************************************************************************************\
* Prerequisite
*
* Copy .c and .h files from https://github.com/tuanpmt/esp_mqtt folder mqtt to folder mqtt
* - Replace BOOL with bool
* - Remove variables certificate and private_key from file mqtt.c
* - Add file user_config.h with default defines for
* MQTT_BUF_SIZE 256, MQTT_RECONNECT_TIMEOUT 5, QUEUE_BUFFER_SIZE 2048 and PROTOCOL_NAMEv311
\*********************************************************************************************/
/*********************************************************************************************\
* Mqtt internal callbacks
\*********************************************************************************************/
static void mqttConnectedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data;
if (_this && _this->onMqttConnectedCb) _this->onMqttConnectedCb();
}
static void mqttDisconnectedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data;
if (_this && _this->onMqttDisconnectedCb) _this->onMqttDisconnectedCb();
}
static void mqttPublishedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data;
if (_this && _this->onMqttPublishedCb) _this->onMqttPublishedCb();
}
static void mqttTimeoutCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data;
if (_this && _this->onMqttTimeoutCb) _this->onMqttTimeoutCb();
}
static void mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len)
{
MQTT_Client* client = (MQTT_Client*)args;
TasmotaMqtt* _this = (TasmotaMqtt*)client->user_data;
if (_this) _this->_onMqttDataCb(topic, topic_len, data, data_len);
}
/*********************************************************************************************\
* TasmotaMqtt class implementation
\*********************************************************************************************/
TasmotaMqtt::TasmotaMqtt() :
onMqttConnectedCb(0),
onMqttDisconnectedCb(0),
onMqttPublishedCb(0),
onMqttTimeoutCb(0),
onMqttDataCb(0)
{
}
TasmotaMqtt::~TasmotaMqtt()
{
MQTT_DeleteClient(&mqttClient);
}
void TasmotaMqtt::InitConnection(const char* host, uint32_t port, uint8_t security)
{
MQTT_InitConnection(&mqttClient, (uint8_t*)host, port, security);
// set user data
mqttClient.user_data = (void*)this;
MQTT_OnConnected(&mqttClient, mqttConnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
MQTT_OnPublished(&mqttClient, mqttPublishedCb);
MQTT_OnTimeout(&mqttClient, mqttTimeoutCb);
MQTT_OnData(&mqttClient, mqttDataCb);
}
void TasmotaMqtt::InitClient(const char* client_id, const char* client_user, const char* client_pass, uint32_t keep_alive_time, uint8_t clean_session)
{
MQTT_InitClient(&mqttClient, (uint8_t*)client_id, (uint8_t*)client_user, (uint8_t*)client_pass, keep_alive_time, clean_session);
}
void TasmotaMqtt::DeleteClient()
{
MQTT_DeleteClient(&mqttClient);
}
void TasmotaMqtt::InitLWT(const char* will_topic, const char* will_msg, uint8_t will_qos, bool will_retain)
{
MQTT_InitLWT(&mqttClient, (uint8_t*)will_topic, (uint8_t*)will_msg, will_qos, (uint8_t)will_retain);
}
void TasmotaMqtt::OnConnected( void (*function)(void) )
{
onMqttConnectedCb = function;
}
void TasmotaMqtt::OnDisconnected( void (*function)(void) )
{
onMqttDisconnectedCb = function;
}
void TasmotaMqtt::OnPublished( void (*function)(void) )
{
onMqttPublishedCb = function;
}
void TasmotaMqtt::OnTimeout( void (*function)(void) )
{
onMqttTimeoutCb = function;
}
void TasmotaMqtt::OnData( void (*function)(char*, uint8_t*, unsigned int) )
{
onMqttDataCb = function;
}
bool TasmotaMqtt::Subscribe(const char* topic, uint8_t qos)
{
return MQTT_Subscribe(&mqttClient, (char*)topic, qos);
}
bool TasmotaMqtt::Unsubscribe(const char* topic)
{
return MQTT_UnSubscribe(&mqttClient, (char*)topic);
}
void TasmotaMqtt::Connect()
{
MQTT_Connect(&mqttClient);
}
void TasmotaMqtt::Connect(const char* client_id, const char* client_user, const char* client_pass, const char* will_topic, const char* will_msg, uint8_t will_qos, bool will_retain)
{
MQTT_InitClient(&mqttClient, (uint8_t*)client_id, (uint8_t*)client_user, (uint8_t*)client_pass, MQTT_KEEPALIVE, 1);
MQTT_InitLWT(&mqttClient, (uint8_t*)will_topic, (uint8_t*)will_msg, will_qos, (uint8_t)will_retain);
MQTT_Connect(&mqttClient);
}
void TasmotaMqtt::Disconnect()
{
MQTT_Disconnect(&mqttClient);
}
bool TasmotaMqtt::Publish(const char* topic, const char* data, int data_length, int qos, bool retain)
{
return MQTT_Publish(&mqttClient, topic, data, data_length, qos, (int)retain);
}
bool TasmotaMqtt::Connected()
{
return (mqttClient.connState > TCP_CONNECTED);
}
/*********************************************************************************************/
void TasmotaMqtt::_onMqttDataCb(const char* topic, uint32_t topic_len, const char* data, uint32_t data_len)
{
char topic_copy[topic_len +1];
memcpy(topic_copy, topic, topic_len);
topic_copy[topic_len] = 0;
if (0 == data_len) data = (const char*)&topic_copy + topic_len;
onMqttDataCb((char*)topic_copy, (byte*)data, data_len);
}

View File

@ -1,88 +0,0 @@
/*
TasmotaMqtt.h - Wrapper for mqtt for esp8266 by Tuan PM for Tasmota
Copyright (C) 2018 Theo Arends and Ingo Randolf
This library 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/>.
*/
#ifndef TasmotaMqtt_h
#define TasmotaMqtt_h
/*********************************************************************************************\
* TasmotaMqtt supports currently only non-TLS MQTT
*
* Adapted from esp-mqtt-arduino by Ingo Randolf (https://github.com/i-n-g-o/esp-mqtt-arduino)
\*********************************************************************************************/
#include <Arduino.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
extern "C" {
#include <stddef.h>
#include "mqtt/mqtt.h"
}
// MQTT_KEEPALIVE : keepAlive interval in Seconds
#ifndef MQTT_KEEPALIVE
#define MQTT_KEEPALIVE 15
#endif
class TasmotaMqtt {
public:
TasmotaMqtt();
~TasmotaMqtt();
void InitConnection(const char* host, uint32_t port, uint8_t security = 0);
void InitClient(const char* client_id, const char* client_user, const char* client_pass, uint32_t keep_alive_time = MQTT_KEEPALIVE, uint8_t clean_session = 1);
void DeleteClient();
void InitLWT(const char* will_topic, const char* will_msg, uint8_t will_qos = 0, bool will_retain = false);
void OnConnected( void (*)(void) );
void OnDisconnected( void (*)(void) );
void OnPublished( void (*)(void) );
void OnTimeout( void (*)(void) );
void OnData( void (*)(char*, uint8_t*, unsigned int) );
bool Subscribe(const char* topic, uint8_t qos = 0);
bool Unsubscribe(const char* topic);
void Connect();
void Connect(const char* client_id, const char* client_user, const char* client_pass, const char* will_topic, const char* will_msg, uint8_t will_qos = 0, bool will_retain = false);
void Disconnect();
bool Publish(const char* topic, const char* data, int data_length, int qos = 0, bool retain = false);
bool Connected();
int State() { return mqttClient.connState; };
void (*onMqttConnectedCb)(void);
void (*onMqttDisconnectedCb)(void);
void (*onMqttPublishedCb)(void);
void (*onMqttTimeoutCb)(void);
void (*onMqttDataCb) (char*, uint8_t*, unsigned int);
// internal callback
void _onMqttDataCb(const char*, uint32_t, const char*, uint32_t);
private:
MQTT_Client mqttClient;
};
#endif // TasmotaMqtt_h

View File

@ -1,19 +0,0 @@
/*
* debug.h
*
* Created on: Dec 4, 2014
* Author: Minh
*/
#ifndef USER_DEBUG_H_
#define USER_DEBUG_H_
#if defined(MQTT_DEBUG_ON)
#define MQTT_INFO( format, ... ) os_printf( format, ## __VA_ARGS__ )
#else
#define MQTT_INFO( format, ... )
#endif
#endif /* USER_DEBUG_H_ */

View File

@ -1,997 +0,0 @@
/* mqtt.c
* Protocol: http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
*
* Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "user_interface.h"
#include "osapi.h"
#include "espconn.h"
#include "os_type.h"
#include "mem.h"
#include "mqtt_msg.h"
#include "debug.h"
#include "user_config.h"
#include "mqtt.h"
#include "queue.h"
#define MQTT_TASK_PRIO 2
#define MQTT_TASK_QUEUE_SIZE 1
#define MQTT_SEND_TIMOUT 5
#ifndef MQTT_SSL_SIZE
#define MQTT_SSL_SIZE 5120
#endif
#ifndef QUEUE_BUFFER_SIZE
#define QUEUE_BUFFER_SIZE 2048
#endif
/*
unsigned char *default_certificate;
unsigned int default_certificate_len = 0;
unsigned char *default_private_key;
unsigned int default_private_key_len = 0;
*/
os_event_t mqtt_procTaskQueue[MQTT_TASK_QUEUE_SIZE];
#ifdef PROTOCOL_NAMEv311
LOCAL uint8_t zero_len_id[2] = { 0, 0 };
#endif
LOCAL void ICACHE_FLASH_ATTR
mqtt_dns_found(const char *name, ip_addr_t *ipaddr, void *arg)
{
struct espconn *pConn = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pConn->reverse;
if (ipaddr == NULL)
{
MQTT_INFO("DNS: Found, but got no ip, try to reconnect\r\n");
client->connState = TCP_RECONNECT_REQ;
return;
}
MQTT_INFO("DNS: found ip %d.%d.%d.%d\n",
*((uint8 *) &ipaddr->addr),
*((uint8 *) &ipaddr->addr + 1),
*((uint8 *) &ipaddr->addr + 2),
*((uint8 *) &ipaddr->addr + 3));
if (client->ip.addr == 0 && ipaddr->addr != 0)
{
os_memcpy(client->pCon->proto.tcp->remote_ip, &ipaddr->addr, 4);
if (client->security) {
#ifdef MQTT_SSL_ENABLE
espconn_secure_set_size(ESPCONN_CLIENT, MQTT_SSL_SIZE);
espconn_secure_connect(client->pCon);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else {
espconn_connect(client->pCon);
}
client->connState = TCP_CONNECTING;
MQTT_INFO("TCP: connecting...\r\n");
}
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
LOCAL void ICACHE_FLASH_ATTR
deliver_publish(MQTT_Client* client, uint8_t* message, int length)
{
mqtt_event_data_t event_data;
event_data.topic_length = length;
event_data.topic = mqtt_get_publish_topic(message, &event_data.topic_length);
event_data.data_length = length;
event_data.data = mqtt_get_publish_data(message, &event_data.data_length);
if (client->dataCb)
client->dataCb((uint32_t*)client, event_data.topic, event_data.topic_length, event_data.data, event_data.data_length);
}
void ICACHE_FLASH_ATTR
mqtt_send_keepalive(MQTT_Client *client)
{
MQTT_INFO("\r\nMQTT: Send keepalive packet to %s:%d!\r\n", client->host, client->port);
client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection);
client->mqtt_state.pending_msg_type = MQTT_MSG_TYPE_PINGREQ;
client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data);
client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length);
client->sendTimeout = MQTT_SEND_TIMOUT;
MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id);
err_t result = ESPCONN_OK;
if (client->security) {
#ifdef MQTT_SSL_ENABLE
result = espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else {
result = espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length);
}
client->mqtt_state.outbound_message = NULL;
if (ESPCONN_OK == result) {
client->keepAliveTick = 0;
client->connState = MQTT_DATA;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
else {
client->connState = TCP_RECONNECT_DISCONNECTING;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
}
/**
* @brief Delete tcp client and free all memory
* @param mqttClient: The mqtt client which contain TCP client
* @retval None
*/
void ICACHE_FLASH_ATTR
mqtt_tcpclient_delete(MQTT_Client *mqttClient)
{
if (mqttClient->pCon != NULL) {
MQTT_INFO("TCP: Free memory\r\n");
// Force abort connections
espconn_abort(mqttClient->pCon);
// Delete connections
espconn_delete(mqttClient->pCon);
if (mqttClient->pCon->proto.tcp) {
os_free(mqttClient->pCon->proto.tcp);
mqttClient->pCon->proto.tcp = NULL;
}
os_free(mqttClient->pCon);
mqttClient->pCon = NULL;
}
}
/**
* @brief Delete MQTT client and free all memory
* @param mqttClient: The mqtt client
* @retval None
*/
void ICACHE_FLASH_ATTR
mqtt_client_delete(MQTT_Client *mqttClient)
{
if (mqttClient == NULL)
return;
if (mqttClient->pCon != NULL) {
mqtt_tcpclient_delete(mqttClient);
}
if (mqttClient->host != NULL) {
os_free(mqttClient->host);
mqttClient->host = NULL;
}
if (mqttClient->user_data != NULL) {
os_free(mqttClient->user_data);
mqttClient->user_data = NULL;
}
if (mqttClient->mqtt_state.in_buffer != NULL) {
os_free(mqttClient->mqtt_state.in_buffer);
mqttClient->mqtt_state.in_buffer = NULL;
}
if (mqttClient->mqtt_state.out_buffer != NULL) {
os_free(mqttClient->mqtt_state.out_buffer);
mqttClient->mqtt_state.out_buffer = NULL;
}
if (mqttClient->mqtt_state.outbound_message != NULL) {
if (mqttClient->mqtt_state.outbound_message->data != NULL)
{
os_free(mqttClient->mqtt_state.outbound_message->data);
mqttClient->mqtt_state.outbound_message->data = NULL;
}
}
if (mqttClient->mqtt_state.mqtt_connection.buffer != NULL) {
// Already freed but not NULL
mqttClient->mqtt_state.mqtt_connection.buffer = NULL;
}
if (mqttClient->connect_info.client_id != NULL) {
#ifdef PROTOCOL_NAMEv311
/* Don't attempt to free if it's the zero_len array */
if ( ((uint8_t*)mqttClient->connect_info.client_id) != zero_len_id )
os_free(mqttClient->connect_info.client_id);
#else
os_free(mqttClient->connect_info.client_id);
#endif
mqttClient->connect_info.client_id = NULL;
}
if (mqttClient->connect_info.username != NULL) {
os_free(mqttClient->connect_info.username);
mqttClient->connect_info.username = NULL;
}
if (mqttClient->connect_info.password != NULL) {
os_free(mqttClient->connect_info.password);
mqttClient->connect_info.password = NULL;
}
if (mqttClient->connect_info.will_topic != NULL) {
os_free(mqttClient->connect_info.will_topic);
mqttClient->connect_info.will_topic = NULL;
}
if (mqttClient->connect_info.will_message != NULL) {
os_free(mqttClient->connect_info.will_message);
mqttClient->connect_info.will_message = NULL;
}
if (mqttClient->msgQueue.buf != NULL) {
os_free(mqttClient->msgQueue.buf);
mqttClient->msgQueue.buf = NULL;
}
// Initialize state
mqttClient->connState = WIFI_INIT;
// Clear callback functions to avoid abnormal callback
mqttClient->connectedCb = NULL;
mqttClient->disconnectedCb = NULL;
mqttClient->publishedCb = NULL;
mqttClient->timeoutCb = NULL;
mqttClient->dataCb = NULL;
MQTT_INFO("MQTT: client already deleted\r\n");
}
/**
* @brief Client received callback function.
* @param arg: contain the ip link information
* @param pdata: received data
* @param len: the lenght of received data
* @retval None
*/
void ICACHE_FLASH_ATTR
mqtt_tcpclient_recv(void *arg, char *pdata, unsigned short len)
{
uint8_t msg_type;
uint8_t msg_qos;
uint16_t msg_id;
uint8_t msg_conn_ret;
struct espconn *pCon = (struct espconn*)arg;
MQTT_Client *client = (MQTT_Client *)pCon->reverse;
READPACKET:
MQTT_INFO("TCP: data received %d bytes\r\n", len);
// MQTT_INFO("STATE: %d\r\n", client->connState);
if (len < MQTT_BUF_SIZE && len > 0) {
os_memcpy(client->mqtt_state.in_buffer, pdata, len);
msg_type = mqtt_get_type(client->mqtt_state.in_buffer);
msg_qos = mqtt_get_qos(client->mqtt_state.in_buffer);
msg_id = mqtt_get_id(client->mqtt_state.in_buffer, client->mqtt_state.in_buffer_length);
switch (client->connState) {
case MQTT_CONNECT_SENDING:
if (msg_type == MQTT_MSG_TYPE_CONNACK) {
if (client->mqtt_state.pending_msg_type != MQTT_MSG_TYPE_CONNECT) {
MQTT_INFO("MQTT: Invalid packet\r\n");
if (client->security) {
#ifdef MQTT_SSL_ENABLE
espconn_secure_disconnect(client->pCon);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else {
espconn_disconnect(client->pCon);
}
} else {
msg_conn_ret = mqtt_get_connect_return_code(client->mqtt_state.in_buffer);
switch (msg_conn_ret) {
case CONNECTION_ACCEPTED:
MQTT_INFO("MQTT: Connected to %s:%d\r\n", client->host, client->port);
client->connState = MQTT_DATA;
if (client->connectedCb)
client->connectedCb((uint32_t*)client);
break;
case CONNECTION_REFUSE_PROTOCOL:
case CONNECTION_REFUSE_SERVER_UNAVAILABLE:
case CONNECTION_REFUSE_BAD_USERNAME:
case CONNECTION_REFUSE_NOT_AUTHORIZED:
MQTT_INFO("MQTT: Connection refuse, reason code: %d\r\n", msg_conn_ret);
default:
if (client->security) {
#ifdef MQTT_SSL_ENABLE
espconn_secure_disconnect(client->pCon);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else {
espconn_disconnect(client->pCon);
}
}
}
}
break;
case MQTT_DATA:
case MQTT_KEEPALIVE_SEND:
client->mqtt_state.message_length_read = len;
client->mqtt_state.message_length = mqtt_get_total_length(client->mqtt_state.in_buffer, client->mqtt_state.message_length_read);
switch (msg_type)
{
case MQTT_MSG_TYPE_SUBACK:
if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_SUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id)
MQTT_INFO("MQTT: Subscribe successful\r\n");
break;
case MQTT_MSG_TYPE_UNSUBACK:
if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && client->mqtt_state.pending_msg_id == msg_id)
MQTT_INFO("MQTT: UnSubscribe successful\r\n");
break;
case MQTT_MSG_TYPE_PUBLISH:
if (msg_qos == 1)
client->mqtt_state.outbound_message = mqtt_msg_puback(&client->mqtt_state.mqtt_connection, msg_id);
else if (msg_qos == 2)
client->mqtt_state.outbound_message = mqtt_msg_pubrec(&client->mqtt_state.mqtt_connection, msg_id);
if (msg_qos == 1 || msg_qos == 2) {
MQTT_INFO("MQTT: Queue response QoS: %d\r\n", msg_qos);
if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
}
}
deliver_publish(client, client->mqtt_state.in_buffer, client->mqtt_state.message_length_read);
break;
case MQTT_MSG_TYPE_PUBACK:
if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) {
MQTT_INFO("MQTT: received MQTT_MSG_TYPE_PUBACK, finish QoS1 publish\r\n");
}
break;
case MQTT_MSG_TYPE_PUBREC:
client->mqtt_state.outbound_message = mqtt_msg_pubrel(&client->mqtt_state.mqtt_connection, msg_id);
if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
}
break;
case MQTT_MSG_TYPE_PUBREL:
client->mqtt_state.outbound_message = mqtt_msg_pubcomp(&client->mqtt_state.mqtt_connection, msg_id);
if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
}
break;
case MQTT_MSG_TYPE_PUBCOMP:
if (client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH && client->mqtt_state.pending_msg_id == msg_id) {
MQTT_INFO("MQTT: receive MQTT_MSG_TYPE_PUBCOMP, finish QoS2 publish\r\n");
}
break;
case MQTT_MSG_TYPE_PINGREQ:
client->mqtt_state.outbound_message = mqtt_msg_pingresp(&client->mqtt_state.mqtt_connection);
if (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
}
break;
case MQTT_MSG_TYPE_PINGRESP:
// Ignore
break;
}
// NOTE: this is done down here and not in the switch case above
// because the PSOCK_READBUF_LEN() won't work inside a switch
// statement due to the way protothreads resume.
if (msg_type == MQTT_MSG_TYPE_PUBLISH)
{
len = client->mqtt_state.message_length_read;
if (client->mqtt_state.message_length < client->mqtt_state.message_length_read)
{
//client->connState = MQTT_PUBLISH_RECV;
//Not Implement yet
len -= client->mqtt_state.message_length;
pdata += client->mqtt_state.message_length;
MQTT_INFO("Get another published message\r\n");
goto READPACKET;
}
}
break;
}
} else {
MQTT_INFO("ERROR: Message too long\r\n");
}
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
/**
* @brief Client send over callback function.
* @param arg: contain the ip link information
* @retval None
*/
void ICACHE_FLASH_ATTR
mqtt_tcpclient_sent_cb(void *arg)
{
struct espconn *pCon = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pCon->reverse;
MQTT_INFO("TCP: Sent\r\n");
client->sendTimeout = 0;
client->keepAliveTick = 0;
if ((client->connState == MQTT_DATA || client->connState == MQTT_KEEPALIVE_SEND)
&& client->mqtt_state.pending_msg_type == MQTT_MSG_TYPE_PUBLISH) {
if (client->publishedCb)
client->publishedCb((uint32_t*)client);
}
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
void ICACHE_FLASH_ATTR mqtt_timer(void *arg)
{
MQTT_Client* client = (MQTT_Client*)arg;
if (client->connState == MQTT_DATA) {
client->keepAliveTick ++;
if (client->keepAliveTick > (client->mqtt_state.connect_info->keepalive / 2)) {
client->connState = MQTT_KEEPALIVE_SEND;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
} else if (client->connState == TCP_RECONNECT_REQ) {
client->reconnectTick ++;
if (client->reconnectTick > MQTT_RECONNECT_TIMEOUT) {
client->reconnectTick = 0;
client->connState = TCP_RECONNECT;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
if (client->timeoutCb)
client->timeoutCb((uint32_t*)client);
}
}
if (client->sendTimeout > 0)
client->sendTimeout --;
}
void ICACHE_FLASH_ATTR
mqtt_tcpclient_discon_cb(void *arg)
{
struct espconn *pespconn = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pespconn->reverse;
MQTT_INFO("TCP: Disconnected callback\r\n");
if (TCP_DISCONNECTING == client->connState) {
client->connState = TCP_DISCONNECTED;
}
else if (MQTT_DELETING == client->connState) {
client->connState = MQTT_DELETED;
}
else {
client->connState = TCP_RECONNECT_REQ;
}
if (client->disconnectedCb)
client->disconnectedCb((uint32_t*)client);
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
/**
* @brief Tcp client connect success callback function.
* @param arg: contain the ip link information
* @retval None
*/
void ICACHE_FLASH_ATTR
mqtt_tcpclient_connect_cb(void *arg)
{
struct espconn *pCon = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pCon->reverse;
espconn_regist_disconcb(client->pCon, mqtt_tcpclient_discon_cb);
espconn_regist_recvcb(client->pCon, mqtt_tcpclient_recv);////////
espconn_regist_sentcb(client->pCon, mqtt_tcpclient_sent_cb);///////
MQTT_INFO("MQTT: Connected to broker %s:%d\r\n", client->host, client->port);
mqtt_msg_init(&client->mqtt_state.mqtt_connection, client->mqtt_state.out_buffer, client->mqtt_state.out_buffer_length);
client->mqtt_state.outbound_message = mqtt_msg_connect(&client->mqtt_state.mqtt_connection, client->mqtt_state.connect_info);
client->mqtt_state.pending_msg_type = mqtt_get_type(client->mqtt_state.outbound_message->data);
client->mqtt_state.pending_msg_id = mqtt_get_id(client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length);
client->sendTimeout = MQTT_SEND_TIMOUT;
MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id);
if (client->security) {
#ifdef MQTT_SSL_ENABLE
espconn_secure_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else {
espconn_send(client->pCon, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length);
}
client->mqtt_state.outbound_message = NULL;
client->connState = MQTT_CONNECT_SENDING;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
/**
* @brief Tcp client connect repeat callback function.
* @param arg: contain the ip link information
* @retval None
*/
void ICACHE_FLASH_ATTR
mqtt_tcpclient_recon_cb(void *arg, sint8 errType)
{
struct espconn *pCon = (struct espconn *)arg;
MQTT_Client* client = (MQTT_Client *)pCon->reverse;
MQTT_INFO("TCP: Reconnect to %s:%d\r\n", client->host, client->port);
client->connState = TCP_RECONNECT_REQ;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
}
/**
* @brief MQTT publish function.
* @param client: MQTT_Client reference
* @param topic: string topic will publish to
* @param data: buffer data send point to
* @param data_length: length of data
* @param qos: qos
* @param retain: retain
* @retval TRUE if success queue
*/
bool ICACHE_FLASH_ATTR
MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain)
{
uint8_t dataBuffer[MQTT_BUF_SIZE];
uint16_t dataLen;
client->mqtt_state.outbound_message = mqtt_msg_publish(&client->mqtt_state.mqtt_connection,
topic, data, data_length,
qos, retain,
&client->mqtt_state.pending_msg_id);
if (client->mqtt_state.outbound_message->length == 0) {
MQTT_INFO("MQTT: Queuing publish failed\r\n");
return FALSE;
}
MQTT_INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size);
while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) {
MQTT_INFO("MQTT: Serious buffer error\r\n");
return FALSE;
}
}
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
return TRUE;
}
/**
* @brief MQTT subscibe function.
* @param client: MQTT_Client reference
* @param topic: string topic will subscribe
* @param qos: qos
* @retval TRUE if success queue
*/
bool ICACHE_FLASH_ATTR
MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos)
{
uint8_t dataBuffer[MQTT_BUF_SIZE];
uint16_t dataLen;
client->mqtt_state.outbound_message = mqtt_msg_subscribe(&client->mqtt_state.mqtt_connection,
topic, qos,
&client->mqtt_state.pending_msg_id);
MQTT_INFO("MQTT: queue subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id);
while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) {
MQTT_INFO("MQTT: Serious buffer error\r\n");
return FALSE;
}
}
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
return TRUE;
}
/**
* @brief MQTT un-subscibe function.
* @param client: MQTT_Client reference
* @param topic: String topic will un-subscribe
* @retval TRUE if success queue
*/
bool ICACHE_FLASH_ATTR
MQTT_UnSubscribe(MQTT_Client *client, char* topic)
{
uint8_t dataBuffer[MQTT_BUF_SIZE];
uint16_t dataLen;
client->mqtt_state.outbound_message = mqtt_msg_unsubscribe(&client->mqtt_state.mqtt_connection,
topic,
&client->mqtt_state.pending_msg_id);
MQTT_INFO("MQTT: queue un-subscribe, topic\"%s\", id: %d\r\n", topic, client->mqtt_state.pending_msg_id);
while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) {
MQTT_INFO("MQTT: Serious buffer error\r\n");
return FALSE;
}
}
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
return TRUE;
}
/**
* @brief MQTT ping function.
* @param client: MQTT_Client reference
* @retval TRUE if success queue
*/
bool ICACHE_FLASH_ATTR
MQTT_Ping(MQTT_Client *client)
{
uint8_t dataBuffer[MQTT_BUF_SIZE];
uint16_t dataLen;
client->mqtt_state.outbound_message = mqtt_msg_pingreq(&client->mqtt_state.mqtt_connection);
if (client->mqtt_state.outbound_message->length == 0) {
MQTT_INFO("MQTT: Queuing publish failed\r\n");
return FALSE;
}
MQTT_INFO("MQTT: queuing publish, length: %d, queue size(%d/%d)\r\n", client->mqtt_state.outbound_message->length, client->msgQueue.rb.fill_cnt, client->msgQueue.rb.size);
while (QUEUE_Puts(&client->msgQueue, client->mqtt_state.outbound_message->data, client->mqtt_state.outbound_message->length) == -1) {
MQTT_INFO("MQTT: Queue full\r\n");
if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == -1) {
MQTT_INFO("MQTT: Serious buffer error\r\n");
return FALSE;
}
}
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)client);
return TRUE;
}
void ICACHE_FLASH_ATTR
MQTT_Task(os_event_t *e)
{
MQTT_Client* client = (MQTT_Client*)e->par;
uint8_t dataBuffer[MQTT_BUF_SIZE];
uint16_t dataLen;
if (e->par == 0)
return;
switch (client->connState) {
case TCP_RECONNECT_REQ:
break;
case TCP_RECONNECT:
mqtt_tcpclient_delete(client);
MQTT_Connect(client);
MQTT_INFO("TCP: Reconnect to: %s:%d\r\n", client->host, client->port);
client->connState = TCP_CONNECTING;
break;
case MQTT_DELETING:
case TCP_DISCONNECTING:
case TCP_RECONNECT_DISCONNECTING:
if (client->security) {
#ifdef MQTT_SSL_ENABLE
espconn_secure_disconnect(client->pCon);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else {
espconn_disconnect(client->pCon);
}
break;
case TCP_DISCONNECTED:
MQTT_INFO("MQTT: Disconnected\r\n");
mqtt_tcpclient_delete(client);
break;
case MQTT_DELETED:
MQTT_INFO("MQTT: Deleted client\r\n");
mqtt_client_delete(client);
break;
case MQTT_KEEPALIVE_SEND:
mqtt_send_keepalive(client);
break;
case MQTT_DATA:
if (QUEUE_IsEmpty(&client->msgQueue) || client->sendTimeout != 0) {
break;
}
if (QUEUE_Gets(&client->msgQueue, dataBuffer, &dataLen, MQTT_BUF_SIZE) == 0) {
client->mqtt_state.pending_msg_type = mqtt_get_type(dataBuffer);
client->mqtt_state.pending_msg_id = mqtt_get_id(dataBuffer, dataLen);
client->sendTimeout = MQTT_SEND_TIMOUT;
MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type, client->mqtt_state.pending_msg_id);
client->keepAliveTick = 0;
if (client->security) {
#ifdef MQTT_SSL_ENABLE
espconn_secure_send(client->pCon, dataBuffer, dataLen);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else {
espconn_send(client->pCon, dataBuffer, dataLen);
}
client->mqtt_state.outbound_message = NULL;
break;
}
break;
}
}
/**
* @brief MQTT initialization connection function
* @param client: MQTT_Client reference
* @param host: Domain or IP string
* @param port: Port to connect
* @param security: 1 for ssl, 0 for none
* @retval None
*/
void ICACHE_FLASH_ATTR
MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security)
{
uint32_t temp;
MQTT_INFO("MQTT:InitConnection\r\n");
os_memset(mqttClient, 0, sizeof(MQTT_Client));
temp = os_strlen(host);
mqttClient->host = (uint8_t*)os_zalloc(temp + 1);
os_strcpy(mqttClient->host, host);
mqttClient->host[temp] = 0;
mqttClient->port = port;
mqttClient->security = security;
}
/**
* @brief MQTT initialization mqtt client function
* @param client: MQTT_Client reference
* @param clientid: MQTT client id
* @param client_user:MQTT client user
* @param client_pass:MQTT client password
* @param client_pass:MQTT keep alive timer, in second
* @retval None
*/
bool ICACHE_FLASH_ATTR
MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession)
{
uint32_t temp;
MQTT_INFO("MQTT:InitClient\r\n");
os_memset(&mqttClient->connect_info, 0, sizeof(mqtt_connect_info_t));
if ( !client_id )
{
/* Should be allowed by broker, but clean session flag must be set. */
#ifdef PROTOCOL_NAMEv311
if (cleanSession)
{
mqttClient->connect_info.client_id = zero_len_id;
} else {
MQTT_INFO("cleanSession must be set to use 0 length client_id\r\n");
return false;
}
/* Not supported. Return. */
#else
MQTT_INFO("Client ID required for MQTT < 3.1.1!\r\n");
return false;
#endif
}
/* If connect_info's client_id is still NULL and we get here, we can *
* assume the passed client_id is non-NULL. */
if ( !(mqttClient->connect_info.client_id) )
{
temp = os_strlen(client_id);
mqttClient->connect_info.client_id = (uint8_t*)os_zalloc(temp + 1);
os_strcpy(mqttClient->connect_info.client_id, client_id);
mqttClient->connect_info.client_id[temp] = 0;
}
if (client_user)
{
temp = os_strlen(client_user);
mqttClient->connect_info.username = (uint8_t*)os_zalloc(temp + 1);
os_strcpy(mqttClient->connect_info.username, client_user);
mqttClient->connect_info.username[temp] = 0;
}
if (client_pass)
{
temp = os_strlen(client_pass);
mqttClient->connect_info.password = (uint8_t*)os_zalloc(temp + 1);
os_strcpy(mqttClient->connect_info.password, client_pass);
mqttClient->connect_info.password[temp] = 0;
}
mqttClient->connect_info.keepalive = keepAliveTime;
mqttClient->connect_info.clean_session = cleanSession;
mqttClient->mqtt_state.in_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE);
mqttClient->mqtt_state.in_buffer_length = MQTT_BUF_SIZE;
mqttClient->mqtt_state.out_buffer = (uint8_t *)os_zalloc(MQTT_BUF_SIZE);
mqttClient->mqtt_state.out_buffer_length = MQTT_BUF_SIZE;
mqttClient->mqtt_state.connect_info = &mqttClient->connect_info;
mqtt_msg_init(&mqttClient->mqtt_state.mqtt_connection, mqttClient->mqtt_state.out_buffer, mqttClient->mqtt_state.out_buffer_length);
QUEUE_Init(&mqttClient->msgQueue, QUEUE_BUFFER_SIZE);
system_os_task(MQTT_Task, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE);
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient);
return true;
}
void ICACHE_FLASH_ATTR
MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain)
{
uint32_t temp;
temp = os_strlen(will_topic);
mqttClient->connect_info.will_topic = (uint8_t*)os_zalloc(temp + 1);
os_strcpy(mqttClient->connect_info.will_topic, will_topic);
mqttClient->connect_info.will_topic[temp] = 0;
temp = os_strlen(will_msg);
mqttClient->connect_info.will_message = (uint8_t*)os_zalloc(temp + 1);
os_strcpy(mqttClient->connect_info.will_message, will_msg);
mqttClient->connect_info.will_message[temp] = 0;
mqttClient->connect_info.will_qos = will_qos;
mqttClient->connect_info.will_retain = will_retain;
}
/**
* @brief Begin connect to MQTT broker
* @param client: MQTT_Client reference
* @retval None
*/
void ICACHE_FLASH_ATTR
MQTT_Connect(MQTT_Client *mqttClient)
{
if (mqttClient->pCon) {
// Clean up the old connection forcefully - using MQTT_Disconnect
// does not actually release the old connection until the
// disconnection callback is invoked.
mqtt_tcpclient_delete(mqttClient);
}
mqttClient->pCon = (struct espconn *)os_zalloc(sizeof(struct espconn));
mqttClient->pCon->type = ESPCONN_TCP;
mqttClient->pCon->state = ESPCONN_NONE;
mqttClient->pCon->proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
mqttClient->pCon->proto.tcp->local_port = espconn_port();
mqttClient->pCon->proto.tcp->remote_port = mqttClient->port;
mqttClient->pCon->reverse = mqttClient;
espconn_regist_connectcb(mqttClient->pCon, mqtt_tcpclient_connect_cb);
espconn_regist_reconcb(mqttClient->pCon, mqtt_tcpclient_recon_cb);
mqttClient->keepAliveTick = 0;
mqttClient->reconnectTick = 0;
os_timer_disarm(&mqttClient->mqttTimer);
os_timer_setfn(&mqttClient->mqttTimer, (os_timer_func_t *)mqtt_timer, mqttClient);
os_timer_arm(&mqttClient->mqttTimer, 1000, 1);
if (UTILS_StrToIP(mqttClient->host, &mqttClient->pCon->proto.tcp->remote_ip)) {
MQTT_INFO("TCP: Connect to ip %s:%d\r\n", mqttClient->host, mqttClient->port);
if (mqttClient->security)
{
#ifdef MQTT_SSL_ENABLE
espconn_secure_set_size(ESPCONN_CLIENT, MQTT_SSL_SIZE);
espconn_secure_connect(mqttClient->pCon);
#else
MQTT_INFO("TCP: Do not support SSL\r\n");
#endif
}
else
{
espconn_connect(mqttClient->pCon);
}
}
else {
MQTT_INFO("TCP: Connect to domain %s:%d\r\n", mqttClient->host, mqttClient->port);
espconn_gethostbyname(mqttClient->pCon, mqttClient->host, &mqttClient->ip, mqtt_dns_found);
}
mqttClient->connState = TCP_CONNECTING;
}
void ICACHE_FLASH_ATTR
MQTT_Disconnect(MQTT_Client *mqttClient)
{
mqttClient->connState = TCP_DISCONNECTING;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient);
os_timer_disarm(&mqttClient->mqttTimer);
}
void ICACHE_FLASH_ATTR
MQTT_DeleteClient(MQTT_Client *mqttClient)
{
if (NULL == mqttClient)
return;
mqttClient->connState = MQTT_DELETED;
// if(TCP_DISCONNECTED == mqttClient->connState) {
// mqttClient->connState = MQTT_DELETED;
// } else if(MQTT_DELETED != mqttClient->connState) {
// mqttClient->connState = MQTT_DELETING;
// }
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClient);
os_timer_disarm(&mqttClient->mqttTimer);
}
void ICACHE_FLASH_ATTR
MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb)
{
mqttClient->connectedCb = connectedCb;
}
void ICACHE_FLASH_ATTR
MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb)
{
mqttClient->disconnectedCb = disconnectedCb;
}
void ICACHE_FLASH_ATTR
MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb)
{
mqttClient->dataCb = dataCb;
}
void ICACHE_FLASH_ATTR
MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb)
{
mqttClient->publishedCb = publishedCb;
}
void ICACHE_FLASH_ATTR
MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb)
{
mqttClient->timeoutCb = timeoutCb;
}

View File

@ -1,148 +0,0 @@
/* mqtt.h
*
* Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef USER_AT_MQTT_H_
#define USER_AT_MQTT_H_
#include "user_config.h"
#include "mqtt_msg.h"
#include "user_interface.h"
#include "queue.h"
typedef struct mqtt_event_data_t
{
uint8_t type;
const char* topic;
const char* data;
uint16_t topic_length;
uint16_t data_length;
uint16_t data_offset;
} mqtt_event_data_t;
typedef struct mqtt_state_t
{
uint16_t port;
int auto_reconnect;
mqtt_connect_info_t* connect_info;
uint8_t* in_buffer;
uint8_t* out_buffer;
int in_buffer_length;
int out_buffer_length;
uint16_t message_length;
uint16_t message_length_read;
mqtt_message_t* outbound_message;
mqtt_connection_t mqtt_connection;
uint16_t pending_msg_id;
int pending_msg_type;
int pending_publish_qos;
} mqtt_state_t;
typedef enum {
WIFI_INIT,
WIFI_CONNECTING,
WIFI_CONNECTING_ERROR,
WIFI_CONNECTED,
DNS_RESOLVE,
TCP_DISCONNECTING,
TCP_DISCONNECTED,
TCP_RECONNECT_DISCONNECTING,
TCP_RECONNECT_REQ,
TCP_RECONNECT,
TCP_CONNECTING,
TCP_CONNECTING_ERROR,
TCP_CONNECTED,
MQTT_CONNECT_SEND,
MQTT_CONNECT_SENDING,
MQTT_SUBSCIBE_SEND,
MQTT_SUBSCIBE_SENDING,
MQTT_DATA,
MQTT_KEEPALIVE_SEND,
MQTT_PUBLISH_RECV,
MQTT_PUBLISHING,
MQTT_DELETING,
MQTT_DELETED,
} tConnState;
typedef void (*MqttCallback)(uint32_t *args);
typedef void (*MqttDataCallback)(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t lengh);
typedef struct {
struct espconn *pCon;
uint8_t security;
uint8_t* host;
uint32_t port;
ip_addr_t ip;
mqtt_state_t mqtt_state;
mqtt_connect_info_t connect_info;
MqttCallback connectedCb;
MqttCallback disconnectedCb;
MqttCallback publishedCb;
MqttCallback timeoutCb;
MqttDataCallback dataCb;
ETSTimer mqttTimer;
uint32_t keepAliveTick;
uint32_t reconnectTick;
uint32_t sendTimeout;
tConnState connState;
QUEUE msgQueue;
void* user_data;
} MQTT_Client;
#define SEC_NONSSL 0
#define SEC_SSL 1
#define MQTT_FLAG_CONNECTED 1
#define MQTT_FLAG_READY 2
#define MQTT_FLAG_EXIT 4
#define MQTT_EVENT_TYPE_NONE 0
#define MQTT_EVENT_TYPE_CONNECTED 1
#define MQTT_EVENT_TYPE_DISCONNECTED 2
#define MQTT_EVENT_TYPE_SUBSCRIBED 3
#define MQTT_EVENT_TYPE_UNSUBSCRIBED 4
#define MQTT_EVENT_TYPE_PUBLISH 5
#define MQTT_EVENT_TYPE_PUBLISHED 6
#define MQTT_EVENT_TYPE_EXITED 7
#define MQTT_EVENT_TYPE_PUBLISH_CONTINUATION 8
void ICACHE_FLASH_ATTR MQTT_InitConnection(MQTT_Client *mqttClient, uint8_t* host, uint32_t port, uint8_t security);
bool ICACHE_FLASH_ATTR MQTT_InitClient(MQTT_Client *mqttClient, uint8_t* client_id, uint8_t* client_user, uint8_t* client_pass, uint32_t keepAliveTime, uint8_t cleanSession);
void ICACHE_FLASH_ATTR MQTT_DeleteClient(MQTT_Client *mqttClient);
void ICACHE_FLASH_ATTR MQTT_InitLWT(MQTT_Client *mqttClient, uint8_t* will_topic, uint8_t* will_msg, uint8_t will_qos, uint8_t will_retain);
void ICACHE_FLASH_ATTR MQTT_OnConnected(MQTT_Client *mqttClient, MqttCallback connectedCb);
void ICACHE_FLASH_ATTR MQTT_OnDisconnected(MQTT_Client *mqttClient, MqttCallback disconnectedCb);
void ICACHE_FLASH_ATTR MQTT_OnPublished(MQTT_Client *mqttClient, MqttCallback publishedCb);
void ICACHE_FLASH_ATTR MQTT_OnTimeout(MQTT_Client *mqttClient, MqttCallback timeoutCb);
void ICACHE_FLASH_ATTR MQTT_OnData(MQTT_Client *mqttClient, MqttDataCallback dataCb);
bool ICACHE_FLASH_ATTR MQTT_Subscribe(MQTT_Client *client, char* topic, uint8_t qos);
bool ICACHE_FLASH_ATTR MQTT_UnSubscribe(MQTT_Client *client, char* topic);
void ICACHE_FLASH_ATTR MQTT_Connect(MQTT_Client *mqttClient);
void ICACHE_FLASH_ATTR MQTT_Disconnect(MQTT_Client *mqttClient);
bool ICACHE_FLASH_ATTR MQTT_Publish(MQTT_Client *client, const char* topic, const char* data, int data_length, int qos, int retain);
#endif /* USER_AT_MQTT_H_ */

View File

@ -1,487 +0,0 @@
/*
* Copyright (c) 2014, Stephen Robinson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include "mqtt_msg.h"
#include "user_config.h"
#define MQTT_MAX_FIXED_HEADER_SIZE 3
enum mqtt_connect_flag
{
MQTT_CONNECT_FLAG_USERNAME = 1 << 7,
MQTT_CONNECT_FLAG_PASSWORD = 1 << 6,
MQTT_CONNECT_FLAG_WILL_RETAIN = 1 << 5,
MQTT_CONNECT_FLAG_WILL = 1 << 2,
MQTT_CONNECT_FLAG_CLEAN_SESSION = 1 << 1
};
struct __attribute((__packed__)) mqtt_connect_variable_header
{
uint8_t lengthMsb;
uint8_t lengthLsb;
#if defined(PROTOCOL_NAMEv31)
uint8_t magic[6];
#elif defined(PROTOCOL_NAMEv311)
uint8_t magic[4];
#else
#error "Please define protocol name"
#endif
uint8_t version;
uint8_t flags;
uint8_t keepaliveMsb;
uint8_t keepaliveLsb;
};
static int ICACHE_FLASH_ATTR append_string(mqtt_connection_t* connection, const char* string, int len)
{
if (connection->message.length + len + 2 > connection->buffer_length)
return -1;
connection->buffer[connection->message.length++] = len >> 8;
connection->buffer[connection->message.length++] = len & 0xff;
memcpy(connection->buffer + connection->message.length, string, len);
connection->message.length += len;
return len + 2;
}
static uint16_t ICACHE_FLASH_ATTR append_message_id(mqtt_connection_t* connection, uint16_t message_id)
{
// If message_id is zero then we should assign one, otherwise
// we'll use the one supplied by the caller
while (message_id == 0)
message_id = ++connection->message_id;
if (connection->message.length + 2 > connection->buffer_length)
return 0;
connection->buffer[connection->message.length++] = message_id >> 8;
connection->buffer[connection->message.length++] = message_id & 0xff;
return message_id;
}
static int ICACHE_FLASH_ATTR init_message(mqtt_connection_t* connection)
{
connection->message.length = MQTT_MAX_FIXED_HEADER_SIZE;
return MQTT_MAX_FIXED_HEADER_SIZE;
}
static mqtt_message_t* ICACHE_FLASH_ATTR fail_message(mqtt_connection_t* connection)
{
connection->message.data = connection->buffer;
connection->message.length = 0;
return &connection->message;
}
static mqtt_message_t* ICACHE_FLASH_ATTR fini_message(mqtt_connection_t* connection, int type, int dup, int qos, int retain)
{
int remaining_length = connection->message.length - MQTT_MAX_FIXED_HEADER_SIZE;
if (remaining_length > 127)
{
connection->buffer[0] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1);
connection->buffer[1] = 0x80 | (remaining_length % 128);
connection->buffer[2] = remaining_length / 128;
connection->message.length = remaining_length + 3;
connection->message.data = connection->buffer;
}
else
{
connection->buffer[1] = ((type & 0x0f) << 4) | ((dup & 1) << 3) | ((qos & 3) << 1) | (retain & 1);
connection->buffer[2] = remaining_length;
connection->message.length = remaining_length + 2;
connection->message.data = connection->buffer + 1;
}
return &connection->message;
}
void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length)
{
memset(connection, 0, sizeof(mqtt_connection_t));
connection->buffer = buffer;
connection->buffer_length = buffer_length;
}
int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length)
{
int i;
int totlen = 0;
for (i = 1; i < length; ++i)
{
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0)
{
++i;
break;
}
}
totlen += i;
return totlen;
}
const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length)
{
int i;
int totlen = 0;
int topiclen;
for (i = 1; i < *length; ++i)
{
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0)
{
++i;
break;
}
}
totlen += i;
if (i + 2 >= *length)
return NULL;
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
if (i + topiclen > *length)
return NULL;
*length = topiclen;
return (const char*)(buffer + i);
}
const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length)
{
int i;
int totlen = 0;
int topiclen;
int blength = *length;
*length = 0;
for (i = 1; i < blength; ++i)
{
totlen += (buffer[i] & 0x7f) << (7 * (i - 1));
if ((buffer[i] & 0x80) == 0)
{
++i;
break;
}
}
totlen += i;
if (i + 2 >= blength)
return NULL;
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
if (i + topiclen >= blength)
return NULL;
i += topiclen;
if (mqtt_get_qos(buffer) > 0)
{
if (i + 2 >= blength)
return NULL;
i += 2;
}
if (totlen < i)
return NULL;
if (totlen <= blength)
*length = totlen - i;
else
*length = blength - i;
return (const char*)(buffer + i);
}
uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length)
{
if (length < 1)
return 0;
switch (mqtt_get_type(buffer))
{
case MQTT_MSG_TYPE_PUBLISH:
{
int i;
int topiclen;
for (i = 1; i < length; ++i)
{
if ((buffer[i] & 0x80) == 0)
{
++i;
break;
}
}
if (i + 2 >= length)
return 0;
topiclen = buffer[i++] << 8;
topiclen |= buffer[i++];
if (i + topiclen >= length)
return 0;
i += topiclen;
if (mqtt_get_qos(buffer) > 0)
{
if (i + 2 >= length)
return 0;
//i += 2;
} else {
return 0;
}
return (buffer[i] << 8) | buffer[i + 1];
}
case MQTT_MSG_TYPE_PUBACK:
case MQTT_MSG_TYPE_PUBREC:
case MQTT_MSG_TYPE_PUBREL:
case MQTT_MSG_TYPE_PUBCOMP:
case MQTT_MSG_TYPE_SUBACK:
case MQTT_MSG_TYPE_UNSUBACK:
case MQTT_MSG_TYPE_SUBSCRIBE:
{
// This requires the remaining length to be encoded in 1 byte,
// which it should be.
if (length >= 4 && (buffer[1] & 0x80) == 0)
return (buffer[2] << 8) | buffer[3];
else
return 0;
}
default:
return 0;
}
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info)
{
struct mqtt_connect_variable_header* variable_header;
init_message(connection);
if (connection->message.length + sizeof(*variable_header) > connection->buffer_length)
return fail_message(connection);
variable_header = (void*)(connection->buffer + connection->message.length);
connection->message.length += sizeof(*variable_header);
variable_header->lengthMsb = 0;
#if defined(PROTOCOL_NAMEv31)
variable_header->lengthLsb = 6;
memcpy(variable_header->magic, "MQIsdp", 6);
variable_header->version = 3;
#elif defined(PROTOCOL_NAMEv311)
variable_header->lengthLsb = 4;
memcpy(variable_header->magic, "MQTT", 4);
variable_header->version = 4;
#else
#error "Please define protocol name"
#endif
variable_header->flags = 0;
variable_header->keepaliveMsb = info->keepalive >> 8;
variable_header->keepaliveLsb = info->keepalive & 0xff;
if (info->clean_session)
variable_header->flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
if (info->client_id == NULL)
{
/* Never allowed */
return fail_message(connection);
}
else if (info->client_id[0] == '\0')
{
#ifdef PROTOCOL_NAMEv311
/* Allowed. Format 0 Length ID */
append_string(connection, info->client_id, 2) ;
#else
/* 0 Length not allowed */
return fail_message(connection);
#endif
}
else
{
/* No 0 data and at least 1 long. Good to go. */
if(append_string(connection, info->client_id, strlen(info->client_id)) < 0)
return fail_message(connection);
}
if (info->will_topic != NULL && info->will_topic[0] != '\0')
{
if (append_string(connection, info->will_topic, strlen(info->will_topic)) < 0)
return fail_message(connection);
if (append_string(connection, info->will_message, strlen(info->will_message)) < 0)
return fail_message(connection);
variable_header->flags |= MQTT_CONNECT_FLAG_WILL;
if (info->will_retain)
variable_header->flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;
variable_header->flags |= (info->will_qos & 3) << 3;
}
if (info->username != NULL && info->username[0] != '\0')
{
if (append_string(connection, info->username, strlen(info->username)) < 0)
return fail_message(connection);
variable_header->flags |= MQTT_CONNECT_FLAG_USERNAME;
}
if (info->password != NULL && info->password[0] != '\0')
{
if (append_string(connection, info->password, strlen(info->password)) < 0)
return fail_message(connection);
variable_header->flags |= MQTT_CONNECT_FLAG_PASSWORD;
}
return fini_message(connection, MQTT_MSG_TYPE_CONNECT, 0, 0, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id)
{
init_message(connection);
if (topic == NULL || topic[0] == '\0')
return fail_message(connection);
if (append_string(connection, topic, strlen(topic)) < 0)
return fail_message(connection);
if (qos > 0)
{
if ((*message_id = append_message_id(connection, 0)) == 0)
return fail_message(connection);
}
else
*message_id = 0;
if (connection->message.length + data_length > connection->buffer_length)
return fail_message(connection);
memcpy(connection->buffer + connection->message.length, data, data_length);
connection->message.length += data_length;
return fini_message(connection, MQTT_MSG_TYPE_PUBLISH, 0, qos, retain);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id)
{
init_message(connection);
if (append_message_id(connection, message_id) == 0)
return fail_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_PUBACK, 0, 0, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id)
{
init_message(connection);
if (append_message_id(connection, message_id) == 0)
return fail_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_PUBREC, 0, 0, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id)
{
init_message(connection);
if (append_message_id(connection, message_id) == 0)
return fail_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_PUBREL, 0, 1, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id)
{
init_message(connection);
if (append_message_id(connection, message_id) == 0)
return fail_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_PUBCOMP, 0, 0, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id)
{
init_message(connection);
if (topic == NULL || topic[0] == '\0')
return fail_message(connection);
if ((*message_id = append_message_id(connection, 0)) == 0)
return fail_message(connection);
if (append_string(connection, topic, strlen(topic)) < 0)
return fail_message(connection);
if (connection->message.length + 1 > connection->buffer_length)
return fail_message(connection);
connection->buffer[connection->message.length++] = qos;
return fini_message(connection, MQTT_MSG_TYPE_SUBSCRIBE, 0, 1, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id)
{
init_message(connection);
if (topic == NULL || topic[0] == '\0')
return fail_message(connection);
if ((*message_id = append_message_id(connection, 0)) == 0)
return fail_message(connection);
if (append_string(connection, topic, strlen(topic)) < 0)
return fail_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_UNSUBSCRIBE, 0, 1, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection)
{
init_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_PINGREQ, 0, 0, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection)
{
init_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_PINGRESP, 0, 0, 0);
}
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection)
{
init_message(connection);
return fini_message(connection, MQTT_MSG_TYPE_DISCONNECT, 0, 0, 0);
}

View File

@ -1,141 +0,0 @@
/*
* File: mqtt_msg.h
* Author: Minh Tuan
*
* Created on July 12, 2014, 1:05 PM
*/
#ifndef MQTT_MSG_H
#define MQTT_MSG_H
#include "user_config.h"
#include "c_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Copyright (c) 2014, Stephen Robinson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/* 7 6 5 4 3 2 1 0*/
/*| --- Message Type---- | DUP Flag | QoS Level | Retain |
/* Remaining Length */
enum mqtt_message_type
{
MQTT_MSG_TYPE_CONNECT = 1,
MQTT_MSG_TYPE_CONNACK = 2,
MQTT_MSG_TYPE_PUBLISH = 3,
MQTT_MSG_TYPE_PUBACK = 4,
MQTT_MSG_TYPE_PUBREC = 5,
MQTT_MSG_TYPE_PUBREL = 6,
MQTT_MSG_TYPE_PUBCOMP = 7,
MQTT_MSG_TYPE_SUBSCRIBE = 8,
MQTT_MSG_TYPE_SUBACK = 9,
MQTT_MSG_TYPE_UNSUBSCRIBE = 10,
MQTT_MSG_TYPE_UNSUBACK = 11,
MQTT_MSG_TYPE_PINGREQ = 12,
MQTT_MSG_TYPE_PINGRESP = 13,
MQTT_MSG_TYPE_DISCONNECT = 14
};
enum mqtt_connect_return_code
{
CONNECTION_ACCEPTED = 0,
CONNECTION_REFUSE_PROTOCOL,
CONNECTION_REFUSE_ID_REJECTED,
CONNECTION_REFUSE_SERVER_UNAVAILABLE,
CONNECTION_REFUSE_BAD_USERNAME,
CONNECTION_REFUSE_NOT_AUTHORIZED
};
typedef struct mqtt_message
{
uint8_t* data;
uint16_t length;
} mqtt_message_t;
typedef struct mqtt_connection
{
mqtt_message_t message;
uint16_t message_id;
uint8_t* buffer;
uint16_t buffer_length;
} mqtt_connection_t;
typedef struct mqtt_connect_info
{
char* client_id;
char* username;
char* password;
char* will_topic;
char* will_message;
uint32_t keepalive;
int will_qos;
int will_retain;
int clean_session;
} mqtt_connect_info_t;
static inline int ICACHE_FLASH_ATTR mqtt_get_type(uint8_t* buffer) { return (buffer[0] & 0xf0) >> 4; }
static inline int ICACHE_FLASH_ATTR mqtt_get_connect_return_code(uint8_t* buffer) { return buffer[3]; }
static inline int ICACHE_FLASH_ATTR mqtt_get_dup(uint8_t* buffer) { return (buffer[0] & 0x08) >> 3; }
static inline int ICACHE_FLASH_ATTR mqtt_get_qos(uint8_t* buffer) { return (buffer[0] & 0x06) >> 1; }
static inline int ICACHE_FLASH_ATTR mqtt_get_retain(uint8_t* buffer) { return (buffer[0] & 0x01); }
void ICACHE_FLASH_ATTR mqtt_msg_init(mqtt_connection_t* connection, uint8_t* buffer, uint16_t buffer_length);
int ICACHE_FLASH_ATTR mqtt_get_total_length(uint8_t* buffer, uint16_t length);
const char* ICACHE_FLASH_ATTR mqtt_get_publish_topic(uint8_t* buffer, uint16_t* length);
const char* ICACHE_FLASH_ATTR mqtt_get_publish_data(uint8_t* buffer, uint16_t* length);
uint16_t ICACHE_FLASH_ATTR mqtt_get_id(uint8_t* buffer, uint16_t length);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_connect(mqtt_connection_t* connection, mqtt_connect_info_t* info);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_publish(mqtt_connection_t* connection, const char* topic, const char* data, int data_length, int qos, int retain, uint16_t* message_id);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_puback(mqtt_connection_t* connection, uint16_t message_id);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrec(mqtt_connection_t* connection, uint16_t message_id);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubrel(mqtt_connection_t* connection, uint16_t message_id);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pubcomp(mqtt_connection_t* connection, uint16_t message_id);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_subscribe(mqtt_connection_t* connection, const char* topic, int qos, uint16_t* message_id);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_unsubscribe(mqtt_connection_t* connection, const char* topic, uint16_t* message_id);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingreq(mqtt_connection_t* connection);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_pingresp(mqtt_connection_t* connection);
mqtt_message_t* ICACHE_FLASH_ATTR mqtt_msg_disconnect(mqtt_connection_t* connection);
#ifdef __cplusplus
}
#endif
#endif /* MQTT_MSG_H */

View File

@ -1,129 +0,0 @@
#include "proto.h"
#include "ringbuf.h"
I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize)
{
parser->buf = buf;
parser->bufSize = bufSize;
parser->dataLen = 0;
parser->callback = completeCallback;
parser->isEsc = 0;
return 0;
}
I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value)
{
switch (value) {
case 0x7D:
parser->isEsc = 1;
break;
case 0x7E:
parser->dataLen = 0;
parser->isEsc = 0;
parser->isBegin = 1;
break;
case 0x7F:
if (parser->callback != NULL)
parser->callback();
parser->isBegin = 0;
return 0;
break;
default:
if (parser->isBegin == 0) break;
if (parser->isEsc) {
value ^= 0x20;
parser->isEsc = 0;
}
if (parser->dataLen < parser->bufSize)
parser->buf[parser->dataLen++] = value;
break;
}
return -1;
}
I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len)
{
while (len--)
PROTO_ParseByte(parser, *buf++);
return 0;
}
I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF* rb, U8 *bufOut, U16* len, U16 maxBufLen)
{
U8 c;
PROTO_PARSER proto;
PROTO_Init(&proto, NULL, bufOut, maxBufLen);
while (RINGBUF_Get(rb, &c) == 0) {
if (PROTO_ParseByte(&proto, c) == 0) {
*len = proto.dataLen;
return 0;
}
}
return -1;
}
I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize)
{
U16 i = 2;
U16 len = *(U16*) packet;
if (bufSize < 1) return -1;
*buf++ = 0x7E;
bufSize--;
while (len--) {
switch (*packet) {
case 0x7D:
case 0x7E:
case 0x7F:
if (bufSize < 2) return -1;
*buf++ = 0x7D;
*buf++ = *packet++ ^ 0x20;
i += 2;
bufSize -= 2;
break;
default:
if (bufSize < 1) return -1;
*buf++ = *packet++;
i++;
bufSize--;
break;
}
}
if (bufSize < 1) return -1;
*buf++ = 0x7F;
return i;
}
I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len)
{
U16 i = 2;
if (RINGBUF_Put(rb, 0x7E) == -1) return -1;
while (len--) {
switch (*packet) {
case 0x7D:
case 0x7E:
case 0x7F:
if (RINGBUF_Put(rb, 0x7D) == -1) return -1;
if (RINGBUF_Put(rb, *packet++ ^ 0x20) == -1) return -1;
i += 2;
break;
default:
if (RINGBUF_Put(rb, *packet++) == -1) return -1;
i++;
break;
}
}
if (RINGBUF_Put(rb, 0x7F) == -1) return -1;
return i;
}

View File

@ -1,32 +0,0 @@
/*
* File: proto.h
* Author: ThuHien
*
* Created on November 23, 2012, 8:57 AM
*/
#ifndef _PROTO_H_
#define _PROTO_H_
#include <stdlib.h>
#include "typedef.h"
#include "ringbuf.h"
typedef void(PROTO_PARSE_CALLBACK)();
typedef struct {
U8 *buf;
U16 bufSize;
U16 dataLen;
U8 isEsc;
U8 isBegin;
PROTO_PARSE_CALLBACK* callback;
} PROTO_PARSER;
I8 ICACHE_FLASH_ATTR PROTO_Init(PROTO_PARSER *parser, PROTO_PARSE_CALLBACK *completeCallback, U8 *buf, U16 bufSize);
I8 ICACHE_FLASH_ATTR PROTO_Parse(PROTO_PARSER *parser, U8 *buf, U16 len);
I16 ICACHE_FLASH_ATTR PROTO_Add(U8 *buf, const U8 *packet, I16 bufSize);
I16 ICACHE_FLASH_ATTR PROTO_AddRb(RINGBUF *rb, const U8 *packet, I16 len);
I8 ICACHE_FLASH_ATTR PROTO_ParseByte(PROTO_PARSER *parser, U8 value);
I16 ICACHE_FLASH_ATTR PROTO_ParseRb(RINGBUF *rb, U8 *bufOut, U16* len, U16 maxBufLen);
#endif

View File

@ -1,75 +0,0 @@
/* str_queue.c
*
* Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "queue.h"
#include "user_interface.h"
#include "osapi.h"
#include "os_type.h"
#include "mem.h"
#include "proto.h"
uint8_t *last_rb_p_r;
uint8_t *last_rb_p_w;
uint32_t last_fill_cnt;
void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize)
{
queue->buf = (uint8_t*)os_zalloc(bufferSize);
RINGBUF_Init(&queue->rb, queue->buf, bufferSize);
}
int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len)
{
uint32_t ret;
last_rb_p_r = queue->rb.p_r;
last_rb_p_w = queue->rb.p_w;
last_fill_cnt = queue->rb.fill_cnt;
ret = PROTO_AddRb(&queue->rb, buffer, len);
if (ret == -1) {
// rolling ring buffer back
queue->rb.p_r = last_rb_p_r;
queue->rb.p_w = last_rb_p_w;
queue->rb.fill_cnt = last_fill_cnt;
}
return ret;
}
int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen)
{
return PROTO_ParseRb(&queue->rb, buffer, len, maxLen);
}
bool ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue)
{
if (queue->rb.fill_cnt <= 0)
return TRUE;
return FALSE;
}

View File

@ -1,44 +0,0 @@
/* str_queue.h --
*
* Copyright (c) 2014-2015, Tuan PM <tuanpm at live dot com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Redis nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef USER_QUEUE_H_
#define USER_QUEUE_H_
#include "os_type.h"
#include "ringbuf.h"
typedef struct {
uint8_t *buf;
RINGBUF rb;
} QUEUE;
void ICACHE_FLASH_ATTR QUEUE_Init(QUEUE *queue, int bufferSize);
int32_t ICACHE_FLASH_ATTR QUEUE_Puts(QUEUE *queue, uint8_t* buffer, uint16_t len);
int32_t ICACHE_FLASH_ATTR QUEUE_Gets(QUEUE *queue, uint8_t* buffer, uint16_t* len, uint16_t maxLen);
bool ICACHE_FLASH_ATTR QUEUE_IsEmpty(QUEUE *queue);
#endif /* USER_QUEUE_H_ */

View File

@ -1,67 +0,0 @@
/**
* \file
* Ring Buffer library
*/
#include "ringbuf.h"
/**
* \brief init a RINGBUF object
* \param r pointer to a RINGBUF object
* \param buf pointer to a byte array
* \param size size of buf
* \return 0 if successfull, otherwise failed
*/
I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size)
{
if (r == NULL || buf == NULL || size < 2) return -1;
r->p_o = r->p_r = r->p_w = buf;
r->fill_cnt = 0;
r->size = size;
return 0;
}
/**
* \brief put a character into ring buffer
* \param r pointer to a ringbuf object
* \param c character to be put
* \return 0 if successfull, otherwise failed
*/
I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c)
{
if (r->fill_cnt >= r->size)return -1; // ring buffer is full, this should be atomic operation
r->fill_cnt++; // increase filled slots count, this should be atomic operation
*r->p_w++ = c; // put character into buffer
if (r->p_w >= r->p_o + r->size) // rollback if write pointer go pass
r->p_w = r->p_o; // the physical boundary
return 0;
}
/**
* \brief get a character from ring buffer
* \param r pointer to a ringbuf object
* \param c read character
* \return 0 if successfull, otherwise failed
*/
I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c)
{
if (r->fill_cnt <= 0)return -1; // ring buffer is empty, this should be atomic operation
r->fill_cnt--; // decrease filled slots count
*c = *r->p_r++; // get the character out
if (r->p_r >= r->p_o + r->size) // rollback if write pointer go pass
r->p_r = r->p_o; // the physical boundary
return 0;
}

View File

@ -1,19 +0,0 @@
#ifndef _RING_BUF_H_
#define _RING_BUF_H_
#include <os_type.h>
#include <stdlib.h>
#include "typedef.h"
typedef struct {
U8* p_o; /**< Original pointer */
U8* volatile p_r; /**< Read pointer */
U8* volatile p_w; /**< Write pointer */
volatile I32 fill_cnt; /**< Number of filled slots */
I32 size; /**< Buffer size */
} RINGBUF;
I16 ICACHE_FLASH_ATTR RINGBUF_Init(RINGBUF *r, U8* buf, I32 size);
I16 ICACHE_FLASH_ATTR RINGBUF_Put(RINGBUF *r, U8 c);
I16 ICACHE_FLASH_ATTR RINGBUF_Get(RINGBUF *r, U8* c);
#endif

View File

@ -1,17 +0,0 @@
/**
* \file
* Standard Types definition
*/
#ifndef _TYPE_DEF_H_
#define _TYPE_DEF_H_
typedef char I8;
typedef unsigned char U8;
typedef short I16;
typedef unsigned short U16;
typedef long I32;
typedef unsigned long U32;
typedef unsigned long long U64;
#endif

View File

@ -1,15 +0,0 @@
#ifndef __MQTT_CONFIG_H__
#define __MQTT_CONFIG_H__
//#define MQTT_SSL_ENABLE
#define MQTT_RECONNECT_TIMEOUT 5 /*second*/
//#define MQTT_BUF_SIZE 1024
#define MQTT_BUF_SIZE 512
#define QUEUE_BUFFER_SIZE 2048
//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/
#endif // __MQTT_CONFIG_H__

View File

@ -1,149 +0,0 @@
/*
* Copyright (c) 2014, Tuan PM
* Email: tuanpm@live.com
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stddef.h>
#include "utils.h"
uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str)
{
uint8_t segs = 0; /* Segment count. */
uint8_t chcnt = 0; /* Character count within segment. */
uint8_t accum = 0; /* Accumulator for segment. */
/* Catch NULL pointer. */
if (str == 0)
return 0;
/* Process every character in string. */
while (*str != '\0') {
/* Segment changeover. */
if (*str == '.') {
/* Must have some digits in segment. */
if (chcnt == 0)
return 0;
/* Limit number of segments. */
if (++segs == 4)
return 0;
/* Reset segment values and restart loop. */
chcnt = accum = 0;
str++;
continue;
}
/* Check numeric. */
if ((*str < '0') || (*str > '9'))
return 0;
/* Accumulate and check segment. */
if ((accum = accum * 10 + *str - '0') > 255)
return 0;
/* Advance other segment specific stuff and continue loop. */
chcnt++;
str++;
}
/* Check enough segments and enough characters in last segment. */
if (segs != 3)
return 0;
if (chcnt == 0)
return 0;
/* Address okay. */
return 1;
}
uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip)
{
/* The count of the number of bytes processed. */
int i;
/* A pointer to the next digit to process. */
const char * start;
start = str;
for (i = 0; i < 4; i++) {
/* The digit being processed. */
char c;
/* The value of this byte. */
int n = 0;
while (1) {
c = * start;
start++;
if (c >= '0' && c <= '9') {
n *= 10;
n += c - '0';
}
/* We insist on stopping at "." if we are still parsing
the first, second, or third numbers. If we have reached
the end of the numbers, we will allow any character. */
else if ((i < 3 && c == '.') || i == 3) {
break;
}
else {
return 0;
}
}
if (n >= 256) {
return 0;
}
((uint8_t*)ip)[i] = n;
}
return 1;
}
uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s)
{
uint32_t value = 0, digit;
int8_t c;
while ((c = *s++)) {
if ('0' <= c && c <= '9')
digit = c - '0';
else if ('A' <= c && c <= 'F')
digit = c - 'A' + 10;
else if ('a' <= c && c <= 'f')
digit = c - 'a' + 10;
else break;
value = (value << 4) | digit;
}
return value;
}

View File

@ -1,9 +0,0 @@
#ifndef _UTILS_H_
#define _UTILS_H_
#include "c_types.h"
uint32_t ICACHE_FLASH_ATTR UTILS_Atoh(const int8_t *s);
uint8_t ICACHE_FLASH_ATTR UTILS_StrToIP(const int8_t* str, void *ip);
uint8_t ICACHE_FLASH_ATTR UTILS_IsIPV4 (int8_t *str);
#endif

View File

@ -1,7 +0,0 @@
[Makefile]
indent_style = tab
indent_size = 4
[src/*.h,src/*.cpp,examples/**.ino]
indent_style = space
indent_size = 2

View File

@ -1,2 +0,0 @@
.DS_Store
cmake-build-debug/

View File

@ -1,46 +0,0 @@
language: generic
env:
global:
- IDE_VERSION=1.8.7
matrix:
- EXAMPLE="AdafruitHuzzahESP8266" BOARD="esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80"
- EXAMPLE="AdafruitHuzzahESP8266Secure" BOARD="esp8266:esp8266:huzzah:FlashSize=4M3M,CpuFrequency=80"
- EXAMPLE="ArduinoEthernetShield" BOARD="arduino:avr:uno"
- EXAMPLE="ArduinoMKRGSM1400" BOARD="arduino:samd:mkrgsm1400"
- EXAMPLE="ArduinoMKRGSM1400Secure" BOARD="arduino:samd:mkrgsm1400"
- EXAMPLE="ArduinoWiFi101Secure" BOARD="arduino:avr:uno"
- EXAMPLE="ArduinoWiFiShield" BOARD="arduino:avr:uno"
- EXAMPLE="ArduinoYun" BOARD="arduino:avr:yun"
- EXAMPLE="ArduinoYunSecure" BOARD="arduino:avr:yun"
- EXAMPLE="ESP32DevelopmentBoard" BOARD="espressif:esp32:esp32:FlashFreq=80"
- EXAMPLE="ESP32DevelopmentBoardSecure" BOARD="espressif:esp32:esp32:FlashFreq=80"
before_install:
- /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
- sleep 3
- export DISPLAY=:1.0
- wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz
- tar xf arduino-$IDE_VERSION-linux64.tar.xz
- mv arduino-$IDE_VERSION ~/arduino-ide
- export PATH=$PATH:~/arduino-ide
- if [[ "$BOARD" =~ "esp8266:esp8266:" ]]; then
arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --install-boards esp8266:esp8266;
arduino --pref "boardsmanager.additional.urls=" --save-prefs;
fi
- if [[ "$BOARD" =~ "espressif:esp32:" ]]; then
mkdir -p ~/Arduino/hardware/espressif &&
cd ~/Arduino/hardware/espressif &&
git clone https://github.com/espressif/arduino-esp32.git esp32 &&
cd esp32/tools/ &&
python get.py &&
cd $TRAVIS_BUILD_DIR;
fi
- if [[ "$BOARD" =~ "arduino:samd:mkrgsm1400" ]]; then
arduino --install-boards arduino:samd;
arduino --install-library MKRGSM;
fi
- arduino --install-library WiFi101
install:
- mkdir -p ~/Arduino/libraries
- ln -s $PWD ~/Arduino/libraries/.
script:
- arduino --verbose-build --verify --board $BOARD $PWD/examples/$EXAMPLE/$EXAMPLE.ino;

View File

@ -1,38 +0,0 @@
# Uncompilable CMake File to enable project editing with CLion IDE
cmake_minimum_required(VERSION 2.8.4)
project(arduino-mqtt)
include_directories(
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/
/Users/256dpi/Development/Arduino/libraries/Ethernet/src
/Users/256dpi/Development/Arduino/libraries/WiFi101/src
/Users/256dpi/Development/Arduino/libraries/MKRGSM/src
/Applications/Arduino.app/Contents/Java/libraries/Bridge/src
/Users/256dpi/Library/Arduino15/packages/esp8266/hardware/esp8266/2.3.0/libraries/ESP8266WiFi/src
/Users/256dpi/Library/Arduino15/packages/esp32/libraries/WiFi/src
/Users/256dpi/Library/Arduino15/packages/esp32/libraries/WiFiClientSecure/src
src/)
include_directories(src/)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES
examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino
examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino
examples/ArduinoEthernetShield/ArduinoEthernetShield.ino
examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino
examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino
examples/ArduinoWiFi101/ArduinoWiFi101.ino
examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino
examples/ArduinoWiFiShield/ArduinoWiFiShield.ino
examples/ArduinoYun/ArduinoYun.ino
examples/ArduinoYunSecure/ArduinoYunSecure.ino
examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino
examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino
src/lwmqtt
src/MQTT.h
src/MQTTClient.h)
add_executable(arduino-mqtt ${SOURCE_FILES})

View File

@ -1,14 +0,0 @@
all: fmt
fmt:
clang-format -i src/*.h -style="{BasedOnStyle: Google, ColumnLimit: 120}"
update:
rm -rf ./lwmqtt
git clone --branch v0.6.2 https://github.com/256dpi/lwmqtt.git ./lwmqtt
mkdir -p ./src/lwmqtt
cp -r ./lwmqtt/src/*.c ./src/lwmqtt/
cp -r ./lwmqtt/src/*.h ./src/lwmqtt/
cp -r ./lwmqtt/include/*.h ./src/lwmqtt/
rm -rf ./lwmqtt
sed -i '' "s/<lwmqtt.h>/\"lwmqtt.h\"/g" ./src/lwmqtt/*

View File

@ -1,226 +0,0 @@
# arduino-mqtt
[![Build Status](https://travis-ci.org/256dpi/arduino-mqtt.svg?branch=master)](https://travis-ci.org/256dpi/arduino-mqtt)
[![GitHub release](https://img.shields.io/github/release/256dpi/arduino-mqtt.svg)](https://github.com/256dpi/arduino-mqtt/releases)
This library bundles the [lwmqtt](https://github.com/256dpi/lwmqtt) MQTT 3.1.1 client and adds a thin wrapper to get an Arduino like API.
Download the latest version from the [release](https://github.com/256dpi/arduino-mqtt/releases) section. Or even better use the builtin Library Manager in the Arduino IDE and search for "MQTT".
The library is also available on [PlatformIO](https://platformio.org/lib/show/617/MQTT). You can install it by running: `pio lib install "MQTT"`.
## Compatibility
The following examples show how you can use the library with various Arduino compatible hardware:
- [Arduino Yun & Yun-Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYun/ArduinoYun.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoYunSecure/ArduinoYunSecure.ino))
- [Arduino Ethernet Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoEthernetShield/ArduinoEthernetShield.ino)
- [Arduino WiFi Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFiShield/ArduinoWiFiShield.ino)
- [Adafruit HUZZAH ESP8266](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266/AdafruitHuzzahESP8266.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/AdafruitHuzzahESP8266Secure/AdafruitHuzzahESP8266Secure.ino))
- [Arduino/Genuino WiFi101 Shield](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101/ArduinoWiFi101.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoWiFi101Secure/ArduinoWiFi101Secure.ino))
- [Arduino MKR GSM 1400](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400/ArduinoMKRGSM1400.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ArduinoMKRGSM1400Secure/ArduinoMKRGSM1400Secure.ino))
- [ESP32 Development Board](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoard/ESP32DevelopmentBoard.ino) ([Secure](https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino))
Other shields and boards should also work if they provide a [Client](https://www.arduino.cc/en/Reference/ClientConstructor) based network implementation.
## Notes
- The maximum size for packets being published and received is set by default to 128 bytes. To change the buffer sizes, you need to use `MQTTClient client(256)` instead of just `MQTTClient client` on the top of your sketch. The passed value denotes the read and write buffer size.
- On the ESP8266 it has been reported that an additional `delay(10);` after `client.loop();` fixes many stability issues with WiFi connections.
- To use the library with shiftr.io, you need to provide the token key (username) and token secret (password) as the second and third argument to `client.connect(name, key, secret)`.
## Example
The following example uses an Arduino MKR1000 to connect to shiftr.io. You can check on your device after a successful connection here: https://shiftr.io/try.
```c++
#include <SPI.h>
#include <WiFi101.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}
```
## API
Initialize the object using the hostname of the broker, the brokers port (default: `1883`) and the underlying Client class for network transport:
```c++
void begin(const char hostname[], Client &client);
void begin(const char hostname[], int port, Client &client);
```
- Specify port `8883` when using secure clients for encrypted connections.
- Local domain names (e.g. `Computer.local` on OSX) are not supported by Arduino. You need to set the IP address directly.
The hostname and port can also be changed after calling `begin()`:
```c++
void setHost(const char hostname[]);
void setHost(const char hostname[], int port);
```
Set a will message (last testament) that gets registered on the broker after connecting. `setWill()` has to be called before calling `connect()`:
```c++
void setWill(const char topic[]);
void setWill(const char topic[], const char payload[]);
void setWill(const char topic[], const char payload[], bool retained, int qos);
void clearWill();
```
Register a callback to receive messages:
```c++
void onMessage(MQTTClientCallbackSimple);
// Callback signature: void messageReceived(String &topic, String &payload) {}
void onMessageAdvanced(MQTTClientCallbackAdvanced);
// Callback signature: void messageReceived(MQTTClient *client, char topic[], char payload[], int payload_length) {}
```
- The set callback is mostly called during a call to `loop()` but may also be called during a call to `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` if messages have been received before receiving the required acknowledgement. Therefore, it is strongly recommended to not call `subscribe()`, `unsubscribe()` or `publish() // QoS > 0` directly in the callback.
Set more advanced options:
```c++
void setOptions(int keepAlive, bool cleanSession, int timeout);
```
- The `keepAlive` option controls the keep alive interval in seconds (default: 10).
- The `cleanSession` option controls the session retention on the broker side (default: true).
- The `timeout` option controls the default timeout for all commands in milliseconds (default: 1000).
Connect to broker using the supplied client id and an optional username and password:
```c++
bool connect(const char clientId[], bool skip = false);
bool connect(const char clientId[], const char username[], bool skip = false);
bool connect(const char clientId[], const char username[], const char password[], bool skip = false);
```
- If the `skip` option is set to true, the client will skip the network level connection and jump to the MQTT level connection. This option can be used in order to establish and verify TLS connections manually before giving control to the MQTT client.
- This functions returns a boolean that indicates if the connection has been established successfully.
Publishes a message to the broker with an optional payload:
```c++
bool publish(const String &topic);
bool publish(const char topic[]);
bool publish(const String &topic, const String &payload);
bool publish(const String &topic, const String &payload, bool retained, int qos);
bool publish(const char topic[], const String &payload);
bool publish(const char topic[], const String &payload, bool retained, int qos);
bool publish(const char topic[], const char payload[]);
bool publish(const char topic[], const char payload[], bool retained, int qos);
bool publish(const char topic[], const char payload[], int length);
bool publish(const char topic[], const char payload[], int length, bool retained, int qos);
```
Subscribe to a topic:
```c++
bool subscribe(const String &topic);
bool subscribe(const String &topic, int qos);
bool subscribe(const char topic[]);
bool subscribe(const char topic[], int qos);
```
Unsubscribe from a topic:
```c++
bool unsubscribe(const String &topic);
bool unsubscribe(const char topic[]);
```
Sends and receives packets:
```c++
bool loop();
```
- This function should be called in every `loop`.
Check if the client is currently connected:
```c++
bool connected();
```
Access low-level information for debugging:
```c++
lwmqtt_err_t lastError();
lwmqtt_return_code_t returnCode();
```
- The error codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L11).
- The return codes can be found [here](https://github.com/256dpi/lwmqtt/blob/master/include/lwmqtt.h#L243).
Disconnect from the broker:
```c++
bool disconnect();
```
## Release Management
- Update version in `library.properties`.
- Create release on GitHub.

View File

@ -1,69 +0,0 @@
// This example uses an Adafruit Huzzah ESP8266
// to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <ESP8266WiFi.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
delay(10); // <- fixes some issues with WiFi stability
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,71 +0,0 @@
// This example uses an Adafruit Huzzah ESP8266
// to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <ESP8266WiFi.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClientSecure net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
//
// MQTT brokers usually use port 8883 for secure connections.
client.begin("broker.shiftr.io", 8883, net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
delay(10); // <- fixes some issues with WiFi stability
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,62 +0,0 @@
// This example uses an Arduino Uno together with
// an Ethernet Shield to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <Ethernet.h>
#include <MQTT.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte ip[] = {192, 168, 1, 177}; // <- change to match your network
EthernetClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
Ethernet.begin(mac, ip);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,84 +0,0 @@
// This example uses an Arduino MKR GSM 1400 board
// to connect to shiftr.io.
//
// IMPORTANT: This example uses the new MKRGSM library.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Sandeep Mistry
// https://github.com/256dpi/arduino-mqtt
#include <MKRGSM.h>
#include <MQTT.h>
const char pin[] = "";
const char apn[] = "apn";
const char login[] = "login";
const char password[] = "password";
GSMClient net;
GPRS gprs;
GSM gsmAccess;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
// connection state
bool connected = false;
Serial.print("connecting to cellular network ...");
// After starting the modem with gsmAccess.begin()
// attach to the GPRS network with the APN, login and password
while (!connected) {
if ((gsmAccess.begin(pin) == GSM_READY) &&
(gprs.attachGPRS(apn, login, password) == GPRS_READY)) {
connected = true;
} else {
Serial.print(".");
delay(1000);
}
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,86 +0,0 @@
// This example uses an Arduino MKR GSM 1400 board
// to securely connect to shiftr.io.
//
// IMPORTANT: This example uses the new MKRGSM library.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Sandeep Mistry
// https://github.com/256dpi/arduino-mqtt
#include <MKRGSM.h>
#include <MQTT.h>
const char pin[] = "";
const char apn[] = "apn";
const char login[] = "login";
const char password[] = "password";
GSMSSLClient net;
GPRS gprs;
GSM gsmAccess;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
// connection state
bool connected = false;
Serial.print("connecting to cellular network ...");
// After starting the modem with gsmAccess.begin()
// attach to the GPRS network with the APN, login and password
while (!connected) {
if ((gsmAccess.begin(pin) == GSM_READY) &&
(gprs.attachGPRS(apn, login, password) == GPRS_READY)) {
connected = true;
} else {
Serial.print(".");
delay(1000);
}
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
//
// MQTT brokers usually use port 8883 for secure connections.
client.begin("broker.shiftr.io", 8883, net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,70 +0,0 @@
// This example uses an Arduino/Genuino Zero together with
// a WiFi101 Shield or a MKR1000 to connect to shiftr.io.
//
// IMPORTANT: This example uses the new WiFi101 library.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Gilberto Conti
// https://github.com/256dpi/arduino-mqtt
#include <WiFi101.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,75 +0,0 @@
// This example uses an Arduino/Genuino Zero together with
// a WiFi101 Shield or a MKR1000 to connect to shiftr.io.
//
// IMPORTANT: This example uses the new WiFi101 library.
//
// IMPORTANT: You need to install/update the SSL certificates first:
// https://github.com/arduino-libraries/WiFi101-FirmwareUpdater#to-update-ssl-certificates
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Gilberto Conti
// https://github.com/256dpi/arduino-mqtt
#include <WiFi101.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiSSLClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
//
// MQTT brokers usually use port 8883 for secure connections.
client.begin("broker.shiftr.io", 8883, net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,68 +0,0 @@
// This example uses an Arduino Uno together with
// a WiFi Shield to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <WiFi.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,60 +0,0 @@
// This example uses an Arduino Yun or a Yun-Shield
// and the MQTTClient to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <Bridge.h>
#include <BridgeClient.h>
#include <MQTT.h>
BridgeClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Bridge.begin();
Serial.begin(115200);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,62 +0,0 @@
// This example uses an Arduino Yun or a Yun-Shield
// and the MQTTClient to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <Bridge.h>
#include <BridgeSSLClient.h>
#include <MQTT.h>
BridgeSSLClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("connecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Bridge.begin();
Serial.begin(115200);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
//
// MQTT brokers usually use port 8883 for secure connections.
client.begin("broker.shiftr.io", 8883, net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,69 +0,0 @@
// This example uses an ESP32 Development Board
// to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <WiFi.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
client.begin("broker.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
delay(10); // <- fixes some issues with WiFi stability
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,71 +0,0 @@
// This example uses an ESP32 Development Board
// to connect to shiftr.io.
//
// You can check on your device after a successful
// connection here: https://shiftr.io/try.
//
// by Joël Gähwiler
// https://github.com/256dpi/arduino-mqtt
#include <WiFiClientSecure.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClientSecure net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "try", "try")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("/hello");
// client.unsubscribe("/hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, pass);
// Note: Local domain names (e.g. "Computer.local" on OSX) are not supported by Arduino.
// You need to set the IP address directly.
//
// MQTT brokers usually use port 8883 for secure connections.
client.begin("broker.shiftr.io", 8883, net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
delay(10); // <- fixes some issues with WiFi stability
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}

View File

@ -1,9 +0,0 @@
name=MQTT
version=2.4.0
author=Joel Gaehwiler <joel.gaehwiler@gmail.com>
maintainer=Joel Gaehwiler <joel.gaehwiler@gmail.com>
sentence=MQTT library for Arduino
paragraph=This library bundles the lwmqtt client and adds a thin wrapper to get an Arduino like API.
category=Communication
url=https://github.com/256dpi/arduino-mqtt
architectures=*

View File

@ -1,6 +0,0 @@
#ifndef MQTT_H
#define MQTT_H
#include "MQTTClient.h"
#endif

View File

@ -1,491 +0,0 @@
#ifndef MQTT_CLIENT_H
#define MQTT_CLIENT_H
#include <Arduino.h>
#include <Client.h>
#include <Stream.h>
extern "C" {
#include "lwmqtt/lwmqtt.h"
};
typedef struct {
uint32_t end;
} lwmqtt_arduino_timer_t;
void lwmqtt_arduino_timer_set(void *ref, uint32_t timeout);
int32_t lwmqtt_arduino_timer_get(void *ref);
typedef struct {
Client *client;
} lwmqtt_arduino_network_t;
void lwmqtt_arduino_timer_set(void *ref, uint32_t timeout) {
// cast timer reference
auto t = (lwmqtt_arduino_timer_t *)ref;
// set future end time
t->end = (uint32_t)(millis() + timeout);
}
int32_t lwmqtt_arduino_timer_get(void *ref) {
// cast timer reference
auto t = (lwmqtt_arduino_timer_t *)ref;
// get difference to end time
return (int32_t)t->end - (int32_t)millis();
}
lwmqtt_err_t lwmqtt_arduino_network_read(void *ref, uint8_t *buffer, size_t len, size_t *read, uint32_t timeout) {
// cast network reference
auto n = (lwmqtt_arduino_network_t *)ref;
// set timeout
n->client->setTimeout(timeout);
// read bytes
*read = n->client->readBytes(buffer, len);
if (*read <= 0) {
return LWMQTT_NETWORK_FAILED_READ;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_arduino_network_write(void *ref, uint8_t *buffer, size_t len, size_t *sent, uint32_t /*timeout*/) {
// cast network reference
auto n = (lwmqtt_arduino_network_t *)ref;
// write bytes
*sent = n->client->write(buffer, len);
if (*sent <= 0) {
return LWMQTT_NETWORK_FAILED_WRITE;
};
return LWMQTT_SUCCESS;
}
class MQTTClient;
typedef void (*MQTTClientCallbackSimple)(String &topic, String &payload);
typedef void (*MQTTClientCallbackAdvanced)(MQTTClient *client, char topic[], char bytes[], int length);
typedef struct {
MQTTClient *client = nullptr;
MQTTClientCallbackSimple simple = nullptr;
MQTTClientCallbackAdvanced advanced = nullptr;
} MQTTClientCallback;
static void MQTTClientHandler(lwmqtt_client_t * /*client*/, void *ref, lwmqtt_string_t topic,
lwmqtt_message_t message) {
// get callback
auto cb = (MQTTClientCallback *)ref;
// null terminate topic
char terminated_topic[topic.len + 1];
memcpy(terminated_topic, topic.data, topic.len);
terminated_topic[topic.len] = '\0';
// null terminate payload if available
if (message.payload != nullptr) {
message.payload[message.payload_len] = '\0';
}
// call the advanced callback and return if available
if (cb->advanced != nullptr) {
cb->advanced(cb->client, terminated_topic, (char *)message.payload, (int)message.payload_len);
return;
}
// return if simple callback is not set
if (cb->simple == nullptr) {
return;
}
// create topic string
String str_topic = String(terminated_topic);
// create payload string
String str_payload;
if (message.payload != nullptr) {
str_payload = String((const char *)message.payload);
}
// call simple callback
cb->simple(str_topic, str_payload);
}
class MQTTClient {
private:
size_t bufSize = 0;
uint8_t *readBuf = nullptr;
uint8_t *writeBuf = nullptr;
uint16_t keepAlive = 10;
bool cleanSession = true;
uint32_t timeout = 1000;
Client *netClient = nullptr;
const char *hostname = nullptr;
int port = 0;
lwmqtt_will_t *will = nullptr;
MQTTClientCallback callback;
lwmqtt_arduino_network_t network = {nullptr};
lwmqtt_arduino_timer_t timer1 = {0};
lwmqtt_arduino_timer_t timer2 = {0};
lwmqtt_client_t client = {0};
bool _connected = false;
lwmqtt_return_code_t _returnCode = (lwmqtt_return_code_t)0;
lwmqtt_err_t _lastError = (lwmqtt_err_t)0;
public:
explicit MQTTClient(int bufSize = 128) {
// reset client
memset(&this->client, 0, sizeof(lwmqtt_client_t));
// allocate buffers
this->bufSize = (size_t)bufSize;
this->readBuf = (uint8_t *)malloc((size_t)bufSize + 1);
this->writeBuf = (uint8_t *)malloc((size_t)bufSize);
}
~MQTTClient() {
// free will
this->clearWill();
// free hostname
if (this->hostname != nullptr) {
free((void *)this->hostname);
}
// free buffers
free(this->readBuf);
free(this->writeBuf);
}
void begin(const char hostname[], Client &client) { this->begin(hostname, 1883, client); }
void begin(const char hostname[], int port, Client &client) {
// set hostname and port
this->setHost(hostname, port);
// set client
this->netClient = &client;
// initialize client
lwmqtt_init(&this->client, this->writeBuf, this->bufSize, this->readBuf, this->bufSize);
// set timers
lwmqtt_set_timers(&this->client, &this->timer1, &this->timer2, lwmqtt_arduino_timer_set, lwmqtt_arduino_timer_get);
// set network
lwmqtt_set_network(&this->client, &this->network, lwmqtt_arduino_network_read, lwmqtt_arduino_network_write);
// set callback
lwmqtt_set_callback(&this->client, (void *)&this->callback, MQTTClientHandler);
}
void onMessage(MQTTClientCallbackSimple cb) {
// set callback
this->callback.client = this;
this->callback.simple = cb;
this->callback.advanced = nullptr;
}
void onMessageAdvanced(MQTTClientCallbackAdvanced cb) {
// set callback
this->callback.client = this;
this->callback.simple = nullptr;
this->callback.advanced = cb;
}
void setHost(const char hostname[]) { this->setHost(hostname, 1883); }
void setHost(const char hostname[], int port) {
// free hostname if set
if (this->hostname != nullptr) {
free((void *)this->hostname);
}
// set hostname and port
this->hostname = strdup(hostname);
this->port = port;
}
void setWill(const char topic[]) { this->setWill(topic, ""); }
void setWill(const char topic[], const char payload[]) { this->setWill(topic, payload, false, 0); }
void setWill(const char topic[], const char payload[], bool retained, int qos) {
// return if topic is missing
if (topic == nullptr || strlen(topic) == 0) {
return;
}
// clear existing will
this->clearWill();
// allocate will
this->will = (lwmqtt_will_t *)malloc(sizeof(lwmqtt_will_t));
memset(this->will, 0, sizeof(lwmqtt_will_t));
// set topic
this->will->topic = lwmqtt_string(strdup(topic));
// set payload if available
if (payload != nullptr && strlen(payload) > 0) {
this->will->payload = lwmqtt_string(strdup(payload));
}
// set flags
this->will->retained = retained;
this->will->qos = (lwmqtt_qos_t)qos;
}
void clearWill() {
// return if not set
if (this->will == nullptr) {
return;
}
// free payload if set
if (this->will->payload.len > 0) {
free(this->will->payload.data);
}
// free topic if set
if (this->will->topic.len > 0) {
free(this->will->topic.data);
}
// free will
free(this->will);
this->will = nullptr;
}
void setOptions(int keepAlive, bool cleanSession, int timeout) {
// set new options
this->keepAlive = (uint16_t)keepAlive;
this->cleanSession = cleanSession;
this->timeout = (uint32_t)timeout;
}
bool connect(const char clientId[], bool skip = false) { return this->connect(clientId, nullptr, nullptr); }
bool connect(const char clientId[], const char username[], bool skip = false) { return this->connect(clientId, username, nullptr); }
bool connect(const char clientId[], const char username[], const char password[], bool skip = false) {
// close left open connection if still connected
if (!skip && this->connected()) {
this->close();
}
// save client
this->network.client = this->netClient;
// connect to hostg
if(!skip) {
int ret = this->netClient->connect(this->hostname, (uint16_t)this->port);
if (ret <= 0) {
return false;
}
}
// prepare options
lwmqtt_options_t options = lwmqtt_default_options;
options.keep_alive = this->keepAlive;
options.clean_session = this->cleanSession;
options.client_id = lwmqtt_string(clientId);
// set username and password if available
if (username != nullptr) {
options.username = lwmqtt_string(username);
if (password != nullptr) {
options.password = lwmqtt_string(password);
}
}
// connect to broker
this->_lastError = lwmqtt_connect(&this->client, options, this->will, &this->_returnCode, this->timeout);
if (this->_lastError != LWMQTT_SUCCESS) {
// close connection
this->close();
return false;
}
// set flag
this->_connected = true;
return true;
}
bool publish(const String &topic) { return this->publish(topic.c_str(), ""); }
bool publish(const char topic[]) { return this->publish(topic, ""); }
bool publish(const String &topic, const String &payload) { return this->publish(topic.c_str(), payload.c_str()); }
bool publish(const String &topic, const String &payload, bool retained, int qos) {
return this->publish(topic.c_str(), payload.c_str(), retained, qos);
}
bool publish(const char topic[], const String &payload) { return this->publish(topic, payload.c_str()); }
bool publish(const char topic[], const String &payload, bool retained, int qos) {
return this->publish(topic, payload.c_str(), retained, qos);
}
bool publish(const char topic[], const char payload[]) {
return this->publish(topic, (char *)payload, (int)strlen(payload));
}
bool publish(const char topic[], const char payload[], bool retained, int qos) {
return this->publish(topic, (char *)payload, (int)strlen(payload), retained, qos);
}
bool publish(const char topic[], const char payload[], int length) {
return this->publish(topic, payload, length, false, 0);
}
bool publish(const char topic[], const char payload[], int length, bool retained, int qos) {
// return immediately if not connected
if (!this->connected()) {
return false;
}
// prepare message
lwmqtt_message_t message = lwmqtt_default_message;
message.payload = (uint8_t *)payload;
message.payload_len = (size_t)length;
message.retained = retained;
message.qos = lwmqtt_qos_t(qos);
// publish message
this->_lastError = lwmqtt_publish(&this->client, lwmqtt_string(topic), message, this->timeout);
if (this->_lastError != LWMQTT_SUCCESS) {
// close connection
this->close();
return false;
}
return true;
}
bool subscribe(const String &topic) { return this->subscribe(topic.c_str()); }
bool subscribe(const String &topic, int qos) { return this->subscribe(topic.c_str(), qos); }
bool subscribe(const char topic[]) { return this->subscribe(topic, 0); }
bool subscribe(const char topic[], int qos) {
// return immediately if not connected
if (!this->connected()) {
return false;
}
// subscribe to topic
this->_lastError = lwmqtt_subscribe_one(&this->client, lwmqtt_string(topic), (lwmqtt_qos_t)qos, this->timeout);
if (this->_lastError != LWMQTT_SUCCESS) {
// close connection
this->close();
return false;
}
return true;
}
bool unsubscribe(const String &topic) { return this->unsubscribe(topic.c_str()); }
bool unsubscribe(const char topic[]) {
// return immediately if not connected
if (!this->connected()) {
return false;
}
// unsubscribe from topic
this->_lastError = lwmqtt_unsubscribe_one(&this->client, lwmqtt_string(topic), this->timeout);
if (this->_lastError != LWMQTT_SUCCESS) {
// close connection
this->close();
return false;
}
return true;
}
bool loop() {
// return immediately if not connected
if (!this->connected()) {
return false;
}
// get available bytes on the network
auto available = (size_t)this->netClient->available();
// yield if data is available
if (available > 0) {
this->_lastError = lwmqtt_yield(&this->client, available, this->timeout);
if (this->_lastError != LWMQTT_SUCCESS) {
// close connection
this->close();
return false;
}
}
// keep the connection alive
this->_lastError = lwmqtt_keep_alive(&this->client, this->timeout);
if (this->_lastError != LWMQTT_SUCCESS) {
// close connection
this->close();
return false;
}
return true;
}
bool connected() {
// a client is connected if the network is connected, a client is available and
// the connection has been properly initiated
return this->netClient != nullptr && this->netClient->connected() == 1 && this->_connected;
}
lwmqtt_err_t lastError() { return this->_lastError; }
lwmqtt_return_code_t returnCode() { return this->_returnCode; }
bool disconnect() {
// return immediately if not connected anymore
if (!this->connected()) {
return false;
}
// cleanly disconnect
this->_lastError = lwmqtt_disconnect(&this->client, this->timeout);
// close
this->close();
return this->_lastError == LWMQTT_SUCCESS;
}
private:
void close() {
// set flag
this->_connected = false;
// close network
this->netClient->stop();
}
};
#endif

View File

@ -1,618 +0,0 @@
#include "packet.h"
void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf,
size_t read_buf_size) {
client->last_packet_id = 1;
client->keep_alive_interval = 0;
client->pong_pending = false;
client->write_buf = write_buf;
client->write_buf_size = write_buf_size;
client->read_buf = read_buf;
client->read_buf_size = read_buf_size;
client->callback = NULL;
client->callback_ref = NULL;
client->network = NULL;
client->network_read = NULL;
client->network_write = NULL;
client->keep_alive_timer = NULL;
client->command_timer = NULL;
client->timer_set = NULL;
client->timer_get = NULL;
}
void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write) {
client->network = ref;
client->network_read = read;
client->network_write = write;
}
void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set,
lwmqtt_timer_get_t get) {
client->keep_alive_timer = keep_alive_timer;
client->command_timer = command_timer;
client->timer_set = set;
client->timer_get = get;
client->timer_set(client->keep_alive_timer, 0);
client->timer_set(client->command_timer, 0);
}
void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb) {
client->callback_ref = ref;
client->callback = cb;
}
static uint16_t lwmqtt_get_next_packet_id(lwmqtt_client_t *client) {
// check overflow
if (client->last_packet_id == 65535) {
client->last_packet_id = 1;
return 1;
}
// increment packet id
client->last_packet_id++;
return client->last_packet_id;
}
static lwmqtt_err_t lwmqtt_read_from_network(lwmqtt_client_t *client, size_t offset, size_t len) {
// check read buffer capacity
if (client->read_buf_size < offset + len) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// prepare counter
size_t read = 0;
// read while data is missing
while (read < len) {
// check remaining time
int32_t remaining_time = client->timer_get(client->command_timer);
if (remaining_time <= 0) {
return LWMQTT_NETWORK_TIMEOUT;
}
// read
size_t partial_read = 0;
lwmqtt_err_t err = client->network_read(client->network, client->read_buf + offset + read, len - read,
&partial_read, (uint32_t)remaining_time);
if (err != LWMQTT_SUCCESS) {
return err;
}
// increment counter
read += partial_read;
}
return LWMQTT_SUCCESS;
}
static lwmqtt_err_t lwmqtt_write_to_network(lwmqtt_client_t *client, size_t offset, size_t len) {
// prepare counter
size_t written = 0;
// write while data is left
while (written < len) {
// check remaining time
int32_t remaining_time = client->timer_get(client->command_timer);
if (remaining_time <= 0) {
return LWMQTT_NETWORK_TIMEOUT;
}
// write
size_t partial_write = 0;
lwmqtt_err_t err = client->network_write(client->network, client->write_buf + offset + written, len - written,
&partial_write, (uint32_t)remaining_time);
if (err != LWMQTT_SUCCESS) {
return err;
}
// increment counter
written += partial_write;
}
return LWMQTT_SUCCESS;
}
static lwmqtt_err_t lwmqtt_read_packet_in_buffer(lwmqtt_client_t *client, size_t *read,
lwmqtt_packet_type_t *packet_type) {
// preset packet type
*packet_type = LWMQTT_NO_PACKET;
// read or wait for header byte
lwmqtt_err_t err = lwmqtt_read_from_network(client, 0, 1);
if (err == LWMQTT_NETWORK_TIMEOUT) {
// this is ok as no data has been read at all
return LWMQTT_SUCCESS;
} else if (err != LWMQTT_SUCCESS) {
return err;
}
// detect packet type
err = lwmqtt_detect_packet_type(client->read_buf, 1, packet_type);
if (err != LWMQTT_SUCCESS) {
return err;
}
// prepare variables
size_t len = 0;
uint32_t rem_len = 0;
do {
// adjust len
len++;
// read next byte
err = lwmqtt_read_from_network(client, len, 1);
if (err != LWMQTT_SUCCESS) {
return err;
}
// attempt to detect remaining length
err = lwmqtt_detect_remaining_length(client->read_buf + 1, len, &rem_len);
} while (err == LWMQTT_BUFFER_TOO_SHORT);
// check final error
if (err != LWMQTT_SUCCESS) {
return err;
}
// read the rest of the buffer if needed
if (rem_len > 0) {
err = lwmqtt_read_from_network(client, 1 + len, rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
}
// adjust counter
*read += 1 + len + rem_len;
return LWMQTT_SUCCESS;
}
static lwmqtt_err_t lwmqtt_send_packet_in_buffer(lwmqtt_client_t *client, size_t length) {
// write to network
lwmqtt_err_t err = lwmqtt_write_to_network(client, 0, length);
if (err != LWMQTT_SUCCESS) {
return err;
}
// reset keep alive timer
client->timer_set(client->keep_alive_timer, client->keep_alive_interval);
return LWMQTT_SUCCESS;
}
static lwmqtt_err_t lwmqtt_cycle(lwmqtt_client_t *client, size_t *read, lwmqtt_packet_type_t *packet_type) {
// read next packet from the network
lwmqtt_err_t err = lwmqtt_read_packet_in_buffer(client, read, packet_type);
if (err != LWMQTT_SUCCESS) {
return err;
} else if (*packet_type == LWMQTT_NO_PACKET) {
return LWMQTT_SUCCESS;
}
switch (*packet_type) {
// handle publish packets
case LWMQTT_PUBLISH_PACKET: {
// decode publish packet
bool dup;
uint16_t packet_id;
lwmqtt_string_t topic;
lwmqtt_message_t msg;
err = lwmqtt_decode_publish(client->read_buf, client->read_buf_size, &dup, &packet_id, &topic, &msg);
if (err != LWMQTT_SUCCESS) {
return err;
}
// call callback if set
if (client->callback != NULL) {
client->callback(client, client->callback_ref, topic, msg);
}
// break early on qos zero
if (msg.qos == LWMQTT_QOS0) {
break;
}
// define ack packet
lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET;
if (msg.qos == LWMQTT_QOS1) {
ack_type = LWMQTT_PUBACK_PACKET;
} else if (msg.qos == LWMQTT_QOS2) {
ack_type = LWMQTT_PUBREC_PACKET;
}
// encode ack packet
size_t len;
err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, ack_type, false, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send ack packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
break;
}
// handle pubrec packets
case LWMQTT_PUBREC_PACKET: {
// decode pubrec packet
bool dup;
uint16_t packet_id;
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREC_PACKET, &dup, &packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// encode pubrel packet
size_t len;
err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBREL_PACKET, 0, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send pubrel packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
break;
}
// handle pubrel packets
case LWMQTT_PUBREL_PACKET: {
// decode pubrec packet
bool dup;
uint16_t packet_id;
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_PUBREL_PACKET, &dup, &packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// encode pubcomp packet
size_t len;
err = lwmqtt_encode_ack(client->write_buf, client->write_buf_size, &len, LWMQTT_PUBCOMP_PACKET, 0, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send pubcomp packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
break;
}
// handle pingresp packets
case LWMQTT_PINGRESP_PACKET: {
// set flag
client->pong_pending = false;
break;
}
// handle all other packets
default: { break; }
}
return LWMQTT_SUCCESS;
}
static lwmqtt_err_t lwmqtt_cycle_until(lwmqtt_client_t *client, lwmqtt_packet_type_t *packet_type, size_t available,
lwmqtt_packet_type_t needle) {
// prepare counter
size_t read = 0;
// loop until timeout has been reached
do {
// do one cycle
lwmqtt_err_t err = lwmqtt_cycle(client, &read, packet_type);
if (err != LWMQTT_SUCCESS) {
return err;
}
// return when one packet has been successfully read when no availability has been given
if (needle == LWMQTT_NO_PACKET && available == 0) {
return LWMQTT_SUCCESS;
}
// otherwise check if needle has been found
if (*packet_type == needle) {
return LWMQTT_SUCCESS;
}
} while (client->timer_get(client->command_timer) > 0 && (available == 0 || read < available));
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout) {
// set command timer
client->timer_set(client->command_timer, timeout);
// cycle until timeout has been reached
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
lwmqtt_err_t err = lwmqtt_cycle_until(client, &packet_type, available, LWMQTT_NO_PACKET);
if (err != LWMQTT_SUCCESS) {
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will,
lwmqtt_return_code_t *return_code, uint32_t timeout) {
// set command timer
client->timer_set(client->command_timer, timeout);
// save keep alive interval (take 75% to be a little earlier than actually needed)
client->keep_alive_interval = (uint32_t)(options.keep_alive * 750);
// set keep alive timer
client->timer_set(client->keep_alive_timer, client->keep_alive_interval);
// reset pong pending flag
client->pong_pending = false;
// initialize return code
*return_code = LWMQTT_UNKNOWN_RETURN_CODE;
// encode connect packet
size_t len;
lwmqtt_err_t err = lwmqtt_encode_connect(client->write_buf, client->write_buf_size, &len, options, will);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// wait for connack packet
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_CONNACK_PACKET);
if (err != LWMQTT_SUCCESS) {
return err;
} else if (packet_type != LWMQTT_CONNACK_PACKET) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// decode connack packet
bool session_present;
err = lwmqtt_decode_connack(client->read_buf, client->read_buf_size, &session_present, return_code);
if (err != LWMQTT_SUCCESS) {
return err;
}
// return error if connection was not accepted
if (*return_code != LWMQTT_CONNECTION_ACCEPTED) {
return LWMQTT_CONNECTION_DENIED;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos,
uint32_t timeout) {
// set command timer
client->timer_set(client->command_timer, timeout);
// encode subscribe packet
size_t len;
lwmqtt_err_t err = lwmqtt_encode_subscribe(client->write_buf, client->write_buf_size, &len,
lwmqtt_get_next_packet_id(client), count, topic_filter, qos);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// wait for suback packet
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_SUBACK_PACKET);
if (err != LWMQTT_SUCCESS) {
return err;
} else if (packet_type != LWMQTT_SUBACK_PACKET) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// decode packet
int suback_count = 0;
lwmqtt_qos_t granted_qos[count];
uint16_t packet_id;
err = lwmqtt_decode_suback(client->read_buf, client->read_buf_size, &packet_id, count, &suback_count, granted_qos);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check suback codes
for (int i = 0; i < suback_count; i++) {
if (granted_qos[i] == LWMQTT_QOS_FAILURE) {
return LWMQTT_FAILED_SUBSCRIPTION;
}
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos,
uint32_t timeout) {
return lwmqtt_subscribe(client, 1, &topic_filter, &qos, timeout);
}
lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout) {
// set command timer
client->timer_set(client->command_timer, timeout);
// encode unsubscribe packet
size_t len;
lwmqtt_err_t err = lwmqtt_encode_unsubscribe(client->write_buf, client->write_buf_size, &len,
lwmqtt_get_next_packet_id(client), count, topic_filter);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send unsubscribe packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// wait for unsuback packet
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
err = lwmqtt_cycle_until(client, &packet_type, 0, LWMQTT_UNSUBACK_PACKET);
if (err != LWMQTT_SUCCESS) {
return err;
} else if (packet_type != LWMQTT_UNSUBACK_PACKET) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// decode unsuback packet
bool dup;
uint16_t packet_id;
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, LWMQTT_UNSUBACK_PACKET, &dup, &packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout) {
return lwmqtt_unsubscribe(client, 1, &topic_filter, timeout);
}
lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t message,
uint32_t timeout) {
// set command timer
client->timer_set(client->command_timer, timeout);
// add packet id if at least qos 1
uint16_t packet_id = 0;
if (message.qos == LWMQTT_QOS1 || message.qos == LWMQTT_QOS2) {
packet_id = lwmqtt_get_next_packet_id(client);
}
// encode publish packet
size_t len = 0;
lwmqtt_err_t err =
lwmqtt_encode_publish(client->write_buf, client->write_buf_size, &len, 0, packet_id, topic, message);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// immediately return on qos zero
if (message.qos == LWMQTT_QOS0) {
return LWMQTT_SUCCESS;
}
// define ack packet
lwmqtt_packet_type_t ack_type = LWMQTT_NO_PACKET;
if (message.qos == LWMQTT_QOS1) {
ack_type = LWMQTT_PUBACK_PACKET;
} else if (message.qos == LWMQTT_QOS2) {
ack_type = LWMQTT_PUBCOMP_PACKET;
}
// wait for ack packet
lwmqtt_packet_type_t packet_type = LWMQTT_NO_PACKET;
err = lwmqtt_cycle_until(client, &packet_type, 0, ack_type);
if (err != LWMQTT_SUCCESS) {
return err;
} else if (packet_type != ack_type) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// decode ack packet
bool dup;
err = lwmqtt_decode_ack(client->read_buf, client->read_buf_size, ack_type, &dup, &packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout) {
// set command timer
client->timer_set(client->command_timer, timeout);
// encode disconnect packet
size_t len;
lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_DISCONNECT_PACKET);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send disconnected packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout) {
// set command timer
client->timer_set(client->command_timer, timeout);
// return immediately if keep alive interval is zero
if (client->keep_alive_interval == 0) {
return LWMQTT_SUCCESS;
}
// return immediately if no ping is due
if (client->timer_get(client->keep_alive_timer) > 0) {
return LWMQTT_SUCCESS;
}
// a ping is due
// fail immediately if a pong is already pending
if (client->pong_pending) {
return LWMQTT_PONG_TIMEOUT;
}
// encode pingreq packet
size_t len;
lwmqtt_err_t err = lwmqtt_encode_zero(client->write_buf, client->write_buf_size, &len, LWMQTT_PINGREQ_PACKET);
if (err != LWMQTT_SUCCESS) {
return err;
}
// send packet
err = lwmqtt_send_packet_in_buffer(client, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// set flag
client->pong_pending = true;
return LWMQTT_SUCCESS;
}

View File

@ -1,249 +0,0 @@
#include <string.h>
#include "helpers.h"
uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num) { return (byte & (uint8_t)((~(0xFF << num)) << pos)) >> pos; }
void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num) {
*byte = (*byte & ~(uint8_t)((~(0xFF << num)) << pos)) | (value << pos);
}
lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len) {
// check zero length
if (len == 0) {
*data = NULL;
return LWMQTT_SUCCESS;
}
// check buffer size
if ((size_t)(buf_end - (*buf)) < len) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// read data
*data = *buf;
// advance pointer
*buf += len;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len) {
// check zero length
if (len == 0) {
return LWMQTT_SUCCESS;
}
// check buffer size
if ((size_t)(buf_end - (*buf)) < len) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// write data
memcpy(*buf, data, len);
// advance pointer
*buf += len;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num) {
// check buffer size
if ((size_t)(buf_end - (*buf)) < 2) {
*num = 0;
return LWMQTT_BUFFER_TOO_SHORT;
}
// read two byte integer
*num = (uint16_t)256 * (*buf)[0] + (*buf)[1];
// adjust pointer
*buf += 2;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num) {
// check buffer size
if ((size_t)(buf_end - (*buf)) < 2) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// write bytes
(*buf)[0] = (uint8_t)(num / 256);
(*buf)[1] = (uint8_t)(num % 256);
// adjust pointer
*buf += 2;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str) {
// read length
uint16_t len;
lwmqtt_err_t err = lwmqtt_read_num(buf, buf_end, &len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// read data
err = lwmqtt_read_data(buf, buf_end, (uint8_t **)&str->data, len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// set length
str->len = len;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str) {
// write string length
lwmqtt_err_t err = lwmqtt_write_num(buf, buf_end, str.len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write data
err = lwmqtt_write_data(buf, buf_end, (uint8_t *)str.data, str.len);
if (err != LWMQTT_SUCCESS) {
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte) {
// check buffer size
if ((size_t)(buf_end - (*buf)) < 1) {
*byte = 0;
return LWMQTT_BUFFER_TOO_SHORT;
}
// read byte
*byte = (*buf)[0];
// adjust pointer
*buf += 1;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte) {
// check buffer size
if ((size_t)(buf_end - (*buf)) < 1) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// write byte
(*buf)[0] = byte;
// adjust pointer
*buf += 1;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len) {
if (varnum < 128) {
*len = 1;
return LWMQTT_SUCCESS;
} else if (varnum < 16384) {
*len = 2;
return LWMQTT_SUCCESS;
} else if (varnum < 2097151) {
*len = 3;
return LWMQTT_SUCCESS;
} else if (varnum < 268435455) {
*len = 4;
return LWMQTT_SUCCESS;
} else {
*len = 0;
return LWMQTT_VARNUM_OVERFLOW;
}
}
lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum) {
// prepare last byte
uint8_t byte;
// prepare multiplier
uint32_t multiplier = 1;
// prepare length
size_t len = 0;
// initialize number
*varnum = 0;
// decode variadic number
do {
// increment length
len++;
// return error if buffer is to small
if ((size_t)(buf_end - (*buf)) < len) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// return error if the length has overflowed
if (len > 4) {
return LWMQTT_VARNUM_OVERFLOW;
}
// read byte
byte = (*buf)[len - 1];
// add byte to number
*varnum += (byte & 127) * multiplier;
// increase multiplier
multiplier *= 128;
} while ((byte & 128) != 0);
// adjust pointer
*buf += len;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum) {
// init len counter
size_t len = 0;
// encode variadic number
do {
// check overflow
if (len == 4) {
return LWMQTT_VARNUM_OVERFLOW;
}
// return error if buffer is to small
if ((size_t)(buf_end - (*buf)) < len + 1) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// calculate current byte
uint8_t byte = (uint8_t)(varnum % 128);
// change remaining length
varnum /= 128;
// set the top bit of this byte if there are more to encode
if (varnum > 0) {
byte |= 0x80;
}
// write byte
(*buf)[len++] = byte;
} while (varnum > 0);
// adjust pointer
*buf += len;
return LWMQTT_SUCCESS;
}

View File

@ -1,137 +0,0 @@
#ifndef LWMQTT_HELPERS_H
#define LWMQTT_HELPERS_H
#include "lwmqtt.h"
/**
* Reads bits from a byte.
*
* @param byte - The byte to read from.
* @param pos - The position of the first bit.
* @param num - The number of bits to read.
* @return The read bits as a byte.
*/
uint8_t lwmqtt_read_bits(uint8_t byte, int pos, int num);
/**
* Write bits to a byte.
*
* @param byte - The byte to write bits to.
* @param value - The bits to write as a byte.
* @param pos - The position of the first bit.
* @param num - The number of bits to write.
*/
void lwmqtt_write_bits(uint8_t *byte, uint8_t value, int pos, int num);
/**
* Reads arbitrary data from the specified buffer. The pointer is incremented by bytes read.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param data - Pointer to beginning of data.
* @param len - The amount of data to read.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_read_data(uint8_t **buf, const uint8_t *buf_end, uint8_t **data, size_t len);
/**
* Writes arbitrary data to the specified buffer. The pointer is incremented by the bytes written.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param data - Pointer to the to be written data.
* @param len - The amount of data to write.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_write_data(uint8_t **buf, const uint8_t *buf_end, uint8_t *data, size_t len);
/**
* Reads two byte number from the specified buffer. The pointer is incremented by two.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param num - The read number.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_read_num(uint8_t **buf, const uint8_t *buf_end, uint16_t *num);
/**
* Writes a two byte number to the specified buffer. The pointer is incremented by two.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param num - The number to write.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_write_num(uint8_t **buf, const uint8_t *buf_end, uint16_t num);
/**
* Reads a string from the specified buffer into the passed object. The pointer is incremented by the bytes read.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param str - The object into which the data is to be read.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_read_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t *str);
/**
* Writes a string to the specified buffer. The pointer is incremented by the bytes written.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param str - The string to write.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_write_string(uint8_t **buf, const uint8_t *buf_end, lwmqtt_string_t str);
/**
* Reads one byte from the buffer. The pointer is incremented by one.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param byte - The read byte.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_read_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t *byte);
/**
* Writes one byte to the specified buffer. The pointer is incremented by one.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param byte - The byte to write.
* @return LWMQTT_SUCCESS or LWMQTT_BUFFER_TOO_SHORT.
*/
lwmqtt_err_t lwmqtt_write_byte(uint8_t **buf, const uint8_t *buf_end, uint8_t byte);
/**
* Returns the amount of bytes required by the variable number.
*
* @param varnum - The number to check.
* @param len - The required length;
* @return LWMQTT_SUCCESS or LWMQTT_VARNUM_OVERFLOW.
*/
lwmqtt_err_t lwmqtt_varnum_length(uint32_t varnum, int *len);
/**
* Reads a variable number from the specified buffer. The pointer is incremented by the bytes read.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param varnum - The read varnum.
* @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW.
*/
lwmqtt_err_t lwmqtt_read_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t *varnum);
/**
* Writes a variable number to the specified buffer. The pointer is incremented by the bytes written.
*
* @param buf - Pointer to the buffer.
* @param buf_end - Pointer to the end of the buffer.
* @param varnum - The number to write.
* @return LWMQTT_SUCCESS, LWMQTT_BUFFER_TOO_SHORT or LWMQTT_VARNUM_OVERFLOW.
*/
lwmqtt_err_t lwmqtt_write_varnum(uint8_t **buf, const uint8_t *buf_end, uint32_t varnum);
#endif

View File

@ -1,381 +0,0 @@
#ifndef LWMQTT_H
#define LWMQTT_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
/**
* The error type used by all exposed APIs.
*
* If a function returns an error that operates on a connected client (e.g publish, keep_alive, etc.) the caller should
* switch into a disconnected state, close and cleanup the current connection and start over by creating a new
* connection.
*/
typedef enum {
LWMQTT_SUCCESS = 0,
LWMQTT_BUFFER_TOO_SHORT = -1,
LWMQTT_VARNUM_OVERFLOW = -2,
LWMQTT_NETWORK_FAILED_CONNECT = -3,
LWMQTT_NETWORK_TIMEOUT = -4,
LWMQTT_NETWORK_FAILED_READ = -5,
LWMQTT_NETWORK_FAILED_WRITE = -6,
LWMQTT_REMAINING_LENGTH_OVERFLOW = -7,
LWMQTT_REMAINING_LENGTH_MISMATCH = -8,
LWMQTT_MISSING_OR_WRONG_PACKET = -9,
LWMQTT_CONNECTION_DENIED = -10,
LWMQTT_FAILED_SUBSCRIPTION = -11,
LWMQTT_SUBACK_ARRAY_OVERFLOW = -12,
LWMQTT_PONG_TIMEOUT = -13,
} lwmqtt_err_t;
/**
* A common string object.
*/
typedef struct {
uint16_t len;
char *data;
} lwmqtt_string_t;
/**
* The initializer for string objects.
*/
#define lwmqtt_default_string \
{ 0, NULL }
/**
* Returns a string object for the passed C string.
*
* @param str - The C string.
* @return A string object.
*/
lwmqtt_string_t lwmqtt_string(const char *str);
/**
* Compares a string object to a C string.
*
* @param a - The string object to compare.
* @param b - The C string to compare.
* @return Similarity e.g. strcmp().
*/
int lwmqtt_strcmp(lwmqtt_string_t a, const char *b);
/**
* The available QOS levels.
*/
typedef enum { LWMQTT_QOS0 = 0, LWMQTT_QOS1 = 1, LWMQTT_QOS2 = 2, LWMQTT_QOS_FAILURE = 128 } lwmqtt_qos_t;
/**
* The message object used to publish and receive messages.
*/
typedef struct {
lwmqtt_qos_t qos;
bool retained;
uint8_t *payload;
size_t payload_len;
} lwmqtt_message_t;
/**
* The initializer for message objects.
*/
#define lwmqtt_default_message \
{ LWMQTT_QOS0, false, NULL, 0 }
/**
* Forward declaration of the client object.
*/
typedef struct lwmqtt_client_t lwmqtt_client_t;
/**
* The callback used to read from a network object.
*
* The callbacks is expected to read up to the amount of bytes in to the passed buffer. It should block the specified
* timeout and wait for more incoming data.
*
* @param ref - A custom reference.
* @param buf - The buffer.
* @param len - The length of the buffer.
* @param read - Variable that must be set with the amount of read bytes.
* @param timeout - The timeout in milliseconds for the operation.
*/
typedef lwmqtt_err_t (*lwmqtt_network_read_t)(void *ref, uint8_t *buf, size_t len, size_t *read, uint32_t timeout);
/**
* The callback used to write to a network object.
*
* The callback is expected to write up to the amount of bytes from the passed buffer. It should wait up to the
* specified timeout to write the specified data to the network.
*
* @param ref - A custom reference.
* @param buf - The buffer.
* @param len - The length of the buffer.
* @param sent - Variable that must be set with the amount of written bytes.
* @param timeout - The timeout in milliseconds for the operation.
*/
typedef lwmqtt_err_t (*lwmqtt_network_write_t)(void *ref, uint8_t *buf, size_t len, size_t *sent, uint32_t timeout);
/**
* The callback used to set a timer.
*
* @param ref - A custom reference.
* @param timeout - The amount of milliseconds until the deadline.
*/
typedef void (*lwmqtt_timer_set_t)(void *ref, uint32_t timeout);
/**
* The callback used to get a timers value.
*
* @param - A custom reference.
* @return The amount of milliseconds until the deadline. May return negative numbers if the deadline has been reached.
*/
typedef int32_t (*lwmqtt_timer_get_t)(void *ref);
/**
* The callback used to forward incoming messages.
*
* Note: The callback is mostly executed because of a call to lwmqtt_yield() that processes incoming messages. However,
* it is possible that the callback is also executed during a call to lwmqtt_subscribe(), lwmqtt_publish() or
* lwmqtt_unsubscribe() if incoming messages are received between the required acknowledgements. It is therefore not
* recommended to call any further lwmqtt methods in the callback as this might result in weird call stacks. The
* callback should place the received messages in a queue and dispatch them after the caller has returned.
*/
typedef void (*lwmqtt_callback_t)(lwmqtt_client_t *client, void *ref, lwmqtt_string_t str, lwmqtt_message_t msg);
/**
* The client object.
*/
struct lwmqtt_client_t {
uint16_t last_packet_id;
uint32_t keep_alive_interval;
bool pong_pending;
size_t write_buf_size, read_buf_size;
uint8_t *write_buf, *read_buf;
lwmqtt_callback_t callback;
void *callback_ref;
void *network;
lwmqtt_network_read_t network_read;
lwmqtt_network_write_t network_write;
void *keep_alive_timer;
void *command_timer;
lwmqtt_timer_set_t timer_set;
lwmqtt_timer_get_t timer_get;
};
/**
* Will initialize the specified client object.
*
* @param client - The client object.
* @param write_buf - The write buffer.
* @param write_buf_size - The write buffer size.
* @param read_buf - The read buffer.
* @param read_buf_size - The read buffer size.
*/
void lwmqtt_init(lwmqtt_client_t *client, uint8_t *write_buf, size_t write_buf_size, uint8_t *read_buf,
size_t read_buf_size);
/**
* Will set the network reference and callbacks for this client object.
*
* @param client - The client object.
* @param ref - The reference to the network object.
* @param read - The read callback.
* @param write - The write callback.
*/
void lwmqtt_set_network(lwmqtt_client_t *client, void *ref, lwmqtt_network_read_t read, lwmqtt_network_write_t write);
/**
* Will set the timer references and callbacks for this client object.
*
* @param client - The client object.
* @param keep_alive_timer - The reference to the keep alive timer.
* @param command_timer - The reference to the command timer.
* @param set - The set callback.
* @param get - The get callback.
*/
void lwmqtt_set_timers(lwmqtt_client_t *client, void *keep_alive_timer, void *command_timer, lwmqtt_timer_set_t set,
lwmqtt_timer_get_t get);
/**
* Will set the callback used to receive incoming messages.
*
* @param client - The client object.
* @param ref - A custom reference that will passed to the callback.
* @param cb - The callback to be called.
*/
void lwmqtt_set_callback(lwmqtt_client_t *client, void *ref, lwmqtt_callback_t cb);
/**
* The object defining the last will of a client.
*/
typedef struct {
lwmqtt_string_t topic;
lwmqtt_qos_t qos;
bool retained;
lwmqtt_string_t payload;
} lwmqtt_will_t;
/**
* The default initializer for the will object.
*/
#define lwmqtt_default_will \
{ lwmqtt_default_string, LWMQTT_QOS0, false, lwmqtt_default_string }
/**
* The object containing the connection options for a client.
*/
typedef struct {
lwmqtt_string_t client_id;
uint16_t keep_alive;
bool clean_session;
lwmqtt_string_t username;
lwmqtt_string_t password;
} lwmqtt_options_t;
/**
* The default initializer for the options object.
*/
#define lwmqtt_default_options \
{ lwmqtt_default_string, 60, true, lwmqtt_default_string, lwmqtt_default_string }
/**
* The available return codes transported by the connack packet.
*/
typedef enum {
LWMQTT_CONNECTION_ACCEPTED = 0,
LWMQTT_UNACCEPTABLE_PROTOCOL = 1,
LWMQTT_IDENTIFIER_REJECTED = 2,
LWMQTT_SERVER_UNAVAILABLE = 3,
LWMQTT_BAD_USERNAME_OR_PASSWORD = 4,
LWMQTT_NOT_AUTHORIZED = 5,
LWMQTT_UNKNOWN_RETURN_CODE = 6
} lwmqtt_return_code_t;
/**
* Will send a connect packet and wait for a connack response and set the return code.
*
* The network object must already be connected to the server. An error is returned if the broker rejects the
* connection.
*
* @param client - The client object.
* @param options - The options object.
* @param will - The will object.
* @param return_code - The variable that will receive the return code.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_connect(lwmqtt_client_t *client, lwmqtt_options_t options, lwmqtt_will_t *will,
lwmqtt_return_code_t *return_code, uint32_t timeout);
/**
* Will send a publish packet and wait for all acks to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client - The client object.
* @param topic - The topic.
* @param message - The message.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_publish(lwmqtt_client_t *client, lwmqtt_string_t topic, lwmqtt_message_t msg, uint32_t timeout);
/**
* Will send a subscribe packet with multiple topic filters plus QOS levels and wait for the suback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client - The client object.
* @param count - The number of topic filters and QOS levels.
* @param topic_filter - The list of topic filters.
* @param qos - The list of QOS levels.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_subscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, lwmqtt_qos_t *qos,
uint32_t timeout);
/**
* Will send a subscribe packet with a single topic filter plus QOS level and wait for the suback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client - The client object.
* @param topic_filter - The topic filter.
* @param qos - The QOS level.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_subscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, lwmqtt_qos_t qos,
uint32_t timeout);
/**
* Will send an unsubscribe packet with multiple topic filters and wait for the unsuback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client - The client object.
* @param count - The number of topic filters.
* @param topic_filter - The topic filter.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_unsubscribe(lwmqtt_client_t *client, int count, lwmqtt_string_t *topic_filter, uint32_t timeout);
/**
* Will send an unsubscribe packet with a single topic filter and wait for the unsuback to complete.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client - The client object.
* @param topic_filter - The topic filter.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_unsubscribe_one(lwmqtt_client_t *client, lwmqtt_string_t topic_filter, uint32_t timeout);
/**
* Will send a disconnect packet and finish the client.
*
* @param client - The client object.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_disconnect(lwmqtt_client_t *client, uint32_t timeout);
/**
* Will yield control to the client and receive incoming packets from the network.
*
* Single-threaded applications may peek on the network and assess if data is available to read before calling yield and
* potentially block until the timeout is reached. Multi-threaded applications may select on the socket and block until
* data is available and then yield to the client if data is available. All applications may specify the amount of bytes
* available to read in order to constrain the yield to only receive packets that are already in-flight.
*
* If no availability info is given the yield will return after one packet has been successfully read or the deadline
* has been reached but no single bytes has been received.
*
* Note: The message callback might be called with incoming messages as part of this call.
*
* @param client - The client object.
* @param available - The available bytes to read.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_yield(lwmqtt_client_t *client, size_t available, uint32_t timeout);
/**
* Will yield control to the client to keep the connection alive.
*
* This functions must be called at a rate slightly lower than 25% of the configured keep alive. If keep alive is zero,
* the function must not be called at all.
*
* @param client - The client object.
* @param timeout - The command timeout.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_keep_alive(lwmqtt_client_t *client, uint32_t timeout);
#endif // LWMQTT_H

View File

@ -1,742 +0,0 @@
#include "packet.h"
lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type) {
// set default packet type
*packet_type = LWMQTT_NO_PACKET;
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// prepare header
uint8_t header;
// read header
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// get packet type
*packet_type = (lwmqtt_packet_type_t)lwmqtt_read_bits(header, 4, 4);
// check if packet type is correct and can be received
switch (*packet_type) {
case LWMQTT_CONNACK_PACKET:
case LWMQTT_PUBLISH_PACKET:
case LWMQTT_PUBACK_PACKET:
case LWMQTT_PUBREC_PACKET:
case LWMQTT_PUBREL_PACKET:
case LWMQTT_PUBCOMP_PACKET:
case LWMQTT_SUBACK_PACKET:
case LWMQTT_UNSUBACK_PACKET:
case LWMQTT_PINGRESP_PACKET:
return LWMQTT_SUCCESS;
default:
*packet_type = LWMQTT_NO_PACKET;
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
}
lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len) {
// prepare pointer
uint8_t *ptr = buf;
// attempt to decode remaining length
lwmqtt_err_t err = lwmqtt_read_varnum(&ptr, buf + buf_len, rem_len);
if (err == LWMQTT_VARNUM_OVERFLOW) {
*rem_len = 0;
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
} else if (err != LWMQTT_SUCCESS) {
*rem_len = 0;
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options,
lwmqtt_will_t *will) {
// prepare pointers
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// fixed header is 10
uint32_t rem_len = 10;
// add client id to remaining length
rem_len += options.client_id.len + 2;
// add will if present to remaining length
if (will != NULL) {
rem_len += will->topic.len + 2 + will->payload.len + 2;
}
// add username if present to remaining length
if (options.username.len > 0) {
rem_len += options.username.len + 2;
// add password if present to remaining length
if (options.password.len > 0) {
rem_len += options.password.len + 2;
}
}
// check remaining length length
int rem_len_len;
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
if (err == LWMQTT_VARNUM_OVERFLOW) {
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
}
// prepare header
uint8_t header = 0;
lwmqtt_write_bits(&header, LWMQTT_CONNECT_PACKET, 4, 4);
// write header
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write remaining length
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write version string
err = lwmqtt_write_string(&buf_ptr, buf_end, lwmqtt_string("MQTT"));
if (err != LWMQTT_SUCCESS) {
return err;
}
// write version number
err = lwmqtt_write_byte(&buf_ptr, buf_end, 4);
if (err != LWMQTT_SUCCESS) {
return err;
}
// prepare flags
uint8_t flags = 0;
// set clean session
lwmqtt_write_bits(&flags, (uint8_t)(options.clean_session), 1, 1);
// set will flags if present
if (will != NULL) {
lwmqtt_write_bits(&flags, 1, 2, 1);
lwmqtt_write_bits(&flags, will->qos, 3, 2);
lwmqtt_write_bits(&flags, (uint8_t)(will->retained), 5, 1);
}
// set username flag if present
if (options.username.len > 0) {
lwmqtt_write_bits(&flags, 1, 7, 1);
// set password flag if present
if (options.password.len > 0) {
lwmqtt_write_bits(&flags, 1, 6, 1);
}
}
// write flags
err = lwmqtt_write_byte(&buf_ptr, buf_end, flags);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write keep alive
err = lwmqtt_write_num(&buf_ptr, buf_end, options.keep_alive);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write client id
err = lwmqtt_write_string(&buf_ptr, buf_end, options.client_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write will if present
if (will != NULL) {
// write topic
err = lwmqtt_write_string(&buf_ptr, buf_end, will->topic);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write payload length
err = lwmqtt_write_num(&buf_ptr, buf_end, (uint16_t)will->payload.len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write payload
err = lwmqtt_write_data(&buf_ptr, buf_end, (uint8_t *)will->payload.data, will->payload.len);
if (err != LWMQTT_SUCCESS) {
return err;
}
}
// write username if present
if (options.username.len > 0) {
err = lwmqtt_write_string(&buf_ptr, buf_end, options.username);
if (err != LWMQTT_SUCCESS) {
return err;
}
}
// write password if present
if (options.username.len > 0 && options.password.len > 0) {
err = lwmqtt_write_string(&buf_ptr, buf_end, options.password);
if (err != LWMQTT_SUCCESS) {
return err;
}
}
// set written length
*len = buf_ptr - buf;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present,
lwmqtt_return_code_t *return_code) {
// prepare pointers
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// read header
uint8_t header;
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check packet type
if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_CONNACK_PACKET) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// read remaining length
uint32_t rem_len;
err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check remaining length
if (rem_len != 2) {
return LWMQTT_REMAINING_LENGTH_MISMATCH;
}
// read flags
uint8_t flags;
err = lwmqtt_read_byte(&buf_ptr, buf_end, &flags);
if (err != LWMQTT_SUCCESS) {
return err;
}
// read return code
uint8_t raw_return_code;
err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_return_code);
if (err != LWMQTT_SUCCESS) {
return err;
}
// get session present
*session_present = lwmqtt_read_bits(flags, 7, 1) == 1;
// get return code
switch (raw_return_code) {
case 0:
*return_code = LWMQTT_CONNECTION_ACCEPTED;
break;
case 1:
*return_code = LWMQTT_UNACCEPTABLE_PROTOCOL;
break;
case 2:
*return_code = LWMQTT_IDENTIFIER_REJECTED;
break;
case 3:
*return_code = LWMQTT_SERVER_UNAVAILABLE;
break;
case 4:
*return_code = LWMQTT_BAD_USERNAME_OR_PASSWORD;
break;
case 5:
*return_code = LWMQTT_NOT_AUTHORIZED;
break;
default:
*return_code = LWMQTT_UNKNOWN_RETURN_CODE;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// write header
uint8_t header = 0;
lwmqtt_write_bits(&header, packet_type, 4, 4);
lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write remaining length
err = lwmqtt_write_varnum(&buf_ptr, buf_end, 0);
if (err != LWMQTT_SUCCESS) {
return err;
}
// set length
*len = buf_ptr - buf;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup,
uint16_t *packet_id) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// read header
uint8_t header = 0;
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check packet type
if (lwmqtt_read_bits(header, 4, 4) != packet_type) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// get dup
*dup = lwmqtt_read_bits(header, 3, 1) == 1;
// read remaining length
uint32_t rem_len;
err = lwmqtt_read_varnum(&buf_ptr, buf + buf_len, &rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check remaining length
if (rem_len != 2) {
return LWMQTT_REMAINING_LENGTH_MISMATCH;
}
// read packet id
err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup,
uint16_t packet_id) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// prepare header
uint8_t header = 0;
// set packet type
lwmqtt_write_bits(&header, packet_type, 4, 4);
// set dup
lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1);
// set qos
lwmqtt_write_bits(&header, (uint8_t)(packet_type == LWMQTT_PUBREL_PACKET ? LWMQTT_QOS1 : LWMQTT_QOS0), 1, 2);
// write header
lwmqtt_err_t err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write remaining length
err = lwmqtt_write_varnum(&buf_ptr, buf_end, 2);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write packet id
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// set written length
*len = buf_ptr - buf;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic,
lwmqtt_message_t *msg) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// read header
uint8_t header;
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check packet type
if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_PUBLISH_PACKET) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// get dup
*dup = lwmqtt_read_bits(header, 3, 1) == 1;
// get retained
msg->retained = lwmqtt_read_bits(header, 0, 1) == 1;
// get qos
switch (lwmqtt_read_bits(header, 1, 2)) {
case 0:
msg->qos = LWMQTT_QOS0;
break;
case 1:
msg->qos = LWMQTT_QOS1;
break;
case 2:
msg->qos = LWMQTT_QOS2;
break;
default:
msg->qos = LWMQTT_QOS0;
break;
}
// read remaining length
uint32_t rem_len;
err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check remaining length (topic length)
if (rem_len < 2) {
return LWMQTT_REMAINING_LENGTH_MISMATCH;
}
// check buffer capacity
if ((uint32_t)(buf_end - buf_ptr) < rem_len) {
return LWMQTT_BUFFER_TOO_SHORT;
}
// reset buf end
buf_end = buf_ptr + rem_len;
// read topic
err = lwmqtt_read_string(&buf_ptr, buf_end, topic);
if (err != LWMQTT_SUCCESS) {
return err;
}
// read packet id if qos is at least 1
if (msg->qos > 0) {
err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
} else {
*packet_id = 0;
}
// set payload length
msg->payload_len = buf_end - buf_ptr;
// read payload
err = lwmqtt_read_data(&buf_ptr, buf_end, &msg->payload, buf_end - buf_ptr);
if (err != LWMQTT_SUCCESS) {
return err;
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id,
lwmqtt_string_t topic, lwmqtt_message_t msg) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// calculate remaining length
uint32_t rem_len = 2 + topic.len + (uint32_t)msg.payload_len;
if (msg.qos > 0) {
rem_len += 2;
}
// check remaining length length
int rem_len_len;
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
if (err == LWMQTT_VARNUM_OVERFLOW) {
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
}
// prepare header
uint8_t header = 0;
// set packet type
lwmqtt_write_bits(&header, LWMQTT_PUBLISH_PACKET, 4, 4);
// set dup
lwmqtt_write_bits(&header, (uint8_t)(dup), 3, 1);
// set qos
lwmqtt_write_bits(&header, msg.qos, 1, 2);
// set retained
lwmqtt_write_bits(&header, (uint8_t)(msg.retained), 0, 1);
// write header
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write remaining length
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write topic
err = lwmqtt_write_string(&buf_ptr, buf_end, topic);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write packet id if qos is at least 1
if (msg.qos > 0) {
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
}
// write payload
err = lwmqtt_write_data(&buf_ptr, buf_end, msg.payload, msg.payload_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// set length
*len = buf_ptr - buf;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// calculate remaining length
uint32_t rem_len = 2;
for (int i = 0; i < count; i++) {
rem_len += 2 + topic_filters[i].len + 1;
}
// check remaining length length
int rem_len_len;
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
if (err == LWMQTT_VARNUM_OVERFLOW) {
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
}
// prepare header
uint8_t header = 0;
// set packet type
lwmqtt_write_bits(&header, LWMQTT_SUBSCRIBE_PACKET, 4, 4);
// set qos
lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2);
// write header
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write remaining length
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write packet id
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write all subscriptions
for (int i = 0; i < count; i++) {
// write topic
err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write qos level
err = lwmqtt_write_byte(&buf_ptr, buf_end, (uint8_t)qos_levels[i]);
if (err != LWMQTT_SUCCESS) {
return err;
}
}
// set length
*len = buf_ptr - buf;
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count,
lwmqtt_qos_t *granted_qos_levels) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// read header
uint8_t header;
lwmqtt_err_t err = lwmqtt_read_byte(&buf_ptr, buf_end, &header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check packet type
if (lwmqtt_read_bits(header, 4, 4) != LWMQTT_SUBACK_PACKET) {
return LWMQTT_MISSING_OR_WRONG_PACKET;
}
// read remaining length
uint32_t rem_len;
err = lwmqtt_read_varnum(&buf_ptr, buf_end, &rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// check remaining length (packet id + min. one suback code)
if (rem_len < 3) {
return LWMQTT_REMAINING_LENGTH_MISMATCH;
}
// read packet id
err = lwmqtt_read_num(&buf_ptr, buf_end, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// read all suback codes
for (*count = 0; *count < (int)rem_len - 2; (*count)++) {
// check max count
if (*count > max_count) {
return LWMQTT_SUBACK_ARRAY_OVERFLOW;
}
// read qos level
uint8_t raw_qos_level;
err = lwmqtt_read_byte(&buf_ptr, buf_end, &raw_qos_level);
if (err != LWMQTT_SUCCESS) {
return err;
}
// set qos level
switch (raw_qos_level) {
case 0:
granted_qos_levels[*count] = LWMQTT_QOS0;
break;
case 1:
granted_qos_levels[*count] = LWMQTT_QOS1;
break;
case 2:
granted_qos_levels[*count] = LWMQTT_QOS2;
break;
default:
granted_qos_levels[*count] = LWMQTT_QOS_FAILURE;
break;
}
}
return LWMQTT_SUCCESS;
}
lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
lwmqtt_string_t *topic_filters) {
// prepare pointer
uint8_t *buf_ptr = buf;
uint8_t *buf_end = buf + buf_len;
// calculate remaining length
uint32_t rem_len = 2;
for (int i = 0; i < count; i++) {
rem_len += 2 + topic_filters[i].len;
}
// check remaining length length
int rem_len_len;
lwmqtt_err_t err = lwmqtt_varnum_length(rem_len, &rem_len_len);
if (err == LWMQTT_VARNUM_OVERFLOW) {
return LWMQTT_REMAINING_LENGTH_OVERFLOW;
}
// prepare header
uint8_t header = 0;
// set packet type
lwmqtt_write_bits(&header, LWMQTT_UNSUBSCRIBE_PACKET, 4, 4);
// set qos
lwmqtt_write_bits(&header, LWMQTT_QOS1, 1, 2);
// write header
err = lwmqtt_write_byte(&buf_ptr, buf_end, header);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write remaining length
err = lwmqtt_write_varnum(&buf_ptr, buf_end, rem_len);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write packet id
err = lwmqtt_write_num(&buf_ptr, buf_end, packet_id);
if (err != LWMQTT_SUCCESS) {
return err;
}
// write topics
for (int i = 0; i < count; i++) {
err = lwmqtt_write_string(&buf_ptr, buf_end, topic_filters[i]);
if (err != LWMQTT_SUCCESS) {
return err;
}
}
// set length
*len = buf_ptr - buf;
return LWMQTT_SUCCESS;
}

View File

@ -1,185 +0,0 @@
#ifndef LWMQTT_PACKET_H
#define LWMQTT_PACKET_H
#include "helpers.h"
/**
* The available packet types.
*/
typedef enum {
LWMQTT_NO_PACKET = 0,
LWMQTT_CONNECT_PACKET = 1,
LWMQTT_CONNACK_PACKET,
LWMQTT_PUBLISH_PACKET,
LWMQTT_PUBACK_PACKET,
LWMQTT_PUBREC_PACKET,
LWMQTT_PUBREL_PACKET,
LWMQTT_PUBCOMP_PACKET,
LWMQTT_SUBSCRIBE_PACKET,
LWMQTT_SUBACK_PACKET,
LWMQTT_UNSUBSCRIBE_PACKET,
LWMQTT_UNSUBACK_PACKET,
LWMQTT_PINGREQ_PACKET,
LWMQTT_PINGRESP_PACKET,
LWMQTT_DISCONNECT_PACKET
} lwmqtt_packet_type_t;
/**
* Will detect the packet type from the at least one byte long buffer.
*
* @param buf - The buffer from which the packet type will be detected.
* @param buf_len - The length of the specified buffer.
* @param packet_type - The packet type.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_detect_packet_type(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t *packet_type);
/**
* Will detect the remaining length form the at least on byte long buffer.
*
* It will return LWMQTT_BUFFER_TOO_SHORT if the buffer is to short and an additional byte should be read from the
* network. In case the remaining length is overflowed it will return LWMQTT_REMAINING_LENGTH_OVERFLOW.
*
* @param buf - The buffer from which the remaining length will be detected.
* @param buf_len - The length of the specified buffer.
* @param rem_len - The detected remaining length.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_detect_remaining_length(uint8_t *buf, size_t buf_len, uint32_t *rem_len);
/**
* Encodes a connect packet into the supplied buffer.
*
* @param buf - The buffer into which the packet will be encoded.
* @param buf_len - The length of the specified buffer.
* @param len - The encoded length of the packet.
* @param options - The options to be used to build the connect packet.
* @param will - The last will and testament.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_encode_connect(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_options_t options,
lwmqtt_will_t *will);
/**
* Decodes a connack packet from the supplied buffer.
*
* @param buf - The raw buffer data.
* @param buf_len - The length of the specified buffer.
* @param session_present - The session present flag.
* @param return_code - The return code.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_decode_connack(uint8_t *buf, size_t buf_len, bool *session_present,
lwmqtt_return_code_t *return_code);
/**
* Encodes a zero (disconnect, pingreq) packet into the supplied buffer.
*
* @param buf - The buffer into which the packet will be encoded.
* @param buf_len - The length of the specified buffer.
* @param len - The encoded length of the packet.
* @param packet_type - The packets type.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_encode_zero(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type);
/**
* Decodes an ack (puback, pubrec, pubrel, pubcomp, unsuback) packet from the supplied buffer.
*
* @param buf - The raw buffer data.
* @param buf_len - The length of the specified buffer.
* @param packet_type - The packet type.
* @param dup - The dup flag.
* @param packet_id - The packet id.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_decode_ack(uint8_t *buf, size_t buf_len, lwmqtt_packet_type_t packet_type, bool *dup,
uint16_t *packet_id);
/**
* Encodes an ack (puback, pubrec, pubrel, pubcomp) packet into the supplied buffer.
*
* @param buf - The buffer into which the packet will be encoded.
* @param buf_len - The length of the specified buffer.
* @param len - The encoded length of the packet.
* @param packet_type - The packets type.
* @param dup - The dup flag.
* @param packet_id - The packet id.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_encode_ack(uint8_t *buf, size_t buf_len, size_t *len, lwmqtt_packet_type_t packet_type, bool dup,
uint16_t packet_id);
/**
* Decodes a publish packet from the supplied buffer.
*
* @param buf - The raw buffer data.
* @param buf_len - The length of the specified buffer.
* @param dup - The dup flag.
* @param packet_id - The packet id.
* @param topic - The topic.
* @parma msg - The message.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_decode_publish(uint8_t *buf, size_t buf_len, bool *dup, uint16_t *packet_id, lwmqtt_string_t *topic,
lwmqtt_message_t *msg);
/**
* Encodes a publish packet into the supplied buffer.
*
* @param buf - The buffer into which the packet will be encoded.
* @param buf_len - The length of the specified buffer.
* @param len - The encoded length of the packet.
* @param dup - The dup flag.
* @param packet_id - The packet id.
* @param topic - The topic.
* @param msg - The message.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_encode_publish(uint8_t *buf, size_t buf_len, size_t *len, bool dup, uint16_t packet_id,
lwmqtt_string_t topic, lwmqtt_message_t msg);
/**
* Encodes a subscribe packet into the supplied buffer.
*
* @param buf - The buffer into which the packet will be encoded.
* @param buf_len - The length of the specified buffer.
* @param len - The encoded length of the packet.
* @param packet_id - The packet id.
* @param count - The number of members in the topic_filters and qos_levels array.
* @param topic_filters - The array of topic filter.
* @param qos_levels - The array of requested QoS levels.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_encode_subscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
lwmqtt_string_t *topic_filters, lwmqtt_qos_t *qos_levels);
/**
* Decodes a suback packet from the supplied buffer.
*
* @param buf - The raw buffer data.
* @param buf_len - The length of the specified buffer.
* @param packet_id - The packet id.
* @param max_count - The maximum number of members allowed in the granted_qos_levels array.
* @param count - The number of members in the granted_qos_levels array.
* @param granted_qos_levels - The granted QoS levels.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_decode_suback(uint8_t *buf, size_t buf_len, uint16_t *packet_id, int max_count, int *count,
lwmqtt_qos_t *granted_qos_levels);
/**
* Encodes the supplied unsubscribe data into the supplied buffer, ready for sending
*
* @param buf - The buffer into which the packet will be encoded.
* @param buf_len - The length of the specified buffer.
* @param len - The encoded length of the packet.
* @param packet_id - The packet id.
* @param count - The number of members in the topic_filters array.
* @param topic_filters - The array of topic filters.
* @return An error value.
*/
lwmqtt_err_t lwmqtt_encode_unsubscribe(uint8_t *buf, size_t buf_len, size_t *len, uint16_t packet_id, int count,
lwmqtt_string_t *topic_filters);
#endif // LWMQTT_PACKET_H

View File

@ -1,38 +0,0 @@
#include <string.h>
#include "lwmqtt.h"
lwmqtt_string_t lwmqtt_string(const char *str) {
// check for null
if (str == NULL) {
return (lwmqtt_string_t){0, NULL};
}
// get length
uint16_t len = (uint16_t)strlen(str);
// check zero length
if (len == 0) {
return (lwmqtt_string_t){0, NULL};
}
return (lwmqtt_string_t){len, (char *)str};
}
int lwmqtt_strcmp(lwmqtt_string_t a, const char *b) {
// get string of b
lwmqtt_string_t b_str = lwmqtt_string(b);
// return if both are zero length
if (a.len == 0 && b_str.len == 0) {
return 0;
}
// return if lengths are different
if (a.len != b_str.len) {
return -1;
}
// compare memory of same length
return strncmp(a.data, b_str.data, a.len);
}

View File

@ -29,6 +29,7 @@ src_dir = sonoff
;env_default = sonoff-HE
;env_default = sonoff-HU
;env_default = sonoff-IT
;env_default = sonoff-KO
;env_default = sonoff-NL
;env_default = sonoff-PL
;env_default = sonoff-PT
@ -65,10 +66,12 @@ build_flags = ${esp82xx_defaults.build_flags}
-DVTABLES_IN_FLASH
[core_2_5_0]
; *** Esp8266 core for Arduino version 2.5.0 release (still not available via platformio)
platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota
; *** Esp8266 core for Arduino version 2.5.0
platform = espressif8266@~2.0.4
build_flags = ${esp82xx_defaults.build_flags}
-Wl,-Teagle.flash.1m.ld
; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473
-O2
; lwIP 1.4 (Default)
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
; lwIP 2 - Low Memory
@ -88,6 +91,12 @@ build_flags = ${esp82xx_defaults.build_flags}
platform = https://github.com/platformio/platform-espressif8266.git#feature/stage
build_flags = ${esp82xx_defaults.build_flags}
-Wl,-Teagle.flash.1m.ld
; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473
-O2
; nonos-sdk 22x
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x
; nonos-sdk-pre-v3
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
; lwIP 1.4 (Default)
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
; lwIP 2 - Low Memory
@ -338,7 +347,7 @@ board = ${common.board}
board_build.flash_mode = ${common.board_build.flash_mode}
board_build.f_cpu = ${common.board_build.f_cpu}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} -DMY_LANGUAGE=es-AR
build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES
monitor_speed = ${common.monitor_speed}
upload_port = ${common.upload_port}
upload_resetmethod = ${common.upload_resetmethod}
@ -415,6 +424,20 @@ upload_resetmethod = ${common.upload_resetmethod}
upload_speed = ${common.upload_speed}
extra_scripts = ${common.extra_scripts}
[env:sonoff-KO]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board}
board_build.flash_mode = ${common.board_build.flash_mode}
board_build.f_cpu = ${common.board_build.f_cpu}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} -DMY_LANGUAGE=ko-KO
monitor_speed = ${common.monitor_speed}
upload_port = ${common.upload_port}
upload_resetmethod = ${common.upload_resetmethod}
upload_speed = ${common.upload_speed}
extra_scripts = ${common.extra_scripts}
[env:sonoff-NL]
platform = ${common.platform}
framework = ${common.framework}

View File

@ -415,7 +415,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t
DEBUG_OUTPUT.println(argFilename);
#endif
//use GET to set the filename if uploading using blob
if (argFilename == F("blob") && hasArg(FPSTR(filename)))
if (argFilename == F("blob") && hasArg(FPSTR(filename)))
argFilename = arg(FPSTR(filename));
}
#ifdef DEBUG_ESP_HTTP_SERVER
@ -510,7 +510,7 @@ readfile:
uint8_t endBuf[boundary.length()];
client.readBytes(endBuf, boundary.length());
if (strstr((const char*)endBuf, boundary.c_str()) != NULL){
if (strstr((const char*)endBuf, boundary.c_str()) != nullptr){
if(_currentHandler && _currentHandler->canUpload(_currentUri))
_currentHandler->upload(*this, _currentUri, *_currentUpload);
_currentUpload->totalSize += _currentUpload->currentSize;
@ -571,7 +571,7 @@ readfile:
arg.value = postArgs[iarg].value;
}
_currentArgCount = iarg;
if (postArgs)
if (postArgs)
delete[] postArgs;
return true;
}

View File

@ -1,97 +1,99 @@
/* 6.4.1.16 20190211
* Initial support for online template change using command Template or GUI Configure Other (#5177)
/* 6.5.0.4 20190402
* Fix Configure Timer Web GUI (#5568)
* Add validation check when loading settings from flash
* Fixed Display Bug in KNX webmenu for Physical Address
*
* 6.4.1.15 20190208
* Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106)
* Change image names USE_xyz to FIRMWARE_xyz (#5106)
* Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131)
* Add status message to former declined group commands (#5145)
* 6.5.0.3 20190328
* Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452)
* Change some defines to const
* Change IRsend and receive for 64-bit support (#5523)
* Change IRSend Panasonic protocol to 64-bit (#5523)
*
* 6.4.1.14 20190203
* Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name
* Add Resolution property to Status 3 report providing previous SetOption second value property
* Fix IR local echo
* Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff S31, Pow Ra and many Tuya based devices
* Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2
* Add support for multiple ADS1115 I2C devices (#5083)
* Add rule support for "==", "!=" ">=" and "<=" (#5122)
* Add Hass status sensor (#5139)
* Change GUI weblog solving possible empty screens (#5154)
* Change PN532 support from I2C to Serial for more stability (#5162)
* Add MHZ19 Temperature as Domoticz Temperature selection (#5128)
* 6.5.0.2 20190325
* Change UDP initial message handling from string to char using static memory and add debug info (#5505)
* Add optional support for Badger HR-E Water Meter (#5539)
*
* 6.4.1.13 20190130
* Add command SetOption36 to control boot loop default restoration (#4645, #5063)
* Add resiliency to saved Settings (#5065)
* 6.5.0.1 20190319
* Change Web GUI sensor data collection
*
* 6.4.1.12 20190128
* 6.5.0 20190319
* Remove commands SetOption14 and SetOption63 as it has been superseded by command Interlock
* Remove command SetOption35 0-255 for mDNS start-up delay (#4793)
* Remove support for MQTT_LIBRARY_TYPE, MQTT_ARDUINOMQTT and MQTT_TASMOTAMQTT (#5474)
* Change webserver content handling from single String to small Chunks increasing RAM
* Change code use of boolean to bool and byte to uint8_t
* Change code uint8_t flags to bool flags
*
* 6.4.1.11 20190124
* Remove command SetOption14 as it has been superseded by command Interlock
* Remove command SetOption63 as it has been superseded by command Interlock
* Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#5014)
* Add core version conditional compile options to provided PWM files (#4917)
* Add support for inverted buttons and inverted buttons without pullup (#4914)
*
* 6.4.1.10 20190121
* Fix Hass discovery of MHZ19(B) sensors (#4992)
* Fix Hass Software Watchdog exception during discovery (#4988)
* Add support for MAX44009 Ambient Light sensor (#4907)
*
* 6.4.1.9 20190115
* Add support for Mi LED Desk Lamp with rotary switch (#4887)
* Fix mDNS addService (#4938, #4951)
* Fix allowable MAX_RULE_VARS to 16 (#4933)
* Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947)
* Add SerialBridge command SSerialSend5 <hexdata>
*
* 6.4.1.8 20190107
* Change sonoff_template.h layout regarding optional module flags like ADC0
* Add command SetOption62 1 to force no Button/Switch pullup on dedicated modules. Currently only supported on Shelly2 (#4841)
* Fix Display exception 28 when JSON value is NULL received
* Fix Home Assistant Sensor Discovery Software Watchdog restart (#4831)
* Change sonoff_template.h module lay-out by removing non-configurable GPIOs
* Change button driver making it modular
* Change switch driver making it modular and introduce input filter (#4665, #4724)
* Change switch input detection by optimizing switch debounce (#4724)
* Change web authentication (#4865)
* Change image name BE_MINIMAL to FIRMWARE_MINIMAL and USE_xyz to FIRMWARE_xyz (#5106)
* Change GUI weblog from XML to plain text solving possible empty screens (#5154)
* Fix most compiler warnings
* Fix Display exception 28 when JSON value is nullptr received
* Fix epaper driver (#4785)
* Fix HAss Sensor Discovery Software Watchdog restart (#4831, #4988)
* Fix allowable MAX_RULE_VARS to 16 (#4933)
* Fix mDNS addService (#4938, #4951)
* Fix HAss discovery of MHZ19(B) sensors (#4992)
* Fix some exceptions and watchdogs due to lack of stack space (#5215)
* Fix GUI wifi password acception starting with asteriks (*) (#5231, #5242)
* Fix command WebSend intermittent results (#5273, #5304)
* Fix additional characters in fallbacktopic, hostname and mqttclient on core 2.5.0 (#5359, #5417)
* Fix Energy TotalStartTime when commands EnergyReset0 and/or EnergyReset3 used (#5373)
* Fix DS18S20 temperature calculation (#5375)
* Fix float calculations in range from 0 to -1 (#5386)
* Fix exception on GUI Configure Logging and Configure Other (#5424)
* Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors
* Add command SerialDelimiter 128 to filter reception of only characters between ASCII 32 and 127 (#5131)
* Add command SSerialSend5 \<hexdata\> to SerialBridge
* Add command Interlock 0 / 1 / 1,2 3,4 .. to control interlock ON/OFF and add up to 8 relays in 1 to 4 interlock groups (#4910, #5014)
* Add command Template 255 to copy module configuration over to current active template and store as user template named Merged (#5371)
* Add command WifiConfig 7 to allow reset of device in AP mode without admin password (#5297)
* Add command SetOption36 to control boot loop default restoration (#4645, #5063)
* Add command SetOption37 for RGBCW color mapping (#5326)
* Add command SetOption55 0/1 and define MDNS_ENABLE to disable/enable mDNS (#4793, #4923)
* Add command SetOption62 0/1 to disable retain on Button or Switch hold messages (#5299)
* Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring
* Add support for commands in sensor drivers
* Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764)
* Add support for Near Field Communication (NFC) controller PN532 using Serial (#4791, #5162)
* Add support for OBI Power Socket 2 (#4829)
* Add support for YTF IR Bridge (#4855)
* Change web authentication (#4865)
* Add support for Mi LED Desk Lamp with rotary switch (#4887)
* Add support for Digoo DG-SP202 Smart Socket with Energy monitoring (#4891)
* Add support for Smanergy KA10 Smart Wall Socket with Energy monitoring
* Add support for MAX44009 Ambient Light sensor (#4907)
* Add support for inverted buttons and inverted buttons without pullup (#4914)
* Add support for Luminea ZX2820 Smart Socket with Energy monitoring (#4921)
* Add define MDNS_ENABLE to control initial mDNS state (#4923)
* Add split interlock part 1 (#4910)
*
* 6.4.1.7 20190106
* Fix HLW8012, HJL01 and BL0937 based energy sensors low Power (below 10W) measurement regression from 6.4.1.6
* Add Power status functionality to LED2 when configured leaving LED1 for Link status indication
* Add no pull-up control to Shelly 2 module (default is pull-up, change GPIO2 to Switch3n for no pull-up) (#4841)
* Add 4 seconds startup delay to button control (#4829)
* Change button driver making it modular
*
* 6.4.1.6 20190105
* Add commands PowerCal, VoltageCal and CurrentCal for HLW8012, HJL01 and BL0937 based energy sensors
*
* 6.4.1.5 20190103
* Remove command SetOption35 0-255 for mDNS start-up delay (#4793)
* Add command SetOption55 0/1 to disable/enable mDNS (#4793)
*
* 6.4.1.4 20190101
* Update Copyright (C) 2019
* Fix epaper driver (#4785)
* Add support for Near Field Communication (NFC) controller PN532 using I2C (#4791)
*
* 6.4.1.3 20181229
* Change sonoff_template.h module lay-out by removing non-configurable GPIOs
* Add support for MAX31855 K-Type thermocouple sensor using softSPI (#4764)
*
* 6.4.1.2 20181228
* Change switch driver making it modular and introduce input filter (#4665, #4724)
* Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738)
* Add support for multiple ADS1115 I2C devices (#5083)
* Add support for online template change using command Template or GUI Configure Other (#5177)
* Add support for Korean language translations (#5344)
* Add support for sensor SCD30 (#5434)
* Add parameter CFG_HOLDER to status 1 message (#5206)
* Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name
* Add Resolution property to Status 3 report providing previous SetOption second value property
* Add property MqttCount to status 6 message representing number of Mqtt re-connections
* Add property LinkCount to state and status 11 message representing number of Wifi Link re-connections
* Add property Downtime to state and status 11 message representing the duration of wifi connection loss
* Add variable %timestamp% to rules (#4749)
*
* 6.4.1.1 20181224
* Fix most compiler warnings
* Change switch input detection by optimizing switch debounce (#4724)
* Add rule support for "==", "!=" ">=" and "<=" (#5122)
* Add rule expression enabled by define USE_EXPRESSION in my_user_config.h (#5210)
* Add Power status functionality to LED2 when configured leaving LED1 for Link status indication
* Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff Pow and many Tuya based devices
* Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2
* Add online template configuration using both commands and Configure Template menu option in GUI
* Add (S)SerialSend3 escape sequence \x to allow hexadecimal byte value (#3560, #4947)
* Add define DS18B20_INTERNAL_PULLUP to select internal input pullup when only one DS18B20 sensor is connected eliminating external resistor (#4738)
* Add button control when no relay configured (#4682)
* Add startup delay of 4 seconds to button control (#4829)
* Add core version conditional compile options to provided PWM files (#4917)
* Add resiliency to saved Settings (#5065)
* Add MHZ19 Temperature as Domoticz Temperature selection (#5128)
* Add HAss status sensor (#5139)
* Add status message to former declined group commands (#5145)
* Add 0x to IRRemote (SetOption29) and RCSwitch (SetOption28) received hexadecimal data (#5431)
*
* 6.4.1 20181224
* Change RAM usage BMP/BME I2C sensors

View File

@ -44,6 +44,7 @@
#define D_JSON_CHANNEL "Channel"
#define D_JSON_CO2 "CarbonDioxide"
#define D_JSON_COMMAND "Command"
#define D_JSON_CONFIG_HOLDER "CfgHolder"
#define D_JSON_CONNECT_FAILED "Connect failed"
#define D_JSON_COREVERSION "Core"
#define D_JSON_COUNT "Count"
@ -53,6 +54,7 @@
#define D_JSON_DISTANCE "Distance"
#define D_JSON_DNSSERVER "DNSServer"
#define D_JSON_DONE "Done"
#define D_JSON_DOWNTIME "Downtime"
#define D_JSON_ECO2 "eCO2"
#define D_JSON_EMPTY "Empty"
#define D_JSON_ENDDST "EndDST" // End Daylight Savings Time
@ -67,6 +69,7 @@
#define D_JSON_FLASHCHIPID "FlashChipId"
#define D_JSON_FLASHMODE "FlashMode"
#define D_JSON_FLASHSIZE "FlashSize"
#define D_JSON_FLOWRATE "FlowRate"
#define D_JSON_FREEMEMORY "Free"
#define D_JSON_FREQUENCY "Frequency"
#define D_JSON_FROM "from"
@ -88,12 +91,14 @@
#define D_JSON_INFRARED "Infrared"
#define D_JSON_UNKNOWN "Unknown"
#define D_JSON_LIGHT "Light"
#define D_JSON_LINK_COUNT "LinkCount"
#define D_JSON_LOCAL_TIME "Local"
#define D_JSON_LOW "Low"
#define D_JSON_MAC "Mac"
#define D_JSON_MASK "Mask"
#define D_JSON_MINIMAL "minimal"
#define D_JSON_MODEL "Model"
#define D_JSON_MQTT_COUNT "MqttCount"
#define D_JSON_NO "No"
#define D_JSON_NOISE "Noise"
#define D_JSON_NONE "None"
@ -139,6 +144,7 @@
#define D_JSON_TIME "Time"
#define D_JSON_TODAY "Today"
#define D_JSON_TOTAL "Total"
#define D_JSON_TOTAL_USAGE "TotalUsage"
#define D_JSON_TOTAL_REACTIVE "TotalReactivePower"
#define D_JSON_TOTAL_START_TIME "TotalStartTime"
#define D_JSON_TVOC "TVOC"
@ -244,6 +250,7 @@
#define D_WCFG_4_RETRY "Retry"
#define D_WCFG_5_WAIT "Wait"
#define D_WCFG_6_SERIAL "Serial"
#define D_WCFG_7_WIFIMANAGER_RESET_ONLY "ManagerRst"
#define D_CMND_FRIENDLYNAME "FriendlyName"
#define D_CMND_SWITCHMODE "SwitchMode"
#define D_CMND_INTERLOCK "Interlock"
@ -418,6 +425,7 @@
/********************************************************************************************/
#define D_ASTERIX "********"
#define D_ASTERISK_PWD "****"
#ifndef MY_LANGUAGE
#include "language/en-GB.h"
@ -500,14 +508,16 @@ const char S_JSON_COMMAND_INDEX_ASTERIX[] PROGMEM = "{\"%s%d\":\"" D_A
const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}";
const char S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s%d\":\"%d (" D_JSON_ACTIVE " %d)\"}";
const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}";
const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}";
const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}";
const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}";
const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}";
const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}";
const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}";
const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}";
const char JSON_SNS_TEMP[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}";
const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}";
const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}";
const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}";
const char JSON_SNS_GNGPM[] PROGMEM = ",\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}";
const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";
@ -535,7 +545,8 @@ const char kWifiConfig[MAX_WIFI_OPTION][WCFG_MAX_STRING_LENGTH] PROGMEM = {
D_WCFG_3_WPSCONFIG,
D_WCFG_4_RETRY,
D_WCFG_5_WAIT,
D_WCFG_6_SERIAL };
D_WCFG_6_SERIAL,
D_WCFG_7_WIFIMANAGER_RESET_ONLY };
const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = {
D_CMND,
D_STAT,
@ -554,19 +565,20 @@ const char kOptionBlinkOff[] PROGMEM = "BLINKOFF|" D_BLINKOFF ;
// xdrv_02_webserver.ino
#ifdef USE_WEBSERVER
const char HTTP_SNS_TEMP[] PROGMEM = "%s{s}%s " D_TEMPERATURE "{m}%s&deg;%c{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "%s{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798)
const char HTTP_SNS_CO2[] PROGMEM = "%s{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
#endif // USE_WEBSERVER
const char HTTP_SNS_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%s&deg;%c{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_HUM[] PROGMEM = "{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_PRESSURE[] PROGMEM = "{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_GALLONS[] PROGMEM = "{s}%s " D_TOTAL_USAGE "{m}%s " D_UNIT_GALLONS " {e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char HTTP_SNS_GPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_GALLONS_PER_MIN" {e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
const char S_CONFIGURE_TEMPLATE[] PROGMEM = D_CONFIGURE_TEMPLATE;
const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE;
const char S_CONFIGURE_WIFI[] PROGMEM = D_CONFIGURE_WIFI;
const char S_NO_NETWORKS_FOUND[] PROGMEM = D_NO_NETWORKS_FOUND;

View File

@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
* Updated until v6.4.0.1
* Updated until v6.4.1.18
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Помощен топик"
#define D_FALSE "Невярно"
#define D_FILE "Файл"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Свободна памет"
#define D_FREQUENCY "Честота"
#define D_GAS "Газ"
@ -148,6 +149,7 @@
#define D_STOP "Стоп"
#define D_SUBNET_MASK "Маска на подмрежата"
#define D_SUBSCRIBE_TO "Записване за"
#define D_UNSUBSCRIBE_FROM "Отписване от"
#define D_SUCCESSFUL "Успешно"
#define D_SUNRISE "Изгрев"
#define D_SUNSET "Залез"
@ -155,6 +157,7 @@
#define D_TO "към"
#define D_TOGGLE "Превключване"
#define D_TOPIC "Топик"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Предаване"
#define D_TRUE "Вярно"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Разрешете JavaScript, за да използвате Tasmota"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър - моля надградете го"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Минимален фърмуеър<br/>моля надградете го"
#define D_WEBSERVER_ACTIVE_ON "Уеб сървърът е активен на"
#define D_WITH_IP_ADDRESS "с IP адрес"
#define D_WEBSERVER_STOPPED "Уеб сървърът е спрян"
@ -253,7 +256,7 @@
#define D_MODULE_PARAMETERS "Параметри на модула"
#define D_MODULE_TYPE "Тип на модула"
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
#define D_PULLUP_ENABLE "Без pull-up за бутон/ключ"
#define D_GPIO "GPIO"
#define D_SERIAL_IN "Сериен вход"
#define D_SERIAL_OUT "Сериен изход"
@ -288,7 +291,8 @@
#define D_TELEMETRY_PERIOD "Период на телеметрия"
#define D_OTHER_PARAMETERS "Други параметри"
#define D_TEMPLATE "Template"
#define D_TEMPLATE "Модел"
#define D_ACTIVATE "Активирай"
#define D_WEB_ADMIN_PASSWORD "Парола на уеб администратора"
#define D_MQTT_ENABLE "Активиране на MQTT"
#define D_FRIENDLY_NAME "Приятелско име"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "Единично"
#define D_MULTI_DEVICE "Мулти"
#define D_CONFIGURE_TEMPLATE "Конфигуриране на модел"
#define D_TEMPLATE_PARAMETERS "Параметри на модел"
#define D_TEMPLATE_NAME "Име"
#define D_BASE_TYPE "Базиран на"
#define D_TEMPLATE_FLAGS "Флагове"
#define D_ALLOW_ADC0 "ADC0 вход"
#define D_ALLOW_PULLUP "Потребителски избор на pull-up"
#define D_SAVE_CONFIGURATION "Запазване на конфигурацията"
#define D_CONFIGURATION_SAVED "Конфигурацията е запазена"
#define D_CONFIGURATION_RESET "Конфигурацията е изчистена"
@ -482,8 +494,13 @@
#define D_TX20_SOUTH "Ю"
#define D_TX20_WEST "З"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Няма"
#define D_SENSOR_USER "Потребит."
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +582,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "h"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER_PER_HOUR "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Záložní topic"
#define D_FALSE "Nepravda"
#define D_FILE "Soubor"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Volná paměť"
#define D_FREQUENCY "Kmitočet"
#define D_GAS "Plyn"
@ -148,6 +149,7 @@
#define D_STOP "Stop"
#define D_SUBNET_MASK "Maska podsítě"
#define D_SUBSCRIBE_TO "Přihlaš se do"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "úspěšné."
#define D_SUNRISE "Svítání"
#define D_SUNSET "Soumrak"
@ -155,6 +157,7 @@
#define D_TO "do"
#define D_TOGGLE "Přepni"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Odešli"
#define D_TRUE "Pravda"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Pro používání prostředí Tasmota povolte JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ - prosím zaktualizujte"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNÍ<br/>prosím zaktualizujte"
#define D_WEBSERVER_ACTIVE_ON "Aktivní Web server"
#define D_WITH_IP_ADDRESS "na IP adrese"
#define D_WEBSERVER_STOPPED "Web server zastaven"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Další nastavení"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora"
#define D_MQTT_ENABLE "MQTT aktivní"
#define D_FRIENDLY_NAME "Friendly Name"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "single device"
#define D_MULTI_DEVICE "multi device"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Ulož nastavení"
#define D_CONFIGURATION_SAVED "Nastavení uloženo"
#define D_CONFIGURATION_RESET "Nastavení resetováno"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "J"
#define D_TX20_WEST "Z"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Není"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "hod"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
* Updated until v6.3.0.17
* Updated until v6.4.1.18
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Fallback-Topic"
#define D_FALSE "falsch"
#define D_FILE "Datei"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Freier Arbeitsspeicher"
#define D_FREQUENCY "Frequenz"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Stop"
#define D_SUBNET_MASK "Subnetzmaske"
#define D_SUBSCRIBE_TO "abonniere"
#define D_UNSUBSCRIBE_FROM "löse abo. von"
#define D_SUCCESSFUL "erfolgreich"
#define D_SUNRISE "Sonnenaufgang"
#define D_SUNSET "Sonnenuntergang"
@ -155,6 +157,7 @@
#define D_TO "zu"
#define D_TOGGLE "An/Aus"
#define D_TOPIC "topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Übertragen"
#define D_TRUE "wahr"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "JavaScript aktivieren um Tasmota benutzen zu können"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware - bitte upgraden"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMUM-Firmware<br/>bitte upgraden"
#define D_WEBSERVER_ACTIVE_ON "Web-Server aktiv bei"
#define D_WITH_IP_ADDRESS "mit IP-Adresse"
#define D_WEBSERVER_STOPPED "Web-Server angehalten"
@ -288,7 +291,8 @@
#define D_TELEMETRY_PERIOD "Telemetrieperiode"
#define D_OTHER_PARAMETERS "Sonstige Einstellungen"
#define D_TEMPLATE "Template"
#define D_TEMPLATE "Vorlage"
#define D_ACTIVATE "Aktivieren"
#define D_WEB_ADMIN_PASSWORD "Passwort für Web Oberfläche"
#define D_MQTT_ENABLE "MQTT aktivieren"
#define D_FRIENDLY_NAME "Name [friendly name]"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "Einzelnes Gerät"
#define D_MULTI_DEVICE "Mehrfachgerät"
#define D_CONFIGURE_TEMPLATE "Vorlage konfigurieren"
#define D_TEMPLATE_PARAMETERS "Vorlage Parameter"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "basiert auf"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "Nutzer pull-up Auswahl"
#define D_SAVE_CONFIGURATION "Konfiguration speichern"
#define D_CONFIGURATION_SAVED "Konfiguration gespeichert"
#define D_CONFIGURATION_RESET "Konfiguration zurücksetzen"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "None"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "h"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Fallback Topic"
#define D_FALSE "Ψευδές"
#define D_FILE "Αρχείο"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Ελεύθερη μνήμη"
#define D_FREQUENCY "Συχνότητα"
#define D_GAS "Αέριο"
@ -148,6 +149,7 @@
#define D_STOP "Τερματισμός"
#define D_SUBNET_MASK "Μάσκα υποδικτύου"
#define D_SUBSCRIBE_TO "Εγγραφή στο"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Επιτυχές"
#define D_SUNRISE "Σούρουπο"
#define D_SUNSET "Ηλιοβασίλεμα"
@ -155,6 +157,7 @@
#define D_TO "έως"
#define D_TOGGLE "Εναλλαγή"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Μετάδοση"
#define D_TRUE "Αληθές"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// webserver.ino
#define D_NOSCRIPT "To use Tasmota, please enable JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - παρακαλώ αναβαθμίστε"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware<br/>παρακαλώ αναβαθμίστε"
#define D_WEBSERVER_ACTIVE_ON "Ενεργός διακομιστής Web στο"
#define D_WITH_IP_ADDRESS "με διεύθυνση IP"
#define D_WEBSERVER_STOPPED "Ο διακομιστής Web σταμάτησε"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Άλλες παράμετροι"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Κωδικός διαχειριστή"
#define D_MQTT_ENABLE "Ενεργοποίηση MQTT"
#define D_FRIENDLY_NAME "Φιλική ονομασία"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "μονή συσκευή"
#define D_MULTI_DEVICE "πολλαπλές συσκευές"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Αποθήκευση ρυθμίσεων"
#define D_CONFIGURATION_SAVED "Οι ρυθμίσεις αποθηκεύτηκαν"
#define D_CONFIGURATION_RESET "Επαναφορά ρυθμίσεων"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "Ν"
#define D_TX20_WEST "Δ"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Κανένα"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Fallback Topic"
#define D_FALSE "False"
#define D_FILE "File"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Free Memory"
#define D_FREQUENCY "Frequency"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Stop"
#define D_SUBNET_MASK "Subnet Mask"
#define D_SUBSCRIBE_TO "Subscribe to"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Successful"
#define D_SUNRISE "Sunrise"
#define D_SUNSET "Sunset"
@ -155,6 +157,7 @@
#define D_TO "to"
#define D_TOGGLE "Toggle"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Transmit"
#define D_TRUE "True"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "To use Tasmota, please enable JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - please upgrade"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware<br/>please upgrade"
#define D_WEBSERVER_ACTIVE_ON "Web server active on"
#define D_WITH_IP_ADDRESS "with IP address"
#define D_WEBSERVER_STOPPED "Web server stopped"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Other parameters"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Web Admin Password"
#define D_MQTT_ENABLE "MQTT enable"
#define D_FRIENDLY_NAME "Friendly Name"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "single device"
#define D_MULTI_DEVICE "multi device"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Save configuration"
#define D_CONFIGURATION_SAVED "Configuration saved"
#define D_CONFIGURATION_RESET "Configuration reset"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "None"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,15 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -1,5 +1,5 @@
/*
es-AR.h - localization for Spanish - Argentina for Sonoff-Tasmota
es-ES.h - localization for Spanish - Spain for Sonoff-Tasmota
Copyright (C) 2019 Adrian Scillato
@ -17,8 +17,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _LANGUAGE_ES_AR_H_
#define _LANGUAGE_ES_AR_H_
#ifndef _LANGUAGE_ES_ES_H_
#define _LANGUAGE_ES_ES_H_
/*************************** ATTENTION *******************************\
*
@ -33,7 +33,7 @@
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
#define LANGUAGE_LCID 11274
#define LANGUAGE_LCID 1034
// HTML (ISO 639-1) Language Code
#define D_HTML_LANGUAGE "es"
@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "FallbackTopic"
#define D_FALSE "Falso"
#define D_FILE "Archivo"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Memoria Libre"
#define D_FREQUENCY "Frecuencia"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Detener"
#define D_SUBNET_MASK "Máscara Subred"
#define D_SUBSCRIBE_TO "Suscribir a"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Exitosa"
#define D_SUNRISE "Salida del Sol"
#define D_SUNSET "Puesta del Sol"
@ -155,6 +157,7 @@
#define D_TO "a"
#define D_TOGGLE "Conmutar"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Transmitir"
#define D_TRUE "Verdadero"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Habilitar JavaScript para usar Tasmota"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO - actualice por favor"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MÍNIMO<br/>actualice por favor"
#define D_WEBSERVER_ACTIVE_ON "Servidor web activo en"
#define D_WITH_IP_ADDRESS "con dirección IP"
#define D_WEBSERVER_STOPPED "Servidor web detenido"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Otros parámetros"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Clave Administrador Web"
#define D_MQTT_ENABLE "Habilitar MQTT"
#define D_FRIENDLY_NAME "Nombre Amigable"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "dispositivo simple"
#define D_MULTI_DEVICE "dispositivo múltiple"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Grabar configuración"
#define D_CONFIGURATION_SAVED "Configuración grabada"
#define D_CONFIGURATION_RESET "Configuración restablecida"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "O"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Ninguno"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
@ -633,4 +653,4 @@
#define D_UNIT_KWARH "kVArH"
#define D_UNIT_ANGLE "Grados"
#endif // _LANGUAGE_ES_AR_H_
#endif // _LANGUAGE_ES_ES_H_

View File

@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
* Updated until v6.3.0.17
* Updated until v6.4.1.18
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -93,13 +93,14 @@
#define D_FALLBACK_TOPIC "Topic de secours"
#define D_FALSE "Faux"
#define D_FILE "Fichier"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Mémoire libre"
#define D_FREQUENCY "Fréquence"
#define D_GAS "Gaz"
#define D_GATEWAY "Passerelle"
#define D_GROUP "Groupe"
#define D_HOST "Host"
#define D_HOSTNAME "Hostname"
#define D_HOST "Hôte"
#define D_HOSTNAME "Nom d'Hôte"
#define D_HUMIDITY "Humidité"
#define D_ILLUMINANCE "Éclairement"
#define D_IMMEDIATE "immédiat" // Button immediate
@ -138,7 +139,7 @@
#define D_RESTARTING "Redémarre"
#define D_RESTART_REASON "Raison du redémarrage"
#define D_RESTORE "restaurer"
#define D_RETAINED "retenu"
#define D_RETAINED "persistant" // MQTT
#define D_RULE "Règle"
#define D_SAVE "Enregistrer"
#define D_SENSOR "Capteur"
@ -147,7 +148,8 @@
#define D_STD_TIME "STD"
#define D_STOP "Stop"
#define D_SUBNET_MASK "Masque sous-réseau"
#define D_SUBSCRIBE_TO "Souscrire à"
#define D_SUBSCRIBE_TO "S'abonner à"
#define D_UNSUBSCRIBE_FROM "Se désabonner de"
#define D_SUCCESSFUL "Réussi"
#define D_SUNRISE "Lever du jour"
#define D_SUNSET "Tombée de la nuit"
@ -155,6 +157,7 @@
#define D_TO "à"
#define D_TOGGLE "Inverser"
#define D_TOPIC "Topic" // Keep MQTT keyword
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Transmettre"
#define D_TRUE "Vrai"
#define D_TVOC "TVOC"
@ -184,7 +187,7 @@
#define D_LEVEL_10 "level 1-0"
#define D_LEVEL_01 "level 0-1"
#define D_SERIAL_LOGGING_DISABLED "Journalisation série désactivée"
#define D_SYSLOG_LOGGING_REENABLED "Jounalisation syslog réactivée"
#define D_SYSLOG_LOGGING_REENABLED "Jounalisation SysLog réactivée"
#define D_SET_BAUDRATE_TO "Définir le débit à"
#define D_RECEIVED_TOPIC "Topic reçu" // Terme MQTT
@ -209,7 +212,7 @@
#define D_QUERY_DONE "Requête terminée. Services MQTT trouvés"
#define D_MQTT_SERVICE_FOUND "Service MQTT trouvé sur"
#define D_FOUND_AT "trouvé à"
#define D_SYSLOG_HOST_NOT_FOUND "Host syslog introuvable"
#define D_SYSLOG_HOST_NOT_FOUND "Hôte SysLog introuvable"
// settings.ino
#define D_SAVED_TO_FLASH_AT "Enregistré en flash à"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Pour utiliser Tasmota, veuillez activer JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL - merci de mettre à jour"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMAL<br/>merci de mettre à jour"
#define D_WEBSERVER_ACTIVE_ON "Serveur web actif sur"
#define D_WITH_IP_ADDRESS "avec l'adresse IP"
#define D_WEBSERVER_STOPPED "Serveur web éteint"
@ -253,7 +256,7 @@
#define D_MODULE_PARAMETERS "Paramètres module"
#define D_MODULE_TYPE "Type de module"
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
#define D_PULLUP_ENABLE "Inter. sans pull-up"
#define D_GPIO "GPIO"
#define D_SERIAL_IN "Entrée série"
#define D_SERIAL_OUT "Sortie série"
@ -281,14 +284,15 @@
#define D_LOGGING_PARAMETERS "Paramètres du journal"
#define D_SERIAL_LOG_LEVEL "Niveau de journalisation série"
#define D_WEB_LOG_LEVEL "Niveau de journalisation web"
#define D_SYS_LOG_LEVEL "Niveau Syslog"
#define D_SYS_LOG_LEVEL "Niveau SysLog"
#define D_MORE_DEBUG "Plus de debug"
#define D_SYSLOG_HOST "Hôte Syslog"
#define D_SYSLOG_PORT "Port Syslog"
#define D_SYSLOG_HOST "Hôte SysLog"
#define D_SYSLOG_PORT "Port SysLog"
#define D_TELEMETRY_PERIOD "Période télémétrie"
#define D_OTHER_PARAMETERS "Autres paramètres"
#define D_TEMPLATE "Template"
#define D_TEMPLATE "Modèle"
#define D_ACTIVATE "Activer"
#define D_WEB_ADMIN_PASSWORD "Mot de passe Web Admin"
#define D_MQTT_ENABLE "MQTT activé"
#define D_FRIENDLY_NAME "Surnom"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "module unique"
#define D_MULTI_DEVICE "multi module"
#define D_CONFIGURE_TEMPLATE "Configuration du modèle"
#define D_TEMPLATE_PARAMETERS "Paramètres du modèle"
#define D_TEMPLATE_NAME "Nom"
#define D_BASE_TYPE "Basé sur"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "Entrée ADC0"
#define D_ALLOW_PULLUP "Pull-up utilisateur"
#define D_SAVE_CONFIGURATION "Enregistrer la configuration"
#define D_CONFIGURATION_SAVED "Configuration enregistrée"
#define D_CONFIGURATION_RESET "Configuration réinitialisée"
@ -332,7 +344,7 @@
#define D_UPLOAD_ERR_3 "L'octet magique n'est pas 0xE9"
#define D_UPLOAD_ERR_4 "La taille du programme à flasher est plus grande que la taille réelle de la mémoire flash"
#define D_UPLOAD_ERR_5 "Erreur de comparaison du buffer de téléchargement"
#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer Weblog 3"
#define D_UPLOAD_ERR_6 "Téléchargement échoué. Activer WebLog 3"
#define D_UPLOAD_ERR_7 "Téléchargement annulé"
#define D_UPLOAD_ERR_8 "Fichier invalide"
#define D_UPLOAD_ERR_9 "Fichier trop grand"
@ -343,7 +355,7 @@
#define D_UPLOAD_ERROR_CODE "Code d'erreur téléchargement"
#define D_ENTER_COMMAND "Saisir une commande"
#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer Weblog 2 si une réponse est attendue"
#define D_ENABLE_WEBLOG_FOR_RESPONSE "Activer WebLog 2 si une réponse est attendue"
#define D_NEED_USER_AND_PASSWORD "Nécessite utilisateur=<username>&password=<password>"
// xdrv_01_mqtt.ino
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "O"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Aucun"
#define D_SENSOR_USER "Utilisateur"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "h"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h"

View File

@ -54,21 +54,21 @@
#define D_ADMIN "מנהל"
#define D_AIR_QUALITY "איכות אוויר"
#define D_AP "AP" // Access Point
#define D_AS "as"
#define D_AUTO "AUTO"
#define D_AS ""
#define D_AUTO "אוטומטי"
#define D_BLINK "מהבהב"
#define D_BLINKOFF "כיבוי היבהוב"
#define D_BOOT_COUNT "מונה הפעלה מחדש"
#define D_BRIGHTLIGHT "בהירות"
#define D_BSSID "BSSId"
#define D_BUTTON "לחצן"
#define D_BY "by" // Written by me
#define D_BY "על ידי" // Written by me
#define D_BYTES "בייט"
#define D_CELSIUS "צלזיוס"
#define D_CHANNEL "ערוץ"
#define D_CO2 "Carbon dioxide"
#define D_CO2 "פחמן דו חמצני"
#define D_CODE "קוד" // Button code
#define D_COLDLIGHT "קור"
#define D_COLDLIGHT "אור קר"
#define D_COMMAND "פקודה"
#define D_CONNECTED "מחובר"
#define D_COUNT "סופר"
@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "נושא לחזרה"
#define D_FALSE "שגוי"
#define D_FILE "קובץ"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "זכרון פנוי"
#define D_FREQUENCY "תדר"
#define D_GAS "גז"
@ -112,7 +113,7 @@
#define D_LWT "LWT"
#define D_MODULE "מודול"
#define D_MQTT "MQTT"
#define D_MULTI_PRESS "multi-press"
#define D_MULTI_PRESS "לחיצה מרובה"
#define D_NOISE "רעש"
#define D_NONE "כלום"
#define D_OFF "כבוי"
@ -132,7 +133,7 @@
#define D_PROGRAM_FLASH_SIZE "גודל תוכנית פלאש"
#define D_PROGRAM_SIZE "גודל תוכנית"
#define D_PROJECT "פרויקט"
#define D_RAIN "Rain"
#define D_RAIN "גשם"
#define D_RECEIVED "התקבל"
#define D_RESTART "איתחול"
#define D_RESTARTING "הפעלה מחדש"
@ -148,6 +149,7 @@
#define D_STOP "עצירה"
#define D_SUBNET_MASK "רשת מסכת משנה"
#define D_SUBSCRIBE_TO "הרשם ל"
#define D_UNSUBSCRIBE_FROM "בטל רישום"
#define D_SUCCESSFUL "הצליח"
#define D_SUNRISE "זריחה"
#define D_SUNSET "שקיעה"
@ -155,6 +157,7 @@
#define D_TO "ל"
#define D_TOGGLE "מתג"
#define D_TOPIC "נושא"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "עבר"
#define D_TRUE "נכון"
#define D_TVOC "TVOC"
@ -175,61 +178,61 @@
#define D_UV_POWER "UV Power"
#define D_VERSION "גרסה"
#define D_VOLTAGE "מתח"
#define D_WEIGHT "Weight"
#define D_WEIGHT "משקל"
#define D_WARMLIGHT "חום"
#define D_WEB_SERVER "Web שרת"
// sonoff.ino
#define D_WARNING_MINIMAL_VERSION "WARNING This version does not support persistent settings"
#define D_WARNING_MINIMAL_VERSION "אזהרה גרסה זו אינה תומכת בהגדרות קבועות"
#define D_LEVEL_10 "level 1-0"
#define D_LEVEL_01 "level 0-1"
#define D_SERIAL_LOGGING_DISABLED "Serial logging disabled"
#define D_SYSLOG_LOGGING_REENABLED "Syslog logging re-enabled"
#define D_SERIAL_LOGGING_DISABLED "רישום טורי מושבת"
#define D_SYSLOG_LOGGING_REENABLED "הופעל מחדש Syslog רישום"
#define D_SET_BAUDRATE_TO "Set Baudrate to"
#define D_RECEIVED_TOPIC "Received Topic"
#define D_DATA_SIZE "Data Size"
#define D_SET_BAUDRATE_TO "הגדר קצב שידור ל"
#define D_RECEIVED_TOPIC "Topic התקבל"
#define D_DATA_SIZE "גודל נתונים"
#define D_ANALOG_INPUT "אנלוגי"
// support.ino
#define D_OSWATCH "osWatch"
#define D_BLOCKED_LOOP "Blocked Loop"
#define D_WPS_FAILED_WITH_STATUS "WPSconfig FAILED with status"
#define D_ACTIVE_FOR_3_MINUTES "active for 3 minutes"
#define D_FAILED_TO_START "failed to start"
#define D_PATCH_ISSUE_2186 "Patch issue 2186"
#define D_CONNECTING_TO_AP "Connecting to AP"
#define D_IN_MODE "in mode"
#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connect failed as no IP address received"
#define D_CONNECT_FAILED_AP_NOT_REACHED "Connect failed as AP cannot be reached"
#define D_CONNECT_FAILED_WRONG_PASSWORD "Connect failed with AP incorrect password"
#define D_CONNECT_FAILED_AP_TIMEOUT "Connect failed with AP timeout"
#define D_ATTEMPTING_CONNECTION "Attempting connection..."
#define D_CHECKING_CONNECTION "Checking connection..."
#define D_QUERY_DONE "Query done. MQTT services found"
#define D_MQTT_SERVICE_FOUND "MQTT service found on"
#define D_FOUND_AT "found at"
#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host not found"
#define D_BLOCKED_LOOP "לולאות חסומות"
#define D_WPS_FAILED_WITH_STATUS "נכשל עם הסטטוס WPSconfig"
#define D_ACTIVE_FOR_3_MINUTES "פעיל במשך 3 דקות"
#define D_FAILED_TO_START "נכשל בנסיון להתחיל"
#define D_PATCH_ISSUE_2186 "בעית תיקון 2186"
#define D_CONNECTING_TO_AP "AP -מתחבר ל"
#define D_IN_MODE "במצב"
#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP החיבור נכשל מכיוון שלא התקבלה כתובת"
#define D_CONNECT_FAILED_AP_NOT_REACHED "זמין AP החיבור נכשל כיוון שאין"
#define D_CONNECT_FAILED_WRONG_PASSWORD "סיסמא שגויה , AP חיבור נכשל ל"
#define D_CONNECT_FAILED_AP_TIMEOUT "פג זמן המתנה , AP חיבור נכשל ל"
#define D_ATTEMPTING_CONNECTION "...מנסה להתחבר"
#define D_CHECKING_CONNECTION "...בודק חיבור"
#define D_QUERY_DONE "MQTT השאילתה נעשתה. נמצאו שירותי"
#define D_MQTT_SERVICE_FOUND "MQTT נמצאו שירותי"
#define D_FOUND_AT "נמצא ב"
#define D_SYSLOG_HOST_NOT_FOUND "לא נמצא Syslog מארח"
// settings.ino
#define D_SAVED_TO_FLASH_AT "Saved to flash at"
#define D_LOADED_FROM_FLASH_AT "Loaded from flash at"
#define D_SAVED_TO_FLASH_AT "נשמר לפלאש ב"
#define D_LOADED_FROM_FLASH_AT "נטען מהפלאש מ"
#define D_USE_DEFAULTS "השתמש בהגדרות ברירת המחדל"
#define D_ERASED_SECTOR "סקטור מחוק"
// xdrv_02_webserver.ino
#define D_NOSCRIPT "JavaScript - כדי להשתמש ב קושחה אסמוטה אנא הפעל"
#define D_NOSCRIPT "JavaScript - כדי להשתמש בקושחת אסמוטה אנא הפעל"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "קושחה מינימלית - בבקשה אנא שדרג"
#define D_WEBSERVER_ACTIVE_ON "Web server active on"
#define D_WITH_IP_ADDRESS "with IP address"
#define D_WEBSERVER_STOPPED "Web server stopped"
#define D_FILE_NOT_FOUND "File Not Found"
#define D_REDIRECTED "Redirected to captive portal"
#define D_WEBSERVER_ACTIVE_ON "שרת ווב פעיל"
#define D_WITH_IP_ADDRESS "IP עם כתובת"
#define D_WEBSERVER_STOPPED "שרת ווב הופסק"
#define D_FILE_NOT_FOUND "קובץ לא נמצא"
#define D_REDIRECTED "הופנה מחדש לפורטל"
#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "Wifimanager set AccessPoint and keep Station"
#define D_WIFIMANAGER_SET_ACCESSPOINT "Wifimanager set AccessPoint"
#define D_TRYING_TO_CONNECT "מנסה לחבר את ההתקן לרשת"
#define D_RESTART_IN "הפעלה מחדש תןך"
#define D_RESTART_IN "הפעלה מחדש תוך"
#define D_SECONDS "שניות"
#define D_DEVICE_WILL_RESTART "ההתקן יופעל מחדש בעוד מס' שניות"
#define D_BUTTON_TOGGLE "מצב"
@ -253,7 +256,7 @@
#define D_MODULE_PARAMETERS "מודול פרמטרים"
#define D_MODULE_TYPE "סוג מודול"
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
#define D_PULLUP_ENABLE "pull-up אין לחצן/מתג"
#define D_GPIO " רגל "
#define D_SERIAL_IN "כניסת סריאל"
#define D_SERIAL_OUT "יציאת סריאל"
@ -285,11 +288,12 @@
#define D_MORE_DEBUG "מיפוי נוסף"
#define D_SYSLOG_HOST "Syslog מארח"
#define D_SYSLOG_PORT "Syslog פורט"
#define D_TELEMETRY_PERIOD "Telemetry period"
#define D_TELEMETRY_PERIOD "זמן שידור"
#define D_OTHER_PARAMETERS "פרמטרים שונים"
#define D_TEMPLATE "Template"
#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל - אתר"
#define D_TEMPLATE "תבנית"
#define D_ACTIVATE "הפעל"
#define D_WEB_ADMIN_PASSWORD "סיסמת מנהל"
#define D_MQTT_ENABLE "MQTT אפשר"
#define D_FRIENDLY_NAME "שם ידידותי"
#define D_BELKIN_WEMO "Belkin WeMo"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "התקן בודד"
#define D_MULTI_DEVICE "התקנים"
#define D_CONFIGURE_TEMPLATE "הגדר תבנית"
#define D_TEMPLATE_PARAMETERS "פרמטרים של תבנית"
#define D_TEMPLATE_NAME "שם"
#define D_BASE_TYPE "מבוסס על"
#define D_TEMPLATE_FLAGS "אפשריות"
#define D_ALLOW_ADC0 "ADC0 כניסת"
#define D_ALLOW_PULLUP "pull-up בחירת משתמש עבור"
#define D_SAVE_CONFIGURATION "שמירת הגדרות"
#define D_CONFIGURATION_SAVED "הגדרות נשמרו"
#define D_CONFIGURATION_RESET "איפוס הגדרות"
@ -347,12 +359,12 @@
#define D_NEED_USER_AND_PASSWORD "Need user=<username>&password=<password>"
// xdrv_01_mqtt.ino
#define D_FINGERPRINT "Verify TLS fingerprint..."
#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to"
#define D_RETRY_IN "Retry in"
#define D_VERIFIED "Verified using Fingerprint"
#define D_INSECURE "Insecure connection due to invalid Fingerprint"
#define D_CONNECT_FAILED_TO "Connect failed to"
#define D_FINGERPRINT "...TLS אמת טביעת אצבע של"
#define D_TLS_CONNECT_FAILED_TO "נכשל TLS חיבור"
#define D_RETRY_IN "נסה שוב תוך"
#define D_VERIFIED "מאומת באמצעות טביעת אצבע"
#define D_INSECURE "חיבור לא מאובטח עקב טביעת אצבע לא חוקית"
#define D_CONNECT_FAILED_TO "חיבור נכשל ל"
// xplg_wemohue.ino
#define D_MULTICAST_DISABLED "Multicast disabled"
@ -364,38 +376,38 @@
#define D_WEMO_BASIC_EVENT "WeMo basic event"
#define D_WEMO_EVENT_SERVICE "WeMo event service"
#define D_WEMO_META_SERVICE "WeMo meta service"
#define D_WEMO_SETUP "WeMo setup"
#define D_RESPONSE_SENT "Response sent"
#define D_WEMO_SETUP "WeMo הגדרת"
#define D_RESPONSE_SENT "תגובה נשלחה"
#define D_HUE "Hue"
#define D_HUE_BRIDGE_SETUP "Hue setup"
#define D_HUE_BRIDGE_SETUP "Hue הגדרת"
#define D_HUE_API_NOT_IMPLEMENTED "Hue API not implemented"
#define D_HUE_API "Hue API"
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 response packets sent"
// xdrv_07_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz parameters"
#define D_DOMOTICZ_PARAMETERS "Domoticz פרמטרי"
#define D_DOMOTICZ_IDX "Idx"
#define D_DOMOTICZ_KEY_IDX "Key idx"
#define D_DOMOTICZ_SWITCH_IDX "Switch idx"
#define D_DOMOTICZ_SENSOR_IDX "Sensor idx"
#define D_DOMOTICZ_TEMP "Temp"
#define D_DOMOTICZ_TEMP_HUM "Temp,Hum"
#define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Hum,Baro"
#define D_DOMOTICZ_POWER_ENERGY "Power,Energy"
#define D_DOMOTICZ_ILLUMINANCE "Illuminance"
#define D_DOMOTICZ_TEMP "טמפרטורה"
#define D_DOMOTICZ_TEMP_HUM "טמפרטורה,לחות"
#define D_DOMOTICZ_TEMP_HUM_BARO "טמפרטורה,לחות,ברומטר"
#define D_DOMOTICZ_POWER_ENERGY "הספק,צריכה"
#define D_DOMOTICZ_ILLUMINANCE "עוצמת אור"
#define D_DOMOTICZ_COUNT "Count/PM1"
#define D_DOMOTICZ_VOLTAGE "Voltage/PM2.5"
#define D_DOMOTICZ_CURRENT "Current/PM10"
#define D_DOMOTICZ_AIRQUALITY "AirQuality"
#define D_DOMOTICZ_UPDATE_TIMER "Update timer"
#define D_DOMOTICZ_AIRQUALITY "איכות אוויר"
#define D_DOMOTICZ_UPDATE_TIMER "עדכן טיימר"
// xdrv_09_timers.ino
#define D_CONFIGURE_TIMER "הגדרות תזמון"
#define D_TIMER_PARAMETERS "פרמטרים עבור תזמון"
#define D_TIMER_ENABLE "אפשר תזמון"
#define D_TIMER_ARM "חמש"
#define D_TIMER_ARM "טען"
#define D_TIMER_TIME "זמן"
#define D_TIMER_DAYS "ימים"
#define D_TIMER_REPEAT "חזרות"
@ -403,25 +415,25 @@
#define D_TIMER_ACTION "פעולה"
// xdrv_10_knx.ino
#define D_CONFIGURE_KNX "Configure KNX"
#define D_KNX_PARAMETERS "KNX Parameters"
#define D_KNX_GENERAL_CONFIG "General"
#define D_KNX_PHYSICAL_ADDRESS "Physical Address"
#define D_CONFIGURE_KNX "KNX הגדר"
#define D_KNX_PARAMETERS "KNX פרמטרי"
#define D_KNX_GENERAL_CONFIG "כללי"
#define D_KNX_PHYSICAL_ADDRESS "כתובת פיזית"
#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Must be unique on the KNX network )"
#define D_KNX_ENABLE "Enable KNX"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "Data to Send to Group Addresses"
#define D_ADD "Add"
#define D_DELETE "Delete"
#define D_REPLY "Reply"
#define D_KNX_GROUP_ADDRESS_TO_READ "Group Addresses to Receive Data from"
#define D_KNX_ENABLE "KNX אפשר"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "נתונים לשליחה אל כתובות קבוצתיות"
#define D_ADD "הוסף"
#define D_DELETE "מחק"
#define D_REPLY "השב"
#define D_KNX_GROUP_ADDRESS_TO_READ "כתובות קבוצתיות לקבלת נתונים מ"
#define D_LOG_KNX "KNX: "
#define D_RECEIVED_FROM "Received from"
#define D_KNX_COMMAND_WRITE "Write"
#define D_KNX_COMMAND_READ "Read"
#define D_KNX_COMMAND_OTHER "Other"
#define D_SENT_TO "sent to"
#define D_RECEIVED_FROM "התקבל מאת"
#define D_KNX_COMMAND_WRITE "כתיבה"
#define D_KNX_COMMAND_READ "קריאה"
#define D_KNX_COMMAND_OTHER "אחר"
#define D_SENT_TO "נשלח ל"
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
#define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_ENHANCEMENT "שיפור התקשורת"
#define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX"
@ -431,16 +443,16 @@
#define D_ENERGY_TOTAL "צריכה כללית"
// xsns_05_ds18b20.ino
#define D_SENSOR_BUSY "Sensor busy"
#define D_SENSOR_CRC_ERROR "Sensor CRC error"
#define D_SENSORS_FOUND "Sensors found"
#define D_SENSOR_BUSY "שרת עסוק"
#define D_SENSOR_CRC_ERROR "בחיישן CRC שגיאת"
#define D_SENSORS_FOUND "חיישנים לא נמצאו"
// xsns_06_dht.ino
#define D_TIMEOUT_WAITING_FOR "Timeout waiting for"
#define D_START_SIGNAL_LOW "start signal low"
#define D_START_SIGNAL_HIGH "start signal high"
#define D_PULSE "pulse"
#define D_CHECKSUM_FAILURE "Checksum failure"
#define D_TIMEOUT_WAITING_FOR "הזמן הקצוב להמתנה"
#define D_START_SIGNAL_LOW "להתחיל אות נמוך"
#define D_START_SIGNAL_HIGH "להתחיל אות גבוה"
#define D_PULSE "פעימה"
#define D_CHECKSUM_FAILURE "בדיקת כשל נכשלה"
// xsns_07_sht1x.ino
#define D_SENSOR_DID_NOT_ACK_COMMAND "Sensor did not ACK command"
@ -449,7 +461,7 @@
// xsns_18_pms5003.ino
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
#define D_PARTICALS_BEYOND "Particals"
#define D_PARTICALS_BEYOND "חלקיקים"
// xsns_32_mpu6050.ino
#define D_AX_AXIS "Accel. X-Axis"
@ -460,30 +472,34 @@
#define D_GZ_AXIS "Gyro Z-Axis"
// xsns_34_hx711.ino
#define D_HX_CAL_REMOVE "Remove weigth"
#define D_HX_CAL_REFERENCE "Load reference weigth"
#define D_HX_CAL_DONE "Calibrated"
#define D_HX_CAL_FAIL "Calibration failed"
#define D_RESET_HX711 "Reset Scale"
#define D_CONFIGURE_HX711 "Configure Scale"
#define D_HX711_PARAMETERS "Scale parameters"
#define D_ITEM_WEIGHT "Item weight"
#define D_REFERENCE_WEIGHT "Reference weigth"
#define D_CALIBRATE "Calibrate"
#define D_CALIBRATION "Calibration"
#define D_HX_CAL_REMOVE "הסר משקל"
#define D_HX_CAL_REFERENCE "טען משקל התייחסות"
#define D_HX_CAL_DONE "מכויל"
#define D_HX_CAL_FAIL "כיול נכשל"
#define D_RESET_HX711 "אפס את קנה המידה"
#define D_CONFIGURE_HX711 "הגדר קנה מידה"
#define D_HX711_PARAMETERS "פרמטרים של קנה מידה"
#define D_ITEM_WEIGHT "משקל פריט"
#define D_REFERENCE_WEIGHT "משקל הפניה"
#define D_CALIBRATE "כייל"
#define D_CALIBRATION "כיול"
//xsns_35_tx20.ino
#define D_TX20_WIND_DIRECTION "Wind Direction"
#define D_TX20_WIND_SPEED "Wind Speed"
#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg"
#define D_TX20_WIND_SPEED_MAX "Wind Speed Max"
#define D_TX20_WIND_DIRECTION "כיוון הרוח"
#define D_TX20_WIND_SPEED "מהירות הרוח"
#define D_TX20_WIND_SPEED_AVG "מהירות הרוח ממוצעת"
#define D_TX20_WIND_SPEED_MAX "מהירות הרוח מקסימלית"
#define D_TX20_NORTH "N"
#define D_TX20_EAST "E"
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "None"
#define D_SENSOR_USER "משתמש"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -491,7 +507,7 @@
#define D_SENSOR_I2C_SCL "I2C SCL"
#define D_SENSOR_I2C_SDA "I2C SDA"
#define D_SENSOR_WS2812 "WS2812"
#define D_SENSOR_DFR562 "MP3 Player"
#define D_SENSOR_DFR562 "נגן מוזיקה"
#define D_SENSOR_IRSEND "IRsend"
#define D_SENSOR_SWITCH "מתג" // Suffix "1"
#define D_SENSOR_BUTTON "לחצן" // Suffix "1"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "fallback topik"
#define D_FALSE "Hamis"
#define D_FILE "Fájl"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Szabad memória"
#define D_FREQUENCY "Frekvencia"
#define D_GAS "Gáz"
@ -148,6 +149,7 @@
#define D_STOP "Leállítás"
#define D_SUBNET_MASK "Alhálózati maszk"
#define D_SUBSCRIBE_TO "Feliratkozás a(z)"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Sikeres"
#define D_SUNRISE "Napkelte"
#define D_SUNSET "Napnyugta"
@ -155,6 +157,7 @@
#define D_TO "-nak"
#define D_TOGGLE "Megfordítás"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Továbbít"
#define D_TRUE "Igaz"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "A Tasmota használatához engedélyezd a Javascriptet!"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware - frissítsd!"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMÁLIS firmware<br/>frissítsd!"
#define D_WEBSERVER_ACTIVE_ON "Webszerver aktív:"
#define D_WITH_IP_ADDRESS "IP cím:"
#define D_WEBSERVER_STOPPED "Webszerver leállítva"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Egyéb beállítások"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Web admin jelszó"
#define D_MQTT_ENABLE "MQTT engedélyezése"
#define D_FRIENDLY_NAME "Név"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "single device"
#define D_MULTI_DEVICE "multi device"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Beállítások mentése"
#define D_CONFIGURATION_SAVED "Beállítások elmentve"
#define D_CONFIGURATION_RESET "Beállítások visszaállítása"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "D"
#define D_TX20_WEST "NY"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Nincs"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "h"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Topic Riserva"
#define D_FALSE "Falso"
#define D_FILE "File"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Memoria Libera"
#define D_FREQUENCY "Frequenza"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Stop"
#define D_SUBNET_MASK "Maschera sottorete"
#define D_SUBSCRIBE_TO "Sottoscrivi a"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Riuscito"
#define D_SUNRISE "Alba"
#define D_SUNSET "Tramonto"
@ -155,6 +157,7 @@
#define D_TO "a"
#define D_TOGGLE "Toggle"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Trasmesso"
#define D_TRUE "Vero"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Abilitare JavaScript per utilizzare Tasmota"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - effettuare aggiornamento"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware<br/>effettuare aggiornamento"
#define D_WEBSERVER_ACTIVE_ON "Web server attivo su"
#define D_WITH_IP_ADDRESS "con indirizzo IP"
#define D_WEBSERVER_STOPPED "Web server arrestato"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Altri parametri"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web"
#define D_MQTT_ENABLE "Abilita MQTT"
#define D_FRIENDLY_NAME "Nome confidenziale"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "dispositivo singolo"
#define D_MULTI_DEVICE "dispositivo multiplo"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Salva configurazione"
#define D_CONFIGURATION_SAVED "Configurazione salvata"
#define D_CONFIGURATION_RESET "Configurazione azzerata"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Nessuno"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

656
sonoff/language/ko-KO.h Normal file
View File

@ -0,0 +1,656 @@
/*
ko-KO.h - localization for Korean - Korean for Sonoff-Tasmota
Copyright (C) 2019 Theo Arends (translated by NyaamZ)
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/>.
*/
#ifndef _LANGUAGE_KO_KO_H_
#define _LANGUAGE_KO_KO_H_
/*************************** ATTENTION *******************************\
*
* Due to memory constraints only UTF-8 is supported.
* To save code space keep text as short as possible.
* Time and Date provided by SDK can not be localized (yet).
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
* Updated until v6.2.1.11
\*********************************************************************/
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
// https://www.science.co.il/language/Locale-codes.php
#define LANGUAGE_LCID 1042
// HTML (ISO 639-1) Language Code
#define D_HTML_LANGUAGE "ko"
// "2017-03-07T11:08:02" - ISO8601:2004
#define D_YEAR_MONTH_SEPARATOR "-"
#define D_MONTH_DAY_SEPARATOR "-"
#define D_DATE_TIME_SEPARATOR "T"
#define D_HOUR_MINUTE_SEPARATOR ":"
#define D_MINUTE_SECOND_SEPARATOR ":"
#define D_DAY3LIST "일 월 화 수 목 금 토 "
#define D_MONTH3LIST "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월11월12월"
// Non JSON decimal separator
#define D_DECIMAL_SEPARATOR "."
// Common
#define D_ADMIN "Admin"
#define D_AIR_QUALITY "공기질"
#define D_AP "AP" // Access Point
#define D_AS "as"
#define D_AUTO "자동"
#define D_BLINK "깜박임"
#define D_BLINKOFF "깜박임 끄기"
#define D_BOOT_COUNT "가동횟수"
#define D_BRIGHTLIGHT "밝기"
#define D_BSSID "BSSId"
#define D_BUTTON "버튼"
#define D_BY "by" // Written by me
#define D_BYTES "Bytes"
#define D_CELSIUS "섭씨"
#define D_CHANNEL "채널"
#define D_CO2 "이산화탄소"
#define D_CODE "코드" // Button code
#define D_COLDLIGHT "차갑게"
#define D_COMMAND "명령"
#define D_CONNECTED "연결됨"
#define D_COUNT "횟수"
#define D_COUNTER "Counter"
#define D_CURRENT "전류" // As in Voltage and Current
#define D_DATA "데이터"
#define D_DARKLIGHT "어둡게"
#define D_DEBUG "디버그"
#define D_DISABLED "사용 불가"
#define D_DISTANCE "거리"
#define D_DNS_SERVER "DNS 서버"
#define D_DONE "완료"
#define D_DST_TIME "DST"
#define D_ECO2 "eCO2"
#define D_EMULATION "에뮬레이션"
#define D_ENABLED "사용 가능"
#define D_ERASE "삭제"
#define D_ERROR "에러"
#define D_FAHRENHEIT "화씨"
#define D_FAILED "실패"
#define D_FALLBACK "Fallback"
#define D_FALLBACK_TOPIC "Fallback Topic"
#define D_FALSE "거짓"
#define D_FILE "파일"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "남은 메모리"
#define D_FREQUENCY "빈도"
#define D_GAS "가스"
#define D_GATEWAY "게이트웨이"
#define D_GROUP "그룹"
#define D_HOST "호스트"
#define D_HOSTNAME "호스트이름"
#define D_HUMIDITY "습도"
#define D_ILLUMINANCE "조도"
#define D_IMMEDIATE "immediate" // Button immediate
#define D_INDEX "인덱스"
#define D_INFO "정보"
#define D_INFRARED "적외선"
#define D_INITIALIZED "초기화 완료"
#define D_IP_ADDRESS "IP 주소"
#define D_LIGHT "밝게"
#define D_LWT "LWT"
#define D_MODULE "모듈"
#define D_MQTT "MQTT"
#define D_MULTI_PRESS "multi-press"
#define D_NOISE "소음"
#define D_NONE "없음"
#define D_OFF "꺼짐"
#define D_OFFLINE "오프라인"
#define D_OK "Ok"
#define D_ON "켜짐"
#define D_ONLINE "온라인"
#define D_PASSWORD "비밀번호"
#define D_PORT "포트"
#define D_POWER_FACTOR "Power Factor"
#define D_POWERUSAGE "전원"
#define D_POWERUSAGE_ACTIVE "Active Power"
#define D_POWERUSAGE_APPARENT "Apparent Power"
#define D_POWERUSAGE_REACTIVE "Reactive Power"
#define D_PRESSURE "기압"
#define D_PRESSUREATSEALEVEL "해수면기압"
#define D_PROGRAM_FLASH_SIZE "플래시 용량"
#define D_PROGRAM_SIZE "프로그램 용량"
#define D_PROJECT "프로젝트"
#define D_RAIN "비"
#define D_RECEIVED "받음"
#define D_RESTART "재시작"
#define D_RESTARTING "재시작 중"
#define D_RESTART_REASON "재시작 이유"
#define D_RESTORE "복구"
#define D_RETAINED "보류"
#define D_RULE "규칙"
#define D_SAVE "저장"
#define D_SENSOR "센서"
#define D_SSID "SSId"
#define D_START "시작"
#define D_STD_TIME "STD"
#define D_STOP "정지"
#define D_SUBNET_MASK "서브넷 마스크"
#define D_SUBSCRIBE_TO "구독"
#define D_UNSUBSCRIBE_FROM "구독 해제"
#define D_SUCCESSFUL "성공"
#define D_SUNRISE "일출"
#define D_SUNSET "일몰"
#define D_TEMPERATURE "온도"
#define D_TO "to"
#define D_TOGGLE "전환"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "전송"
#define D_TRUE "참"
#define D_TVOC "TVOC"
#define D_UPGRADE "업그레이드"
#define D_UPLOAD "업로드"
#define D_UPTIME "가동시간"
#define D_USER "User"
#define D_UTC_TIME "UTC"
#define D_UV_INDEX "UV 색인"
#define D_UV_INDEX_1 "낮음"
#define D_UV_INDEX_2 "보통"
#define D_UV_INDEX_3 "높음"
#define D_UV_INDEX_4 "위험"
#define D_UV_INDEX_5 "BurnL1/2"
#define D_UV_INDEX_6 "BurnL3"
#define D_UV_INDEX_7 "OoR" // Out of Range
#define D_UV_LEVEL "UV 레벨"
#define D_UV_POWER "UV 파워"
#define D_VERSION "버전"
#define D_VOLTAGE "전압"
#define D_WEIGHT "무게"
#define D_WARMLIGHT "따뜻하게"
#define D_WEB_SERVER "웹 서버"
// sonoff.ino
#define D_WARNING_MINIMAL_VERSION "경고: 이 버전은 영구 설정을 지원하지 않습니다"
#define D_LEVEL_10 "level 1-0"
#define D_LEVEL_01 "level 0-1"
#define D_SERIAL_LOGGING_DISABLED "Serial log 사용 안함"
#define D_SYSLOG_LOGGING_REENABLED "Syslog log 다시 사용"
#define D_SET_BAUDRATE_TO "Set Baudrate to"
#define D_RECEIVED_TOPIC "Received Topic"
#define D_DATA_SIZE "데이터 용량"
#define D_ANALOG_INPUT "아날로그"
// support.ino
#define D_OSWATCH "osWatch"
#define D_BLOCKED_LOOP "Blocked Loop"
#define D_WPS_FAILED_WITH_STATUS "WPS설정 실패"
#define D_ACTIVE_FOR_3_MINUTES "3분동안 활성화"
#define D_FAILED_TO_START "시작 실패"
#define D_PATCH_ISSUE_2186 "Patch issue 2186"
#define D_CONNECTING_TO_AP "AP에 연결 중"
#define D_IN_MODE "in mode"
#define D_CONNECT_FAILED_NO_IP_ADDRESS "IP 주소가 수신되지 않아 연결이 실패했습니다"
#define D_CONNECT_FAILED_AP_NOT_REACHED "연결이 닿지 않아 AP에 연결할 수 없습니다"
#define D_CONNECT_FAILED_WRONG_PASSWORD "비밀번호가 틀려 AP에 연결할 수 없습니다"
#define D_CONNECT_FAILED_AP_TIMEOUT "시간초과로 AP에 연결할 수 없습니다"
#define D_ATTEMPTING_CONNECTION "연결 시도 중..."
#define D_CHECKING_CONNECTION "연결 체크 중..."
#define D_QUERY_DONE "쿼리 완료. MQTT 서비스 발견"
#define D_MQTT_SERVICE_FOUND "MQTT 서비스 발견"
#define D_FOUND_AT "다음에서 발견"
#define D_SYSLOG_HOST_NOT_FOUND "Syslog 호스트가 발견되지 않았습니다"
// settings.ino
#define D_SAVED_TO_FLASH_AT "플래시에 저장"
#define D_LOADED_FROM_FLASH_AT "플래시에서 로드"
#define D_USE_DEFAULTS "디폴트 사용"
#define D_ERASED_SECTOR "삭제된 섹터"
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Tasmota를 사용하려면 JavaScript를 활성화 하십시오."
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware<br/>업그레이드가 필요합니다"
#define D_WEBSERVER_ACTIVE_ON "Web 서버 작동 중"
#define D_WITH_IP_ADDRESS "IP 주소"
#define D_WEBSERVER_STOPPED "Web 서버 멈춤"
#define D_FILE_NOT_FOUND "파일을 찾을 수 없습니다"
#define D_REDIRECTED "인증 페이지로 리디렉션"
#define D_WIFIMANAGER_SET_ACCESSPOINT_AND_STATION "와이파이 매니저가 AccessPoint와 keep Station을 설정"
#define D_WIFIMANAGER_SET_ACCESSPOINT "와이파이 매니저가 AccessPoint를 설정"
#define D_TRYING_TO_CONNECT "장치를 네트워크에 연결하려고 시도 중"
#define D_RESTART_IN "재시작"
#define D_SECONDS "초"
#define D_DEVICE_WILL_RESTART "이 장치는 몇 초 후 재시작됩니다"
#define D_BUTTON_TOGGLE "켜기/끄기"
#define D_CONFIGURATION "설정"
#define D_INFORMATION "정보"
#define D_FIRMWARE_UPGRADE "펌웨어 업그레이드"
#define D_CONSOLE "콘솔"
#define D_CONFIRM_RESTART "재시작"
#define D_CONFIGURE_MODULE "모듈 설정"
#define D_CONFIGURE_WIFI "WiFi 설정"
#define D_CONFIGURE_MQTT "MQTT 설정"
#define D_CONFIGURE_DOMOTICZ "Domoticz 설정"
#define D_CONFIGURE_LOGGING "로그 설정"
#define D_CONFIGURE_OTHER "기타 설정"
#define D_CONFIRM_RESET_CONFIGURATION "설정 초기화 확인"
#define D_RESET_CONFIGURATION "설정 초기화"
#define D_BACKUP_CONFIGURATION "백업 설정"
#define D_RESTORE_CONFIGURATION "복원 설정"
#define D_MAIN_MENU "메인 메뉴"
#define D_MODULE_PARAMETERS "모듈 상세"
#define D_MODULE_TYPE "모듈 타입"
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
#define D_GPIO "GPIO"
#define D_SERIAL_IN "Serial In"
#define D_SERIAL_OUT "Serial Out"
#define D_WIFI_PARAMETERS "Wifi 상세"
#define D_SCAN_FOR_WIFI_NETWORKS "Wifi 네트워크를 검색 중"
#define D_SCAN_DONE "검색 완료"
#define D_NO_NETWORKS_FOUND "발견된 네트워크가 없습니다"
#define D_REFRESH_TO_SCAN_AGAIN "검색 재시도"
#define D_DUPLICATE_ACCESSPOINT "중복된 AccessPoint"
#define D_SKIPPING_LOW_QUALITY "약한 네트워크 신호 무시"
#define D_RSSI "RSSI"
#define D_WEP "WEP"
#define D_WPA_PSK "WPA PSK"
#define D_WPA2_PSK "WPA2 PSK"
#define D_AP1_SSID "AP1 SSId"
#define D_AP1_PASSWORD "AP1 비밀번호"
#define D_AP2_SSID "AP2 SSId"
#define D_AP2_PASSWORD "AP2 비밀번호"
#define D_MQTT_PARAMETERS "MQTT 상세"
#define D_CLIENT "클라이언트"
#define D_FULL_TOPIC "Full Topic"
#define D_LOGGING_PARAMETERS "로그 상세"
#define D_SERIAL_LOG_LEVEL "시리얼 로그 레벨"
#define D_WEB_LOG_LEVEL "Web 로그 레벨"
#define D_SYS_LOG_LEVEL "Syslog 로그 레벨"
#define D_MORE_DEBUG "More debug"
#define D_SYSLOG_HOST "Syslog 호스트"
#define D_SYSLOG_PORT "Syslog 포트"
#define D_TELEMETRY_PERIOD "보고 주기"
#define D_OTHER_PARAMETERS "기타 상세"
#define D_TEMPLATE "템플릿"
#define D_ACTIVATE "활성"
#define D_WEB_ADMIN_PASSWORD "Web Admin 비밀번호"
#define D_MQTT_ENABLE "MQTT 사용"
#define D_FRIENDLY_NAME "별칭"
#define D_BELKIN_WEMO "Belkin WeMo"
#define D_HUE_BRIDGE "Hue Bridge"
#define D_SINGLE_DEVICE "single device"
#define D_MULTI_DEVICE "multi device"
#define D_CONFIGURE_TEMPLATE "템플릿 설정"
#define D_TEMPLATE_PARAMETERS "템플릿 상세"
#define D_TEMPLATE_NAME "이름"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "옵션"
#define D_ALLOW_ADC0 "ADC0 입력"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "설정 저장"
#define D_CONFIGURATION_SAVED "설정 저장 완료"
#define D_CONFIGURATION_RESET "설정 초기화"
#define D_PROGRAM_VERSION "프로그램 버전"
#define D_BUILD_DATE_AND_TIME "빌드 날짜"
#define D_CORE_AND_SDK_VERSION "Core/SDK 버전"
#define D_FLASH_WRITE_COUNT "플래시 쓰기 횟수"
#define D_MAC_ADDRESS "MAC 주소"
#define D_MQTT_HOST "MQTT 호스트"
#define D_MQTT_PORT "MQTT 포트"
#define D_MQTT_CLIENT "MQTT 클라이언트"
#define D_MQTT_USER "MQTT 아이디"
#define D_MQTT_TOPIC "MQTT Topic"
#define D_MQTT_GROUP_TOPIC "MQTT Group Topic"
#define D_MQTT_FULL_TOPIC "MQTT Full Topic"
#define D_MDNS_DISCOVERY "mDNS Discovery"
#define D_MDNS_ADVERTISE "mDNS Advertise"
#define D_ESP_CHIP_ID "ESP Chip Id"
#define D_FLASH_CHIP_ID "Flash Chip Id"
#define D_FLASH_CHIP_SIZE "Flash 용량"
#define D_FREE_PROGRAM_SPACE "여유 프로그램 공간"
#define D_UPGRADE_BY_WEBSERVER "웹 서버에서 업그레이드"
#define D_OTA_URL "OTA Url"
#define D_START_UPGRADE "업그레이드 시작"
#define D_UPGRADE_BY_FILE_UPLOAD "업로드 된 파일로 업그레이드"
#define D_UPLOAD_STARTED "업로드 시작됨"
#define D_UPGRADE_STARTED "업그레이드 시작됨"
#define D_UPLOAD_DONE "업그레이드 완료"
#define D_UPLOAD_ERR_1 "파일이 선택되지 않았습니다"
#define D_UPLOAD_ERR_2 "용량이 충분하지 않습니다"
#define D_UPLOAD_ERR_3 "Magic 바이트가 0xE9가 아닙니다"
#define D_UPLOAD_ERR_4 "플래시 프로그램이 실제 플래시 용량보다 큽니다"
#define D_UPLOAD_ERR_5 "업로드 버퍼가 일치하지 않습니다"
#define D_UPLOAD_ERR_6 "업로드 실패. 로그 3 사용"
#define D_UPLOAD_ERR_7 "업로드 중단"
#define D_UPLOAD_ERR_8 "파일이 유효하지 않습니다"
#define D_UPLOAD_ERR_9 "용량이 초과되었습니다"
#define D_UPLOAD_ERR_10 "RF chip 초기화 실패"
#define D_UPLOAD_ERR_11 "RF chip 삭제 실패"
#define D_UPLOAD_ERR_12 "RF chip 쓰기 실패"
#define D_UPLOAD_ERR_13 "RF 펌웨어 decode 실패"
#define D_UPLOAD_ERROR_CODE "업로드 에러 코드"
#define D_ENTER_COMMAND "명령 입력"
#define D_ENABLE_WEBLOG_FOR_RESPONSE "응답이 있다면 Weblog 2를 사용"
#define D_NEED_USER_AND_PASSWORD "user=<아이디>&password=<비밀번호> 필요"
// xdrv_01_mqtt.ino
#define D_FINGERPRINT "TLS 지문 확인..."
#define D_TLS_CONNECT_FAILED_TO "TLS 연결 실패"
#define D_RETRY_IN "재시도 중"
#define D_VERIFIED "지문 확인 완료"
#define D_INSECURE "유효하지 않은 지문으로 연결이 되지 않았습니다"
#define D_CONNECT_FAILED_TO "연결 실패"
// xplg_wemohue.ino
#define D_MULTICAST_DISABLED "Multicast 사용 불가"
#define D_MULTICAST_REJOINED "Multicast (다시)가입됨"
#define D_MULTICAST_JOIN_FAILED "Multicast 가입 실패"
#define D_FAILED_TO_SEND_RESPONSE "요청 전송 실패"
#define D_WEMO "WeMo"
#define D_WEMO_BASIC_EVENT "WeMo 기본 이벤트"
#define D_WEMO_EVENT_SERVICE "WeMo 이벤트 서비스"
#define D_WEMO_META_SERVICE "WeMo meta 서비스"
#define D_WEMO_SETUP "WeMo 설정"
#define D_RESPONSE_SENT "요청 전송됨"
#define D_HUE "Hue"
#define D_HUE_BRIDGE_SETUP "Hue 설정"
#define D_HUE_API_NOT_IMPLEMENTED "Hue API가 포함되지 않음"
#define D_HUE_API "Hue API"
#define D_HUE_POST_ARGS "Hue POST args"
#define D_3_RESPONSE_PACKETS_SENT "3 요청 패킷이 전송됨"
// xdrv_07_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Domoticz 상세"
#define D_DOMOTICZ_IDX "Idx"
#define D_DOMOTICZ_KEY_IDX "Key idx"
#define D_DOMOTICZ_SWITCH_IDX "스위치 idx"
#define D_DOMOTICZ_SENSOR_IDX "센서 idx"
#define D_DOMOTICZ_TEMP "온도"
#define D_DOMOTICZ_TEMP_HUM "온도,습도"
#define D_DOMOTICZ_TEMP_HUM_BARO "온도,습도,기압"
#define D_DOMOTICZ_POWER_ENERGY "전력,전력량"
#define D_DOMOTICZ_ILLUMINANCE "조도"
#define D_DOMOTICZ_COUNT "횟수/PM1"
#define D_DOMOTICZ_VOLTAGE "전압/PM2.5"
#define D_DOMOTICZ_CURRENT "전류/PM10"
#define D_DOMOTICZ_AIRQUALITY "공기질"
#define D_DOMOTICZ_UPDATE_TIMER "타이머 갱신"
// xdrv_09_timers.ino
#define D_CONFIGURE_TIMER "타이머 설정"
#define D_TIMER_PARAMETERS "타이머 상세"
#define D_TIMER_ENABLE "타이머 사용"
#define D_TIMER_ARM "Arm"
#define D_TIMER_TIME "시간"
#define D_TIMER_DAYS "일"
#define D_TIMER_REPEAT "반복"
#define D_TIMER_OUTPUT "출력"
#define D_TIMER_ACTION "행동"
// xdrv_10_knx.ino
#define D_CONFIGURE_KNX "KNX 설정"
#define D_KNX_PARAMETERS "KNX 상세"
#define D_KNX_GENERAL_CONFIG "일반"
#define D_KNX_PHYSICAL_ADDRESS "물리적 주소"
#define D_KNX_PHYSICAL_ADDRESS_NOTE "( KNX 네트워크 상에서 반드시 고유한 이름이어야 합니다 )"
#define D_KNX_ENABLE "KNX 사용"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "그룹 주소로 데이타를 보냅니다"
#define D_ADD "추가"
#define D_DELETE "삭제"
#define D_REPLY "응답"
#define D_KNX_GROUP_ADDRESS_TO_READ "받은 데이터의 그룹 주소"
#define D_LOG_KNX "KNX: "
#define D_RECEIVED_FROM "다음에서 받음"
#define D_KNX_COMMAND_WRITE "쓰기"
#define D_KNX_COMMAND_READ "읽기"
#define D_KNX_COMMAND_OTHER "기타"
#define D_SENT_TO "다음으로 보내기"
#define D_KNX_WARNING "그룹 주소 ( 0 / 0 / 0 )은 예약되어 사용할 수 없습니다"
#define D_KNX_ENHANCEMENT "커뮤니케이션 강화"
#define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX"
// xdrv_03_energy.ino
#define D_ENERGY_TODAY "금일 전력 사용량"
#define D_ENERGY_YESTERDAY "어제 전력 사용량"
#define D_ENERGY_TOTAL "총 전력 사용량"
// xsns_05_ds18b20.ino
#define D_SENSOR_BUSY "센서가 사용 중"
#define D_SENSOR_CRC_ERROR "센서 CRC 에러"
#define D_SENSORS_FOUND "센서 발견"
// xsns_06_dht.ino
#define D_TIMEOUT_WAITING_FOR "대기 시간 초과"
#define D_START_SIGNAL_LOW "시작 신호 낮음"
#define D_START_SIGNAL_HIGH "시작 신호 높음"
#define D_PULSE "pulse"
#define D_CHECKSUM_FAILURE "체크섬 실패"
// xsns_07_sht1x.ino
#define D_SENSOR_DID_NOT_ACK_COMMAND "센서가 ACK 명령을 수행하지 않음"
#define D_SHT1X_FOUND "SHT1X 발견"
// xsns_18_pms5003.ino
#define D_STANDARD_CONCENTRATION "CF-1 PM" // Standard Particle CF-1 Particle Matter
#define D_ENVIRONMENTAL_CONCENTRATION "PM" // Environmetal Particle Matter
#define D_PARTICALS_BEYOND "입자"
// xsns_32_mpu6050.ino
#define D_AX_AXIS "Accel. X-Axis"
#define D_AY_AXIS "Accel. Y-Axis"
#define D_AZ_AXIS "Accel. Z-Axis"
#define D_GX_AXIS "Gyro X-Axis"
#define D_GY_AXIS "Gyro Y-Axis"
#define D_GZ_AXIS "Gyro Z-Axis"
// xsns_34_hx711.ino
#define D_HX_CAL_REMOVE "중량 제거"
#define D_HX_CAL_REFERENCE "참조 중량 로드"
#define D_HX_CAL_DONE "교정됨"
#define D_HX_CAL_FAIL "교정 실패"
#define D_RESET_HX711 "스케일 초기화"
#define D_CONFIGURE_HX711 "스케일 설정"
#define D_HX711_PARAMETERS "스케일 상세"
#define D_ITEM_WEIGHT "아이템 중량"
#define D_REFERENCE_WEIGHT "참조 중량"
#define D_CALIBRATE "교정"
#define D_CALIBRATION "교정"
//xsns_35_tx20.ino
#define D_TX20_WIND_DIRECTION "풍향"
#define D_TX20_WIND_SPEED "풍속"
#define D_TX20_WIND_SPEED_AVG "평균 풍속"
#define D_TX20_WIND_SPEED_MAX "최대 풍속"
#define D_TX20_NORTH "N"
#define D_TX20_EAST "E"
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "없음"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
#define D_SENSOR_DS18X20 "DS18x20"
#define D_SENSOR_I2C_SCL "I2C SCL"
#define D_SENSOR_I2C_SDA "I2C SDA"
#define D_SENSOR_WS2812 "WS2812"
#define D_SENSOR_DFR562 "MP3 Player"
#define D_SENSOR_IRSEND "IRsend"
#define D_SENSOR_SWITCH "Switch" // Suffix "1"
#define D_SENSOR_BUTTON "Button" // Suffix "1"
#define D_SENSOR_RELAY "Relay" // Suffix "1i"
#define D_SENSOR_LED "Led" // Suffix "1i"
#define D_SENSOR_PWM "PWM" // Suffix "1"
#define D_SENSOR_COUNTER "Counter" // Suffix "1"
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
#define D_SENSOR_PZEM004_RX "PZEM004 Rx"
#define D_SENSOR_PZEM016_RX "PZEM016 Rx"
#define D_SENSOR_PZEM017_RX "PZEM017 Rx"
#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx"
#define D_SENSOR_SAIR_RX "SAir Rx"
#define D_SENSOR_SAIR_TX "SAir Tx"
#define D_SENSOR_SPI_CS "SPI CS"
#define D_SENSOR_SPI_DC "SPI DC"
#define D_SENSOR_BACKLIGHT "BkLight"
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
#define D_SENSOR_SBR_RX "SerBr Rx"
#define D_SENSOR_SBR_TX "SerBr Tx"
#define D_SENSOR_SR04_TRIG "SR04 Tri"
#define D_SENSOR_SR04_ECHO "SR04 Ech"
#define D_SENSOR_SDM120_TX "SDMx20 Tx"
#define D_SENSOR_SDM120_RX "SDMx20 Rx"
#define D_SENSOR_SDM630_TX "SDM630 Tx"
#define D_SENSOR_SDM630_RX "SDM630 Rx"
#define D_SENSOR_TM1638_CLK "TM16 CLK"
#define D_SENSOR_TM1638_DIO "TM16 DIO"
#define D_SENSOR_TM1638_STB "TM16 STB"
#define D_SENSOR_HX711_SCK "HX711 SCK"
#define D_SENSOR_HX711_DAT "HX711 DAT"
#define D_SENSOR_TX20_TX "TX20"
#define D_SENSOR_RFSEND "RFSend"
#define D_SENSOR_RFRECV "RFrecv"
#define D_SENSOR_TUYA_TX "Tuya Tx"
#define D_SENSOR_TUYA_RX "Tuya Rx"
#define D_SENSOR_MGC3130_XFER "MGC3130 Xfr"
#define D_SENSOR_MGC3130_RESET "MGC3130 Rst"
#define D_SENSOR_SSPI_MISO "SSPI MISO"
#define D_SENSOR_SSPI_MOSI "SSPI MOSI"
#define D_SENSOR_SSPI_SCLK "SSPI SCLK"
#define D_SENSOR_SSPI_CS "SSPI CS"
#define D_SENSOR_SSPI_DC "SSPI DC"
#define D_SENSOR_RF_SENSOR "RF Sensor"
#define D_SENSOR_AZ_RX "AZ Rx"
#define D_SENSOR_AZ_TX "AZ Tx"
#define D_SENSOR_MAX31855_CS "MX31855 CS"
#define D_SENSOR_MAX31855_CLK "MX31855 CLK"
#define D_SENSOR_MAX31855_DO "MX31855 DO"
#define D_SENSOR_NRG_SEL "HLWBL SEL" // Suffix "i"
#define D_SENSOR_NRG_CF1 "HLWBL CF1"
#define D_SENSOR_HLW_CF "HLW8012 CF"
#define D_SENSOR_HJL_CF "BL0937 CF"
#define D_SENSOR_MCP39F5_TX "MCP39F5 Tx"
#define D_SENSOR_MCP39F5_RX "MCP39F5 Rx"
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
#define D_SENSOR_PN532_TX "PN532 Tx"
#define D_SENSOR_PN532_RX "PN532 Rx"
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
#define D_SENSOR_SM16716_POWER "SM16716 PWR"
#define D_SENSOR_MY92X1_DI "MY92x1 DI"
#define D_SENSOR_MY92X1_DCKI "MY92x1 DCKI"
#define D_SENSOR_ARIRFRCV "ALux IrRcv"
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "시"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kOhm"
#define D_UNIT_KILOWATTHOUR "kWh"
#define D_UNIT_LUX "lx"
#define D_UNIT_MICROGRAM_PER_CUBIC_METER "ug/m3"
#define D_UNIT_MICROMETER "마이크로미터"
#define D_UNIT_MICROSECOND "마이크로초"
#define D_UNIT_MILLIAMPERE "mA"
#define D_UNIT_MILLIMETER "mm"
#define D_UNIT_MILLIMETER_MERCURY "mmHg"
#define D_UNIT_MILLISECOND "밀리초"
#define D_UNIT_MINUTE "분"
#define D_UNIT_PARTS_PER_BILLION "ppb"
#define D_UNIT_PARTS_PER_DECILITER "ppd"
#define D_UNIT_PARTS_PER_MILLION "ppm"
#define D_UNIT_PRESSURE "hPa"
#define D_UNIT_SECOND "초"
#define D_UNIT_SECTORS "섹터"
#define D_UNIT_VA "VA"
#define D_UNIT_VAR "VAr"
#define D_UNIT_VOLT "V"
#define D_UNIT_WATT "W"
#define D_UNIT_WATTHOUR "Wh"
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
// Log message prefix
#define D_LOG_APPLICATION "APP: " // Application
#define D_LOG_BRIDGE "BRG: " // Bridge
#define D_LOG_CONFIG "CFG: " // Settings
#define D_LOG_COMMAND "CMD: " // Command
#define D_LOG_DEBUG "DBG: " // Debug
#define D_LOG_DHT "DHT: " // DHT sensor
#define D_LOG_DOMOTICZ "DOM: " // Domoticz
#define D_LOG_DSB "DSB: " // DS18xB20 sensor
#define D_LOG_HTTP "HTP: " // HTTP webserver
#define D_LOG_I2C "I2C: " // I2C
#define D_LOG_IRR "IRR: " // Infra Red Received
#define D_LOG_LOG "LOG: " // Logging
#define D_LOG_MODULE "MOD: " // Module
#define D_LOG_MDNS "DNS: " // mDNS
#define D_LOG_MQTT "MQT: " // MQTT
#define D_LOG_OTHER "OTH: " // Other
#define D_LOG_RESULT "RSL: " // Result
#define D_LOG_RFR "RFR: " // RF Received
#define D_LOG_SERIAL "SER: " // Serial
#define D_LOG_SHT1 "SHT: " // SHT1x sensor
#define D_LOG_UPLOAD "UPL: " // Upload
#define D_LOG_UPNP "UPP: " // UPnP
#define D_LOG_WIFI "WIF: " // Wifi
//SDM220
#define D_PHASE_ANGLE "Phase Angle"
#define D_IMPORT_ACTIVE "Import Active"
#define D_EXPORT_ACTIVE "Export Active"
#define D_IMPORT_REACTIVE "Import Reactive"
#define D_EXPORT_REACTIVE "Export Reactive"
#define D_TOTAL_REACTIVE "Total Reactive"
#define D_UNIT_KWARH "kVArh"
#define D_UNIT_ANGLE "Deg"
#endif // _LANGUAGE_KO_KO_H_

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Fallback Topic"
#define D_FALSE "Onwaar"
#define D_FILE "Bestand"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Vrij geheugen"
#define D_FREQUENCY "Frequentie"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Stop"
#define D_SUBNET_MASK "Subnet Masker"
#define D_SUBSCRIBE_TO "Abonneer op"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Gelukt"
#define D_SUNRISE "Zonsopgang"
#define D_SUNSET "Zonsondergang"
@ -155,6 +157,7 @@
#define D_TO "naar"
#define D_TOGGLE "Toggle" // Wissel, Tuimel
#define D_TOPIC "Topic" // Onderwerp
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Verzend"
#define D_TRUE "Waar"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Zet JavaScript aan voor Tasmota"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - opwaarderen"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware<br/>opwaarderen"
#define D_WEBSERVER_ACTIVE_ON "Webserver actief op"
#define D_WITH_IP_ADDRESS "met IP adres"
#define D_WEBSERVER_STOPPED "Webserver gestopt"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Overige parameters"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Web Admin Wachtwoord"
#define D_MQTT_ENABLE "MQTT ingeschakeld"
#define D_FRIENDLY_NAME "Beschrijvende naam"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "een apparaat"
#define D_MULTI_DEVICE "meer apparaten"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Bewaar configuratie"
#define D_CONFIGURATION_SAVED "Configuratie opgeslagen"
#define D_CONFIGURATION_RESET "Configuratie ge-reset"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Geen"
#define D_SENSOR_USER "Gebruiker"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "h"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Zastępczy temat"
#define D_FALSE "Fałsz"
#define D_FILE "Plik"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Wolna pamięć"
#define D_FREQUENCY "Frequency"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Stop"
#define D_SUBNET_MASK "Maska podsieci"
#define D_SUBSCRIBE_TO "Subskrybuj do"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Powodzenie"
#define D_SUNRISE "Wschód słońca"
#define D_SUNSET "Zachód słońca"
@ -155,6 +157,7 @@
#define D_TO "do"
#define D_TOGGLE "Przełącz"
#define D_TOPIC "Temat"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Wyślij"
#define D_TRUE "Prawda"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL - proszę uaktualnić"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Oprogramowanie MINIMAL<br/>proszę uaktualnić"
#define D_WEBSERVER_ACTIVE_ON "Aktywny serwer Web"
#define D_WITH_IP_ADDRESS "z adresem IP"
#define D_WEBSERVER_STOPPED "Serwer Web zatrzymany"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Inne parametry"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Hasło administratora Web"
#define D_MQTT_ENABLE "MQTT aktywne"
#define D_FRIENDLY_NAME "Twoja nazwa"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "single device"
#define D_MULTI_DEVICE "multi device"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Zapisz ustawienia"
#define D_CONFIGURATION_SAVED "Ustawienia zapisane"
#define D_CONFIGURATION_RESET "Ustawienia zresetowane"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Brak"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Godz"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Tópico para retornar"
#define D_FALSE "Falso"
#define D_FILE "Arquivo"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Memória livre"
#define D_FREQUENCY "Frequência"
#define D_GAS "Gás"
@ -148,6 +149,7 @@
#define D_STOP "Parar"
#define D_SUBNET_MASK "Máscara sub rede"
#define D_SUBSCRIBE_TO "Subescrever para"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Successo"
#define D_SUNRISE "Nascer do sol"
#define D_SUNSET "Por do sol"
@ -155,6 +157,7 @@
#define D_TO "Para"
#define D_TOGGLE "Inverter"
#define D_TOPIC "Tópico"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Transmitir"
#define D_TRUE "Verdadeiro"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "To use Tasmota, please enable JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo - Atualizar por favor"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware mínimo<br/>Atualizar por favor"
#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em"
#define D_WITH_IP_ADDRESS "com o endereço IP"
#define D_WEBSERVER_STOPPED "Servidor WEB parou"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Outros parâmetros"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin"
#define D_MQTT_ENABLE "MQTT habilitado"
#define D_FRIENDLY_NAME "Nome amigável"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "Dispositivo único"
#define D_MULTI_DEVICE "Múltiplos dispositivos"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Gravar configuração"
#define D_CONFIGURATION_SAVED "Configuração gravada"
#define D_CONFIGURATION_RESET "Reinicialização da configuração"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Nenhum"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "H"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Tópico para retornar"
#define D_FALSE "Falso"
#define D_FILE "Ficheiro"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Memoria Livre"
#define D_FREQUENCY "Frequency"
#define D_GAS "Gás"
@ -148,6 +149,7 @@
#define D_STOP "Parar"
#define D_SUBNET_MASK "Mascara sub rede"
#define D_SUBSCRIBE_TO "Subescrever para"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Successo"
#define D_SUNRISE "Sunrise"
#define D_SUNSET "Sunset"
@ -155,6 +157,7 @@
#define D_TO "para"
#define D_TOGGLE "Pressionar"
#define D_TOPIC "Tópico"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Transmitir"
#define D_TRUE "Verdadeiro"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "To use Tasmota, please enable JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware - Atualizar Por favor"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMO firmware<br/>Atualizar Por favor"
#define D_WEBSERVER_ACTIVE_ON "Servidor WEB ativo em"
#define D_WITH_IP_ADDRESS "com o endereço IP"
#define D_WEBSERVER_STOPPED "Servitor WEB parou"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Outros parametros"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Palavra Chave de WEB Admin"
#define D_MQTT_ENABLE "MQTT habilitado"
#define D_FRIENDLY_NAME "Nome amigável"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "dispositivo único"
#define D_MULTI_DEVICE "multiplos dispositivos"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Salvar configuração"
#define D_CONFIGURATION_SAVED "Configuração guardada"
#define D_CONFIGURATION_RESET "Reinicialização da configuração"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Nenhum"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Топик обратной связи"
#define D_FALSE "Ложно"
#define D_FILE "Файл"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Свободная память"
#define D_FREQUENCY "Frequency"
#define D_GAS "Газ"
@ -148,6 +149,7 @@
#define D_STOP "Стоп"
#define D_SUBNET_MASK "Маска Подсети"
#define D_SUBSCRIBE_TO "Подписаться на"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Успешно"
#define D_SUNRISE "Sunrise"
#define D_SUNSET "Sunset"
@ -155,6 +157,7 @@
#define D_TO "до"
#define D_TOGGLE "Переключить"
#define D_TOPIC "Топик"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Передать"
#define D_TRUE "Истина"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "To use Tasmota, please enable JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL - пожалуйста обновите"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Прошивка MINIMAL<br/>пожалуйста обновите"
#define D_WEBSERVER_ACTIVE_ON "Веб-сервер активен"
#define D_WITH_IP_ADDRESS "с IP-адресом"
#define D_WEBSERVER_STOPPED "Веб-сервер остановлен"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Параметры Прочие"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Пароль Web администратора"
#define D_MQTT_ENABLE "MQTT активен"
#define D_FRIENDLY_NAME "Дружественное Имя"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "одиночное"
#define D_MULTI_DEVICE "мульти"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Сохранить конфигурацию"
#define D_CONFIGURATION_SAVED "Конфигурация сохранена "
#define D_CONFIGURATION_RESET "Конфигурация сброшена"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "-нет-"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "А"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Ч"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -75,6 +75,7 @@
#define D_COUNTER "Počítadlo"
#define D_CURRENT "Prúd" // As in Voltage and Current
#define D_DATA "Dáta"
#define D_FLOW_RATE "Flow rate"
#define D_DARKLIGHT "Tmavý"
#define D_DEBUG "Debug"
#define D_DISABLED "Zablokované"
@ -148,6 +149,7 @@
#define D_STOP "Stop"
#define D_SUBNET_MASK "Maska podsiete"
#define D_SUBSCRIBE_TO "Prihlásiť do"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "úspešné."
#define D_SUNRISE "Svitanie"
#define D_SUNSET "Súmrak"
@ -155,6 +157,7 @@
#define D_TO "do"
#define D_TOGGLE "Prepni"
#define D_TOPIC "Topic"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Odošli"
#define D_TRUE "Pravda"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Pre používanie prostredia Tasmota povoľte JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY - prosím aktualizujte"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Firmware MINIMÁLNY<br/>prosím aktualizujte"
#define D_WEBSERVER_ACTIVE_ON "Aktívny Web server"
#define D_WITH_IP_ADDRESS "na IP adrese"
#define D_WEBSERVER_STOPPED "Web server zastavený"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Ostatné nastavenia"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Heslo Web administrátora"
#define D_MQTT_ENABLE "MQTT aktívne"
#define D_FRIENDLY_NAME "Friendly Name"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "single device"
#define D_MULTI_DEVICE "multi device"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Ulož nastavenia"
#define D_CONFIGURATION_SAVED "Nastavenia uložené"
#define D_CONFIGURATION_RESET "Nastavenia resetované"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "J"
#define D_TX20_WEST "Z"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Žiaden"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "hod"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Reservämne"
#define D_FALSE "Falskt"
#define D_FILE "Fil"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Ledigt minne"
#define D_FREQUENCY "Frekvens"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Stoppa"
#define D_SUBNET_MASK "Nätmask"
#define D_SUBSCRIBE_TO "Prenumera på"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Lyckat"
#define D_SUNRISE "Soluppgång"
#define D_SUNSET "Solnedgång"
@ -155,6 +157,7 @@
#define D_TO "till"
#define D_TOGGLE "Växla"
#define D_TOPIC "Ämne"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "Sänd"
#define D_TRUE "Sant"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "För att använda Tasmota, aktivera JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware - var god uppgradera"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "MINIMAL firmware<br/>var god uppgradera"
#define D_WEBSERVER_ACTIVE_ON "Webbserver aktiv på"
#define D_WITH_IP_ADDRESS "med IP-adress"
#define D_WEBSERVER_STOPPED "Webbserver stoppad"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Andra parametrar"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Webbadmin-lösenord"
#define D_MQTT_ENABLE "MQTT aktivera"
#define D_FRIENDLY_NAME "Läsbart namn"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "soloenhet"
#define D_MULTI_DEVICE "multienhet"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Spara konfiguration"
#define D_CONFIGURATION_SAVED "Konfiguration sparad"
#define D_CONFIGURATION_RESET "Konfiguration nollställd"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "V"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Ingen"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,12 +581,16 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HERTZ "Hz"
#define D_UNIT_HOUR "Tim"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "ink"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

View File

@ -93,6 +93,7 @@
#define D_FALLBACK_TOPIC "Geri İletim Topiği"
#define D_FALSE "False"
#define D_FILE "Dosya"
#define D_FLOW_RATE "Flow rate"
#define D_FREE_MEMORY "Boş Hafıza"
#define D_FREQUENCY "Frekans"
#define D_GAS "Gas"
@ -148,6 +149,7 @@
#define D_STOP "Durdur"
#define D_SUBNET_MASK "Altağ Geçidi Maskesi"
#define D_SUBSCRIBE_TO "Abone olunan"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUCCESSFUL "Başarıyla Tamamlandı"
#define D_SUNRISE "Gün doğumu"
#define D_SUNSET "Gün batımı"
@ -155,6 +157,7 @@
#define D_TO "den"
#define D_TOGGLE "Geçiş Tuşu"
#define D_TOPIC "Başlık"
#define D_TOTAL_USAGE "Total Usage"
#define D_TRANSMIT "İletim"
#define D_TRUE "True"
#define D_TVOC "TVOC"
@ -219,7 +222,7 @@
// xdrv_02_webserver.ino
#define D_NOSCRIPT "To use Tasmota, please enable JavaScript"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük, lütfen yükseltin"
#define D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "Donanım yazılımı çok düşük<br/>lütfen yükseltin"
#define D_WEBSERVER_ACTIVE_ON "Web sunucusu aktif"
#define D_WITH_IP_ADDRESS "IP adres ile"
#define D_WEBSERVER_STOPPED "Web sunucusu durdu"
@ -289,6 +292,7 @@
#define D_OTHER_PARAMETERS "Diğer parametreler"
#define D_TEMPLATE "Template"
#define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Web Yönetici Şifresi"
#define D_MQTT_ENABLE "MQTT aktif"
#define D_FRIENDLY_NAME "Kullanıcı Dostu İsim"
@ -297,6 +301,14 @@
#define D_SINGLE_DEVICE "tekli cihaz"
#define D_MULTI_DEVICE "çoklu cihaz"
#define D_CONFIGURE_TEMPLATE "Configure Template"
#define D_TEMPLATE_PARAMETERS "Template parameters"
#define D_TEMPLATE_NAME "Name"
#define D_BASE_TYPE "Based on"
#define D_TEMPLATE_FLAGS "Options"
#define D_ALLOW_ADC0 "ADC0 input"
#define D_ALLOW_PULLUP "User pull-up selection"
#define D_SAVE_CONFIGURATION "Ayarları Kaydet"
#define D_CONFIGURATION_SAVED "Ayarlar kaydedildi"
#define D_CONFIGURATION_RESET "Ayarlar resetlendi"
@ -482,8 +494,12 @@
#define D_TX20_SOUTH "S"
#define D_TX20_WEST "W"
//xsns_43_hre.ino
#define D_LOG_HRE "HRE: "
// sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "None"
#define D_SENSOR_USER "User"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -565,11 +581,15 @@
#define D_SENSOR_TXD "Serial Tx"
#define D_SENSOR_RXD "Serial Rx"
#define D_SENSOR_ROTARY "Rotary" // Suffix "1A"
#define D_SENSOR_HRE_CLOCK "HRE Clock"
#define D_SENSOR_HRE_DATA "HRE Data"
// Units
#define D_UNIT_AMPERE "A"
#define D_UNIT_CENTIMETER "cm"
#define D_UNIT_HOUR "Hr"
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"

Some files were not shown because too many files have changed in this diff Show More