Merge branch 'development' into teleinfo

This commit is contained in:
Charles 2020-06-19 02:31:05 +02:00
commit 19a63e944c
78 changed files with 11463 additions and 978 deletions

View File

@ -77,6 +77,7 @@
| USE_MAX31855 | - | - | - | - | x | - | - | | USE_MAX31855 | - | - | - | - | x | - | - |
| USE_MAX31865 | - | - | - | - | - | - | - | | USE_MAX31865 | - | - | - | - | - | - | - |
| USE_THERMOSTAT | - | - | - | - | - | - | - | | USE_THERMOSTAT | - | - | - | - | - | - | - |
| USE_LMT01 | - | - | - | - | x | - | - |
| | | | | | | | | | | | | | | | | |
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks | Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
| USE_I2C | - | - | x | x | x | - | x | | USE_I2C | - | - | x | x | x | - | x |
@ -181,3 +182,4 @@
|-----------------------|---------|-------|--------|-----|---------|----|---------|--------|-------- |-----------------------|---------|-------|--------|-----|---------|----|---------|--------|--------
| USE_MI_ESP32 | - | - | - | - | - | - | - | - | | USE_MI_ESP32 | - | - | - | - | - | - | - | - |
| USE_WEBCAM | - | - | - | - | - | - | - | x | | USE_WEBCAM | - | - | - | - | - | - | - | x |
| USE_ETHERNET | - | - | - | - | - | - | - | - |

View File

@ -52,16 +52,20 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
## Changelog ## Changelog
### Version 8.3.1.5 ### Version 8.3.1.6
- Change IRremoteESP8266 library updated to v2.7.7 - Change IRremoteESP8266 library updated to v2.7.7
- Change Adafruit_SGP30 library from v1.0.3 to v1.2.0 (#8519) - Change Adafruit_SGP30 library from v1.0.3 to v1.2.0 (#8519)
- Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]`` - Change Energy JSON Total field from ``"Total":[33.736,11.717,16.978]`` to ``"Total":33.736,"TotalTariff":[11.717,16.978]``
- Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]`` - Change Energy JSON ExportActive field from ``"ExportActive":[33.736,11.717,16.978]`` to ``"ExportActive":33.736,"ExportTariff":[11.717,16.978]``
- Change ESP32 USER GPIO template representation decreasing template message size
- Change define USE_TASMOTA_SLAVE into USE_TASMOTA_CLIENT
- Change commands ``SlaveSend`` and ``SlaveReset`` into ``ClientSend`` and ``ClientReset``
- Fix escape of non-JSON received serial data (#8329) - Fix escape of non-JSON received serial data (#8329)
- Add command ``Rule0`` to change global rule parameters - Add command ``Rule0`` to change global rule parameters
- Add command ``Time 4`` to display timestamp using milliseconds (#8537) - Add command ``Time 4`` to display timestamp using milliseconds (#8537)
- Add command ``SetOption94 0/1`` to select MAX31855 or MAX6675 thermocouple support (#8616) - Add command ``SetOption94 0/1`` to select MAX31855 or MAX6675 thermocouple support (#8616)
- Add command ``Module2`` to configure fallback module on fast reboot (#8464)
- Add commands ``LedPwmOn 0..255``, ``LedPwmOff 0..255`` and ``LedPwmMode1 0/1`` to control led brightness by George (#8491) - Add commands ``LedPwmOn 0..255``, ``LedPwmOff 0..255`` and ``LedPwmMode1 0/1`` to control led brightness by George (#8491)
- Add ESP32 ethernet commands ``EthType 0/1``, ``EthAddress 0..31`` and ``EthClockMode 0..3`` - Add ESP32 ethernet commands ``EthType 0/1``, ``EthAddress 0..31`` and ``EthClockMode 0..3``
- Add support for unique MQTTClient (and inherited fallback topic) by full Mac address using ``mqttclient DVES_%12X`` (#8300) - Add support for unique MQTTClient (and inherited fallback topic) by full Mac address using ``mqttclient DVES_%12X`` (#8300)
@ -80,6 +84,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Add initial support for Telegram bot (#8619) - Add initial support for Telegram bot (#8619)
- Add support for HP303B Temperature and Pressure sensor by Robert Jaakke (#8638) - Add support for HP303B Temperature and Pressure sensor by Robert Jaakke (#8638)
- Add rule trigger ``System#Init`` to allow early rule execution without wifi and mqtt initialized yet - Add rule trigger ``System#Init`` to allow early rule execution without wifi and mqtt initialized yet
- Created Energy sensor (Denky) for French Smart Metering meter provided by global Energy Providers, need a adaptater. See dedicated full [blog](http://hallard.me/category/tinfo/) about French teleinformation stuff - Add support for Energy sensor (Denky) for French Smart Metering meter provided by global Energy Providers, need a adaptater. See dedicated full [blog](http://hallard.me/category/tinfo/) about French teleinformation stuff
- Added Library to be used for decoding Teleinfo (French Metering Smart Meter) - Add Library to be used for decoding Teleinfo (French Metering Smart Meter)
- Add basic support for ESP32 ethernet adding commands ``Wifi 0/1`` and ``Ethernet 0/1`` both default ON - Add basic support for ESP32 ethernet adding commands ``Wifi 0/1`` and ``Ethernet 0/1`` both default ON
- Add support for single wire LMT01 temperature Sensor by justifiably (#8713)

View File

@ -398,7 +398,7 @@ typedef struct __callback_assignment
} callback_assignment_t; } callback_assignment_t;
// FastPrecisePowf from tasmota/support_float.ino // FastPrecisePowf from tasmota/support_float.ino
extern float FastPrecisePowf(const float x, const float y); //extern float FastPrecisePowf(const float x, const float y);
class ESPKNXIP { class ESPKNXIP {
public: public:
@ -567,7 +567,7 @@ class ESPKNXIP {
callback_assignment_id_t __callback_register_assignment(address_t address, callback_id_t id); callback_assignment_id_t __callback_register_assignment(address_t address, callback_id_t id);
void __callback_delete_assignment(callback_assignment_id_t id); void __callback_delete_assignment(callback_assignment_id_t id);
static inline float pow(float a, float b) { return FastPrecisePowf(a, b); } //static inline float pow(float a, float b) { return FastPrecisePowf(a, b); }
ESP8266WebServer *server; ESP8266WebServer *server;
address_t physaddr; address_t physaddr;

1
lib/mbedtls/README.md Normal file
View File

@ -0,0 +1 @@
Stripped down library for aes-ccm-decryption in the MI_NRF24.ino.

View File

@ -0,0 +1,297 @@
/**
* \file aes.h
*
* \brief AES block cipher
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_AES_H
#define MBEDTLS_AES_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#include <stdint.h>
/* padlock.c and aesni.c rely on these values! */
#define MBEDTLS_AES_ENCRYPT 1
#define MBEDTLS_AES_DECRYPT 0
#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
#if !defined(MBEDTLS_AES_ALT)
// Regular implementation
//
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief AES context structure
*
* \note buf is able to hold 32 extra bytes, which can be used:
* - for alignment purposes if VIA padlock is used, and/or
* - to simplify key expansion in the 256-bit case by
* generating an extra round key
*/
typedef struct
{
int nr; /*!< number of rounds */
uint32_t *rk; /*!< AES round keys */
uint32_t buf[68]; /*!< unaligned data */
}
mbedtls_aes_context;
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void mbedtls_aes_init( mbedtls_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void mbedtls_aes_free( mbedtls_aes_context *ctx );
/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
*/
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see MBEDTLS_AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16],
unsigned char output[16] );
#ifdef __cplusplus
}
#endif
#else /* MBEDTLS_AES_ALT */
#include "aes_alt.h"
#endif /* MBEDTLS_AES_ALT */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mbedtls_aes_self_test( int verbose );
#ifdef __cplusplus
}
#endif
#endif /* aes.h */

View File

@ -0,0 +1,141 @@
/**
* \file ccm.h
*
* \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_CCM_H
#define MBEDTLS_CCM_H
#include "cipher.h"
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief CCM context structure
*/
typedef struct {
mbedtls_cipher_context_t cipher_ctx; /*!< cipher context used */
}
mbedtls_ccm_context;
/**
* \brief Initialize CCM context (just makes references valid)
* Makes the context ready for mbedtls_ccm_setkey() or
* mbedtls_ccm_free().
*
* \param ctx CCM context to initialize
*/
void mbedtls_ccm_init( mbedtls_ccm_context *ctx );
/**
* \brief CCM initialization (encryption and decryption)
*
* \param ctx CCM context to be initialized
* \param cipher cipher to use (a 128-bit block cipher)
* \param key encryption key
* \param keybits key size in bits (must be acceptable by the cipher)
*
* \return 0 if successful, or a cipher specific error code
*/
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits );
/**
* \brief Free a CCM context and underlying cipher sub-context
*
* \param ctx CCM context to free
*/
void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
/**
* \brief CCM buffer encryption
*
* \param ctx CCM context
* \param length length of the input data in bytes
* \param iv nonce (initialization vector)
* \param iv_len length of IV in bytes
* must be 2, 3, 4, 5, 6, 7 or 8
* \param add additional data
* \param add_len length of additional data in bytes
* must be less than 2^16 - 2^8
* \param input buffer holding the input data
* \param output buffer for holding the output data
* must be at least 'length' bytes wide
* \param tag buffer for holding the tag
* \param tag_len length of the tag to generate in bytes
* must be 4, 6, 8, 10, 14 or 16
*
* \note The tag is written to a separate buffer. To get the tag
* concatenated with the output as in the CCM spec, use
* tag = output + length and make sure the output buffer is
* at least length + tag_len wide.
*
* \return 0 if successful
*/
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );
/**
* \brief CCM buffer authenticated decryption
*
* \param ctx CCM context
* \param length length of the input data
* \param iv initialization vector
* \param iv_len length of IV
* \param add additional data
* \param add_len length of additional data
* \param input buffer holding the input data
* \param output buffer for holding the output data
* \param tag buffer holding the tag
* \param tag_len length of the tag
*
* \return 0 if successful and authenticated,
* MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match
*/
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int mbedtls_ccm_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CCM_H */

View File

@ -0,0 +1,628 @@
/**
* \file check_config.h
*
* \brief Consistency checks for configuration options
*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* It is recommended to include this file from your config.h
* in order to catch dependency issues early.
*/
#ifndef MBEDTLS_CHECK_CONFIG_H
#define MBEDTLS_CHECK_CONFIG_H
/*
* We assume CHAR_BIT is 8 in many places. In practice, this is true on our
* target platforms, so not an issue, but let's just be extra sure.
*/
#include <limits.h>
#if CHAR_BIT != 8
#error "mbed TLS requires a platform with 8-bit chars"
#endif
#if defined(_WIN32)
#if !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_C is required on Windows"
#endif
/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as
* it would confuse config.pl. */
#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \
!defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_SNPRINTF_ALT
#endif
#endif /* _WIN32 */
#if defined(TARGET_LIKE_MBED) && \
( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) )
#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS"
#endif
#if defined(MBEDTLS_DEPRECATED_WARNING) && \
!defined(__GNUC__) && !defined(__clang__)
#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang"
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME)
#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense"
#endif
#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_AESNI_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C)
#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C)
#error "MBEDTLS_DHM_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_CMAC_C) && \
!defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C)
#error "MBEDTLS_CMAC_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)
#error "MBEDTLS_ECDH_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDSA_C) && \
( !defined(MBEDTLS_ECP_C) || \
!defined(MBEDTLS_ASN1_PARSE_C) || \
!defined(MBEDTLS_ASN1_WRITE_C) )
#error "MBEDTLS_ECDSA_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECJPAKE_C) && \
( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) )
#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \
!defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) )
#error "MBEDTLS_ECP_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
!defined(MBEDTLS_SHA256_C))
#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \
defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64)
#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high"
#endif
#if defined(MBEDTLS_ENTROPY_C) && \
( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \
&& defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32)
#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high"
#endif
#if defined(MBEDTLS_ENTROPY_C) && \
defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C)
#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \
( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) )
#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \
( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \
defined(MBEDTLS_HAVEGE_C) )
#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too"
#endif
#if defined(MBEDTLS_GCM_C) && ( \
!defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) )
#error "MBEDTLS_GCM_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C)
#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C)
#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C)
#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \
!defined(MBEDTLS_ECDH_C)
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \
( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
!defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
!defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \
!defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) )
#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)
#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C)
#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PK_C) && \
( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) )
#error "MBEDTLS_PK_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C)
#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C)
#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C)
#error "MBEDTLS_PKCS11_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\
defined(MBEDTLS_PLATFORM_EXIT_ALT) )
#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\
( !defined(MBEDTLS_PLATFORM_C) ||\
!defined(MBEDTLS_HAVE_TIME) )
#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\
( !defined(MBEDTLS_PLATFORM_C) ||\
!defined(MBEDTLS_HAVE_TIME) )
#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\
( !defined(MBEDTLS_PLATFORM_C) ||\
!defined(MBEDTLS_HAVE_TIME) )
#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_TIME) ||\
defined(MBEDTLS_PLATFORM_TIME_ALT) )
#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_TIME) ||\
defined(MBEDTLS_PLATFORM_TIME_ALT) )
#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\
defined(MBEDTLS_PLATFORM_FPRINTF_ALT) )
#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\
defined(MBEDTLS_PLATFORM_STD_FREE)
#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO)
#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is"
#endif
#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\
defined(MBEDTLS_PLATFORM_STD_CALLOC)
#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO)
#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is"
#endif
#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\
defined(MBEDTLS_PLATFORM_PRINTF_ALT) )
#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\
defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) )
#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\
!defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY)
#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY)
#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY)
#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\
!defined(MBEDTLS_PLATFORM_EXIT_ALT)
#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\
( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\
!defined(MBEDTLS_HAVE_TIME) )
#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\
!defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\
!defined(MBEDTLS_PLATFORM_PRINTF_ALT)
#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\
!defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) )
#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\
!defined(MBEDTLS_ENTROPY_NV_SEED)
#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\
!defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\
!defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\
defined(MBEDTLS_PLATFORM_NV_SEED_ALT) )
#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\
( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\
defined(MBEDTLS_PLATFORM_NV_SEED_ALT) )
#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
#endif
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \
!defined(MBEDTLS_PKCS1_V15) )
#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled"
#endif
#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) )
#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \
!defined(MBEDTLS_SHA1_C) )
#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \
!defined(MBEDTLS_SHA1_C) )
#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \
!defined(MBEDTLS_SHA1_C) )
#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \
!defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) )
#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C)
#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \
!defined(MBEDTLS_MD_C) )
#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C)
#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2))
#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \
defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1))
#error "Illegal protocol selection"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1))
#error "Illegal protocol selection"
#endif
#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \
!defined(MBEDTLS_SSL_PROTO_TLS1_1)))
#error "Illegal protocol selection"
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS)
#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \
!defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
#endif
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites"
#endif
#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C)
#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \
!defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1)
#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \
!defined(MBEDTLS_X509_CRT_PARSE_C)
#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_THREADING_PTHREAD)
#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites"
#endif
#define MBEDTLS_THREADING_IMPL
#endif
#if defined(MBEDTLS_THREADING_ALT)
#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites"
#endif
#define MBEDTLS_THREADING_IMPL
#endif
#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL)
#error "MBEDTLS_THREADING_C defined, single threading implementation required"
#endif
#undef MBEDTLS_THREADING_IMPL
#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C)
#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \
!defined(MBEDTLS_PK_PARSE_C) )
#error "MBEDTLS_X509_USE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \
!defined(MBEDTLS_PK_WRITE_C) )
#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) )
#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) )
#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites"
#endif
/*
* Avoid warning from -pedantic. This is a convenient place for this
* workaround since this is included by every single file before the
* #if defined(MBEDTLS_xxx_C) that results in emtpy translation units.
*/
typedef int mbedtls_iso_c_forbids_empty_translation_units;
#endif /* MBEDTLS_CHECK_CONFIG_H */

View File

@ -0,0 +1,709 @@
/**
* \file cipher.h
*
* \brief Generic cipher wrapper.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_CIPHER_H
#define MBEDTLS_CIPHER_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
#define MBEDTLS_CIPHER_MODE_AEAD
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
#define MBEDTLS_CIPHER_MODE_WITH_PADDING
#endif
#if defined(MBEDTLS_ARC4_C)
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */
#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */
#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */
#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */
#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid, eg because it was free()ed. */
#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length */
#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length */
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
MBEDTLS_CIPHER_ID_NONE = 0,
MBEDTLS_CIPHER_ID_NULL,
MBEDTLS_CIPHER_ID_AES,
MBEDTLS_CIPHER_ID_DES,
MBEDTLS_CIPHER_ID_3DES,
MBEDTLS_CIPHER_ID_CAMELLIA,
MBEDTLS_CIPHER_ID_BLOWFISH,
MBEDTLS_CIPHER_ID_ARC4,
} mbedtls_cipher_id_t;
typedef enum {
MBEDTLS_CIPHER_NONE = 0,
MBEDTLS_CIPHER_NULL,
MBEDTLS_CIPHER_AES_128_ECB,
MBEDTLS_CIPHER_AES_192_ECB,
MBEDTLS_CIPHER_AES_256_ECB,
MBEDTLS_CIPHER_AES_128_CBC,
MBEDTLS_CIPHER_AES_192_CBC,
MBEDTLS_CIPHER_AES_256_CBC,
MBEDTLS_CIPHER_AES_128_CFB128,
MBEDTLS_CIPHER_AES_192_CFB128,
MBEDTLS_CIPHER_AES_256_CFB128,
MBEDTLS_CIPHER_AES_128_CTR,
MBEDTLS_CIPHER_AES_192_CTR,
MBEDTLS_CIPHER_AES_256_CTR,
MBEDTLS_CIPHER_AES_128_GCM,
MBEDTLS_CIPHER_AES_192_GCM,
MBEDTLS_CIPHER_AES_256_GCM,
MBEDTLS_CIPHER_CAMELLIA_128_ECB,
MBEDTLS_CIPHER_CAMELLIA_192_ECB,
MBEDTLS_CIPHER_CAMELLIA_256_ECB,
MBEDTLS_CIPHER_CAMELLIA_128_CBC,
MBEDTLS_CIPHER_CAMELLIA_192_CBC,
MBEDTLS_CIPHER_CAMELLIA_256_CBC,
MBEDTLS_CIPHER_CAMELLIA_128_CFB128,
MBEDTLS_CIPHER_CAMELLIA_192_CFB128,
MBEDTLS_CIPHER_CAMELLIA_256_CFB128,
MBEDTLS_CIPHER_CAMELLIA_128_CTR,
MBEDTLS_CIPHER_CAMELLIA_192_CTR,
MBEDTLS_CIPHER_CAMELLIA_256_CTR,
MBEDTLS_CIPHER_CAMELLIA_128_GCM,
MBEDTLS_CIPHER_CAMELLIA_192_GCM,
MBEDTLS_CIPHER_CAMELLIA_256_GCM,
MBEDTLS_CIPHER_DES_ECB,
MBEDTLS_CIPHER_DES_CBC,
MBEDTLS_CIPHER_DES_EDE_ECB,
MBEDTLS_CIPHER_DES_EDE_CBC,
MBEDTLS_CIPHER_DES_EDE3_ECB,
MBEDTLS_CIPHER_DES_EDE3_CBC,
MBEDTLS_CIPHER_BLOWFISH_ECB,
MBEDTLS_CIPHER_BLOWFISH_CBC,
MBEDTLS_CIPHER_BLOWFISH_CFB64,
MBEDTLS_CIPHER_BLOWFISH_CTR,
MBEDTLS_CIPHER_ARC4_128,
MBEDTLS_CIPHER_AES_128_CCM,
MBEDTLS_CIPHER_AES_192_CCM,
MBEDTLS_CIPHER_AES_256_CCM,
MBEDTLS_CIPHER_CAMELLIA_128_CCM,
MBEDTLS_CIPHER_CAMELLIA_192_CCM,
MBEDTLS_CIPHER_CAMELLIA_256_CCM,
} mbedtls_cipher_type_t;
typedef enum {
MBEDTLS_MODE_NONE = 0,
MBEDTLS_MODE_ECB,
MBEDTLS_MODE_CBC,
MBEDTLS_MODE_CFB,
MBEDTLS_MODE_OFB, /* Unused! */
MBEDTLS_MODE_CTR,
MBEDTLS_MODE_GCM,
MBEDTLS_MODE_STREAM,
MBEDTLS_MODE_CCM,
} mbedtls_cipher_mode_t;
typedef enum {
MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default) */
MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding */
MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding */
MBEDTLS_PADDING_ZEROS, /**< zero padding (not reversible!) */
MBEDTLS_PADDING_NONE, /**< never pad (full blocks only) */
} mbedtls_cipher_padding_t;
typedef enum {
MBEDTLS_OPERATION_NONE = -1,
MBEDTLS_DECRYPT = 0,
MBEDTLS_ENCRYPT,
} mbedtls_operation_t;
enum {
/** Undefined key length */
MBEDTLS_KEY_LENGTH_NONE = 0,
/** Key length, in bits (including parity), for DES keys */
MBEDTLS_KEY_LENGTH_DES = 64,
/** Key length, in bits (including parity), for DES in two key EDE */
MBEDTLS_KEY_LENGTH_DES_EDE = 128,
/** Key length, in bits (including parity), for DES in three-key EDE */
MBEDTLS_KEY_LENGTH_DES_EDE3 = 192,
};
/** Maximum length of any IV, in bytes */
#define MBEDTLS_MAX_IV_LENGTH 16
/** Maximum block size of any cipher, in bytes */
#define MBEDTLS_MAX_BLOCK_LENGTH 16
/**
* Base cipher information (opaque struct).
*/
typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t;
/**
* CMAC context (opaque struct).
*/
typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
/**
* Cipher information. Allows cipher functions to be called in a generic way.
*/
typedef struct {
/** Full cipher identifier (e.g. MBEDTLS_CIPHER_AES_256_CBC) */
mbedtls_cipher_type_t type;
/** Cipher mode (e.g. MBEDTLS_MODE_CBC) */
mbedtls_cipher_mode_t mode;
/** Cipher key length, in bits (default length for variable sized ciphers)
* (Includes parity bits for ciphers like DES) */
unsigned int key_bitlen;
/** Name of the cipher */
const char * name;
/** IV/NONCE size, in bytes.
* For cipher that accept many sizes: recommended size */
unsigned int iv_size;
/** Flags for variable IV size, variable key size, etc. */
int flags;
/** block size, in bytes */
unsigned int block_size;
/** Base cipher information and functions */
const mbedtls_cipher_base_t *base;
} mbedtls_cipher_info_t;
/**
* Generic cipher context.
*/
typedef struct {
/** Information about the associated cipher */
const mbedtls_cipher_info_t *cipher_info;
/** Key length to use */
int key_bitlen;
/** Operation that the context's key has been initialised for */
mbedtls_operation_t operation;
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
/** Padding functions to use, if relevant for cipher mode */
void (*add_padding)( unsigned char *output, size_t olen, size_t data_len );
int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len );
#endif
/** Buffer for data that hasn't been encrypted yet */
unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH];
/** Number of bytes that still need processing */
size_t unprocessed_len;
/** Current IV or NONCE_COUNTER for CTR-mode */
unsigned char iv[MBEDTLS_MAX_IV_LENGTH];
/** IV size in bytes (for ciphers with variable-length IVs) */
size_t iv_size;
/** Cipher-specific context */
void *cipher_ctx;
#if defined(MBEDTLS_CMAC_C)
/** CMAC Specific context */
mbedtls_cmac_context_t *cmac_ctx;
#endif
} mbedtls_cipher_context_t;
/**
* \brief Returns the list of ciphers supported by the generic cipher module.
*
* \return a statically allocated array of ciphers, the last entry
* is 0.
*/
const int *mbedtls_cipher_list( void );
/**
* \brief Returns the cipher information structure associated
* with the given cipher name.
*
* \param cipher_name Name of the cipher to search for.
*
* \return the cipher information structure associated with the
* given cipher_name, or NULL if not found.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name );
/**
* \brief Returns the cipher information structure associated
* with the given cipher type.
*
* \param cipher_type Type of the cipher to search for.
*
* \return the cipher information structure associated with the
* given cipher_type, or NULL if not found.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type );
/**
* \brief Returns the cipher information structure associated
* with the given cipher id, key size and mode.
*
* \param cipher_id Id of the cipher to search for
* (e.g. MBEDTLS_CIPHER_ID_AES)
* \param key_bitlen Length of the key in bits
* \param mode Cipher mode (e.g. MBEDTLS_MODE_CBC)
*
* \return the cipher information structure associated with the
* given cipher_type, or NULL if not found.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
int key_bitlen,
const mbedtls_cipher_mode_t mode );
/**
* \brief Initialize a cipher_context (as NONE)
*/
void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
/**
* \brief Free and clear the cipher-specific context of ctx.
* Freeing ctx itself remains the responsibility of the
* caller.
*/
void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
/**
* \brief Initialises and fills the cipher context structure with
* the appropriate values.
*
* \note Currently also clears structure. In future versions you
* will be required to call mbedtls_cipher_init() on the structure
* first.
*
* \param ctx context to initialise. May not be NULL.
* \param cipher_info cipher to use.
*
* \return 0 on success,
* MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on parameter failure,
* MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the
* cipher-specific context failed.
*/
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info );
/**
* \brief Returns the block size of the given cipher.
*
* \param ctx cipher's context. Must have been initialised.
*
* \return size of the cipher's blocks, or 0 if ctx has not been
* initialised.
*/
static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return 0;
return ctx->cipher_info->block_size;
}
/**
* \brief Returns the mode of operation for the cipher.
* (e.g. MBEDTLS_MODE_CBC)
*
* \param ctx cipher's context. Must have been initialised.
*
* \return mode of operation, or MBEDTLS_MODE_NONE if ctx
* has not been initialised.
*/
static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_MODE_NONE;
return ctx->cipher_info->mode;
}
/**
* \brief Returns the size of the cipher's IV/NONCE in bytes.
*
* \param ctx cipher's context. Must have been initialised.
*
* \return If IV has not been set yet: (recommended) IV size
* (0 for ciphers not using IV/NONCE).
* If IV has already been set: actual size.
*/
static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return 0;
if( ctx->iv_size != 0 )
return (int) ctx->iv_size;
return (int) ctx->cipher_info->iv_size;
}
/**
* \brief Returns the type of the given cipher.
*
* \param ctx cipher's context. Must have been initialised.
*
* \return type of the cipher, or MBEDTLS_CIPHER_NONE if ctx has
* not been initialised.
*/
static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_CIPHER_NONE;
return ctx->cipher_info->type;
}
/**
* \brief Returns the name of the given cipher, as a string.
*
* \param ctx cipher's context. Must have been initialised.
*
* \return name of the cipher, or NULL if ctx was not initialised.
*/
static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return 0;
return ctx->cipher_info->name;
}
/**
* \brief Returns the key length of the cipher.
*
* \param ctx cipher's context. Must have been initialised.
*
* \return cipher's key length, in bits, or
* MBEDTLS_KEY_LENGTH_NONE if ctx has not been
* initialised.
*/
static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_KEY_LENGTH_NONE;
return (int) ctx->cipher_info->key_bitlen;
}
/**
* \brief Returns the operation of the given cipher.
*
* \param ctx cipher's context. Must have been initialised.
*
* \return operation (MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT),
* or MBEDTLS_OPERATION_NONE if ctx has not been
* initialised.
*/
static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return MBEDTLS_OPERATION_NONE;
return ctx->operation;
}
/**
* \brief Set the key to use with the given context.
*
* \param ctx generic cipher context. May not be NULL. Must have been
* initialised using cipher_context_from_type or
* cipher_context_from_string.
* \param key The key to use.
* \param key_bitlen key length to use, in bits.
* \param operation Operation that the key will be used for, either
* MBEDTLS_ENCRYPT or MBEDTLS_DECRYPT.
*
* \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if
* parameter verification fails or a cipher specific
* error code.
*/
int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
int key_bitlen, const mbedtls_operation_t operation );
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
/**
* \brief Set padding mode, for cipher modes that use padding.
* (Default: PKCS7 padding.)
*
* \param ctx generic cipher context
* \param mode padding mode
*
* \returns 0 on success, MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE
* if selected padding mode is not supported, or
* MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
* does not support padding.
*/
int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode );
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
/**
* \brief Set the initialization vector (IV) or nonce
*
* \param ctx generic cipher context
* \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers)
* \param iv_len IV length for ciphers with variable-size IV;
* discarded by ciphers with fixed-size IV.
*
* \returns 0 on success, or MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
*
* \note Some ciphers don't use IVs nor NONCE. For these
* ciphers, this function has no effect.
*/
int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len );
/**
* \brief Finish preparation of the given context
*
* \param ctx generic cipher context
*
* \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA
* if parameter verification fails.
*/
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
#if defined(MBEDTLS_GCM_C)
/**
* \brief Add additional data (for AEAD ciphers).
* Currently only supported with GCM.
* Must be called exactly once, after mbedtls_cipher_reset().
*
* \param ctx generic cipher context
* \param ad Additional data to use.
* \param ad_len Length of ad.
*
* \return 0 on success, or a specific error code.
*/
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len );
#endif /* MBEDTLS_GCM_C */
/**
* \brief Generic cipher update function. Encrypts/decrypts
* using the given cipher context. Writes as many block
* size'd blocks of data as possible to output. Any data
* that cannot be written immediately will either be added
* to the next block, or flushed when cipher_final is
* called.
* Exception: for MBEDTLS_MODE_ECB, expects single block
* in size (e.g. 16 bytes for AES)
*
* \param ctx generic cipher context
* \param input buffer holding the input data
* \param ilen length of the input data
* \param output buffer for the output data. Should be able to hold at
* least ilen + block_size. Cannot be the same buffer as
* input!
* \param olen length of the output data, will be filled with the
* actual number of bytes written.
*
* \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if
* parameter verification fails,
* MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an
* unsupported mode for a cipher or a cipher specific
* error code.
*
* \note If the underlying cipher is GCM, all calls to this
* function, except the last one before mbedtls_cipher_finish(),
* must have ilen a multiple of the block size.
*/
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
size_t ilen, unsigned char *output, size_t *olen );
/**
* \brief Generic cipher finalisation function. If data still
* needs to be flushed from an incomplete block, data
* contained within it will be padded with the size of
* the last block, and written to the output buffer.
*
* \param ctx Generic cipher context
* \param output buffer to write data to. Needs block_size available.
* \param olen length of the data written to the output buffer.
*
* \returns 0 on success, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if
* parameter verification fails,
* MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
* expected a full block but was not provided one,
* MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding
* while decrypting or a cipher specific error code.
*/
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen );
#if defined(MBEDTLS_GCM_C)
/**
* \brief Write tag for AEAD ciphers.
* Currently only supported with GCM.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx Generic cipher context
* \param tag buffer to write the tag
* \param tag_len Length of the tag to write
*
* \return 0 on success, or a specific error code.
*/
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len );
/**
* \brief Check tag for AEAD ciphers.
* Currently only supported with GCM.
* Must be called after mbedtls_cipher_finish().
*
* \param ctx Generic cipher context
* \param tag Buffer holding the tag
* \param tag_len Length of the tag to check
*
* \return 0 on success, or a specific error code.
*/
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len );
#endif /* MBEDTLS_GCM_C */
/**
* \brief Generic all-in-one encryption/decryption
* (for all ciphers except AEAD constructs).
*
* \param ctx generic cipher context
* \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers)
* \param iv_len IV length for ciphers with variable-size IV;
* discarded by ciphers with fixed-size IV.
* \param input buffer holding the input data
* \param ilen length of the input data
* \param output buffer for the output data. Should be able to hold at
* least ilen + block_size. Cannot be the same buffer as
* input!
* \param olen length of the output data, will be filled with the
* actual number of bytes written.
*
* \note Some ciphers don't use IVs nor NONCE. For these
* ciphers, use iv = NULL and iv_len = 0.
*
* \returns 0 on success, or
* MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or
* MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED if decryption
* expected a full block but was not provided one, or
* MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding
* while decrypting, or
* a cipher specific error code.
*/
int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen );
#if defined(MBEDTLS_CIPHER_MODE_AEAD)
/**
* \brief Generic autenticated encryption (AEAD ciphers).
*
* \param ctx generic cipher context
* \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers)
* \param iv_len IV length for ciphers with variable-size IV;
* discarded by ciphers with fixed-size IV.
* \param ad Additional data to authenticate.
* \param ad_len Length of ad.
* \param input buffer holding the input data
* \param ilen length of the input data
* \param output buffer for the output data.
* Should be able to hold at least ilen.
* \param olen length of the output data, will be filled with the
* actual number of bytes written.
* \param tag buffer for the authentication tag
* \param tag_len desired tag length
*
* \returns 0 on success, or
* MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or
* a cipher specific error code.
*/
int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen,
unsigned char *tag, size_t tag_len );
/**
* \brief Generic autenticated decryption (AEAD ciphers).
*
* \param ctx generic cipher context
* \param iv IV to use (or NONCE_COUNTER for CTR-mode ciphers)
* \param iv_len IV length for ciphers with variable-size IV;
* discarded by ciphers with fixed-size IV.
* \param ad Additional data to be authenticated.
* \param ad_len Length of ad.
* \param input buffer holding the input data
* \param ilen length of the input data
* \param output buffer for the output data.
* Should be able to hold at least ilen.
* \param olen length of the output data, will be filled with the
* actual number of bytes written.
* \param tag buffer holding the authentication tag
* \param tag_len length of the authentication tag
*
* \returns 0 on success, or
* MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, or
* MBEDTLS_ERR_CIPHER_AUTH_FAILED if data isn't authentic,
* or a cipher specific error code.
*
* \note If the data is not authentic, then the output buffer
* is zeroed out to prevent the unauthentic plaintext to
* be used by mistake, making this interface safer.
*/
int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen,
const unsigned char *tag, size_t tag_len );
#endif /* MBEDTLS_CIPHER_MODE_AEAD */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CIPHER_H */

View File

@ -0,0 +1,109 @@
/**
* \file cipher_internal.h
*
* \brief Cipher wrappers.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_CIPHER_WRAP_H
#define MBEDTLS_CIPHER_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Base cipher information. The non-mode specific functions and values.
*/
struct mbedtls_cipher_base_t
{
/** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */
mbedtls_cipher_id_t cipher;
/** Encrypt using ECB */
int (*ecb_func)( void *ctx, mbedtls_operation_t mode,
const unsigned char *input, unsigned char *output );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/** Encrypt using CBC */
int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length,
unsigned char *iv, const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/** Encrypt using CFB (Full length) */
int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off,
unsigned char *iv, const unsigned char *input,
unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/** Encrypt using CTR */
int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
unsigned char *nonce_counter, unsigned char *stream_block,
const unsigned char *input, unsigned char *output );
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
/** Encrypt using STREAM */
int (*stream_func)( void *ctx, size_t length,
const unsigned char *input, unsigned char *output );
#endif
/** Set key for encryption purposes */
int (*setkey_enc_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen );
/** Set key for decryption purposes */
int (*setkey_dec_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen);
/** Allocate a new context */
void * (*ctx_alloc_func)( void );
/** Free the given context */
void (*ctx_free_func)( void *ctx );
};
typedef struct
{
mbedtls_cipher_type_t type;
const mbedtls_cipher_info_t *info;
} mbedtls_cipher_definition_t;
extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
extern int mbedtls_cipher_supported[];
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CIPHER_WRAP_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,295 @@
/**
* \file platform.h
*
* \brief mbed TLS Platform abstraction layer
*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_PLATFORM_H
#define MBEDTLS_PLATFORM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
#if defined(_WIN32)
#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< Default snprintf to use */
#else
#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use */
#endif
#endif
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF)
#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_FREE)
#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_EXIT)
#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_TIME)
#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS)
#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< Default exit value to use */
#endif
#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE)
#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< Default exit value to use */
#endif
#if defined(MBEDTLS_FS_IO)
#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ)
#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read
#endif
#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE)
#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write
#endif
#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE)
#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile"
#endif
#endif /* MBEDTLS_FS_IO */
#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR)
#include MBEDTLS_PLATFORM_STD_MEM_HDR
#endif
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
/* \} name SECTION: Module settings */
/*
* The function pointers for calloc and free
*/
#if defined(MBEDTLS_PLATFORM_MEMORY)
#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \
defined(MBEDTLS_PLATFORM_CALLOC_MACRO)
#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO
#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO
#else
/* For size_t */
#include <stddef.h>
extern void * (*mbedtls_calloc)( size_t n, size_t size );
extern void (*mbedtls_free)( void *ptr );
/**
* \brief Set your own memory implementation function pointers
*
* \param calloc_func the calloc function implementation
* \param free_func the free function implementation
*
* \return 0 if successful
*/
int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ),
void (*free_func)( void * ) );
#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */
#else /* !MBEDTLS_PLATFORM_MEMORY */
#define mbedtls_free free
#define mbedtls_calloc calloc
#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */
/*
* The function pointers for fprintf
*/
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
/* We need FILE * */
#include <stdio.h>
extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... );
/**
* \brief Set your own fprintf function pointer
*
* \param fprintf_func the fprintf function implementation
*
* \return 0
*/
int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *,
... ) );
#else
#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO)
#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO
#else
#define mbedtls_fprintf fprintf
#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */
#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
/*
* The function pointers for printf
*/
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)
extern int (*mbedtls_printf)( const char *format, ... );
/**
* \brief Set your own printf function pointer
*
* \param printf_func the printf function implementation
*
* \return 0
*/
int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) );
#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO)
#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO
#else
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */
#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */
/*
* The function pointers for snprintf
*
* The snprintf implementation should conform to C99:
* - it *must* always correctly zero-terminate the buffer
* (except when n == 0, then it must leave the buffer untouched)
* - however it is acceptable to return -1 instead of the required length when
* the destination buffer is too short.
*/
#if defined(_WIN32)
/* For Windows (inc. MSYS2), we provide our own fixed implementation */
int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... );
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... );
/**
* \brief Set your own snprintf function pointer
*
* \param snprintf_func the snprintf function implementation
*
* \return 0
*/
int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n,
const char * format, ... ) );
#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO
#else
#define mbedtls_snprintf snprintf
#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
/*
* The function pointers for exit
*/
#if defined(MBEDTLS_PLATFORM_EXIT_ALT)
extern void (*mbedtls_exit)( int status );
/**
* \brief Set your own exit function pointer
*
* \param exit_func the exit function implementation
*
* \return 0
*/
int mbedtls_platform_set_exit( void (*exit_func)( int status ) );
#else
#if defined(MBEDTLS_PLATFORM_EXIT_MACRO)
#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO
#else
#define mbedtls_exit exit
#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */
#endif /* MBEDTLS_PLATFORM_EXIT_ALT */
/*
* The default exit values
*/
#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS)
#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS
#else
#define MBEDTLS_EXIT_SUCCESS 0
#endif
#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE)
#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE
#else
#define MBEDTLS_EXIT_FAILURE 1
#endif
/*
* The function pointers for reading from and writing a seed file to
* Non-Volatile storage (NV) in a platform-independent way
*
* Only enabled when the NV seed entropy source is enabled
*/
#if defined(MBEDTLS_ENTROPY_NV_SEED)
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)
/* Internal standard platform definitions */
int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len );
int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len );
#endif
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len );
extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len );
/**
* \brief Set your own seed file writing/reading functions
*
* \param nv_seed_read_func the seed reading function implementation
* \param nv_seed_write_func the seed writing function implementation
*
* \return 0
*/
int mbedtls_platform_set_nv_seed(
int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ),
int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len )
);
#else
#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \
defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO)
#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO
#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO
#else
#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read
#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write
#endif
#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#ifdef __cplusplus
}
#endif
#endif /* platform.h */

View File

@ -0,0 +1,81 @@
/**
* \file platform_time.h
*
* \brief mbed TLS Platform time abstraction
*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#ifndef MBEDTLS_PLATFORM_TIME_H
#define MBEDTLS_PLATFORM_TIME_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
/*
* The time_t datatype
*/
#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO)
typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t;
#else
/* For time_t */
#include <time.h>
typedef time_t mbedtls_time_t;
#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */
/*
* The function pointers for time
*/
#if defined(MBEDTLS_PLATFORM_TIME_ALT)
extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time );
/**
* \brief Set your own time function pointer
*
* \param time_func the time function implementation
*
* \return 0
*/
int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) );
#else
#if defined(MBEDTLS_PLATFORM_TIME_MACRO)
#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO
#else
#define mbedtls_time time
#endif /* MBEDTLS_PLATFORM_TIME_MACRO */
#endif /* MBEDTLS_PLATFORM_TIME_ALT */
#ifdef __cplusplus
}
#endif
#endif /* platform_time.h */

1492
lib/mbedtls/src/aes.c Normal file

File diff suppressed because it is too large Load Diff

464
lib/mbedtls/src/ccm.c Normal file
View File

@ -0,0 +1,464 @@
/*
* NIST SP800-38C compliant CCM implementation
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
/*
* Definition of CCM:
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
* RFC 3610 "Counter with CBC-MAC (CCM)"
*
* Related:
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_CCM_C)
#include "mbedtls/ccm.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
#define CCM_ENCRYPT 0
#define CCM_DECRYPT 1
/*
* Initialize context
*/
void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_ccm_context ) );
}
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits )
{
int ret;
const mbedtls_cipher_info_t *cipher_info;
cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, MBEDTLS_MODE_ECB );
if( cipher_info == NULL )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
if( cipher_info->block_size != 16 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
mbedtls_cipher_free( &ctx->cipher_ctx );
if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 )
return( ret );
if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits,
MBEDTLS_ENCRYPT ) ) != 0 )
{
return( ret );
}
return( 0 );
}
/*
* Free context
*/
void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
{
mbedtls_cipher_free( &ctx->cipher_ctx );
mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
}
/*
* Macros for common operations.
* Results in smaller compiled code than static inline functions.
*/
/*
* Update the CBC-MAC state in y using a block in b
* (Always using b as the source helps the compiler optimise a bit better.)
*/
#define UPDATE_CBC_MAC \
for( i = 0; i < 16; i++ ) \
y[i] ^= b[i]; \
\
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
return( ret );
/*
* Encrypt or decrypt a partial block with CTR
* Warning: using b for temporary storage! src and dst must not be b!
* This avoids allocating one more 16 bytes buffer while allowing src == dst.
*/
#define CTR_CRYPT( dst, src, len ) \
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \
return( ret ); \
\
for( i = 0; i < len; i++ ) \
dst[i] = src[i] ^ b[i];
/*
* Authenticated encryption or decryption
*/
static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
int ret;
unsigned char i;
unsigned char q;
size_t len_left, olen;
unsigned char b[16];
unsigned char y[16];
unsigned char ctr[16];
const unsigned char *src;
unsigned char *dst;
/*
* Check length requirements: SP800-38C A.1
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
* 'length' checked later (when writing it to the first block)
*/
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
/* Also implies q is within bounds */
if( iv_len < 7 || iv_len > 13 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
if( add_len > 0xFF00 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
q = 16 - 1 - (unsigned char) iv_len;
/*
* First block B_0:
* 0 .. 0 flags
* 1 .. iv_len nonce (aka iv)
* iv_len+1 .. 15 length
*
* With flags as (bits):
* 7 0
* 6 add present?
* 5 .. 3 (t - 2) / 2
* 2 .. 0 q - 1
*/
b[0] = 0;
b[0] |= ( add_len > 0 ) << 6;
b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
b[0] |= q - 1;
memcpy( b + 1, iv, iv_len );
for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
b[15-i] = (unsigned char)( len_left & 0xFF );
if( len_left > 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
/* Start CBC-MAC with first block */
memset( y, 0, 16 );
UPDATE_CBC_MAC;
/*
* If there is additional data, update CBC-MAC with
* add_len, add, 0 (padding to a block boundary)
*/
if( add_len > 0 )
{
size_t use_len;
len_left = add_len;
src = add;
memset( b, 0, 16 );
b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
b[1] = (unsigned char)( ( add_len ) & 0xFF );
use_len = len_left < 16 - 2 ? len_left : 16 - 2;
memcpy( b + 2, src, use_len );
len_left -= use_len;
src += use_len;
UPDATE_CBC_MAC;
while( len_left > 0 )
{
use_len = len_left > 16 ? 16 : len_left;
memset( b, 0, 16 );
memcpy( b, src, use_len );
UPDATE_CBC_MAC;
len_left -= use_len;
src += use_len;
}
}
/*
* Prepare counter block for encryption:
* 0 .. 0 flags
* 1 .. iv_len nonce (aka iv)
* iv_len+1 .. 15 counter (initially 1)
*
* With flags as (bits):
* 7 .. 3 0
* 2 .. 0 q - 1
*/
ctr[0] = q - 1;
memcpy( ctr + 1, iv, iv_len );
memset( ctr + 1 + iv_len, 0, q );
ctr[15] = 1;
/*
* Authenticate and {en,de}crypt the message.
*
* The only difference between encryption and decryption is
* the respective order of authentication and {en,de}cryption.
*/
len_left = length;
src = input;
dst = output;
while( len_left > 0 )
{
size_t use_len = len_left > 16 ? 16 : len_left;
if( mode == CCM_ENCRYPT )
{
memset( b, 0, 16 );
memcpy( b, src, use_len );
UPDATE_CBC_MAC;
}
CTR_CRYPT( dst, src, use_len );
if( mode == CCM_DECRYPT )
{
memset( b, 0, 16 );
memcpy( b, dst, use_len );
UPDATE_CBC_MAC;
}
dst += use_len;
src += use_len;
len_left -= use_len;
/*
* Increment counter.
* No need to check for overflow thanks to the length check above.
*/
for( i = 0; i < q; i++ )
if( ++ctr[15-i] != 0 )
break;
}
/*
* Authentication: reset counter and crypt/mask internal tag
*/
for( i = 0; i < q; i++ )
ctr[15-i] = 0;
CTR_CRYPT( y, y, 16 );
memcpy( tag, y, tag_len );
return( 0 );
}
/*
* Authenticated encryption
*/
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
{
return( ccm_auth_crypt( ctx, CCM_ENCRYPT, length, iv, iv_len,
add, add_len, input, output, tag, tag_len ) );
}
/*
* Authenticated decryption
*/
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len )
{
int ret;
unsigned char check_tag[16];
unsigned char i;
int diff;
if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, check_tag, tag_len ) ) != 0 )
{
return( ret );
}
/* Check tag in "constant-time" */
for( diff = 0, i = 0; i < tag_len; i++ )
diff |= tag[i] ^ check_tag[i];
if( diff != 0 )
{
mbedtls_zeroize( output, length );
return( MBEDTLS_ERR_CCM_AUTH_FAILED );
}
return( 0 );
}
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/*
* Examples 1 to 3 from SP800-38C Appendix C
*/
#define NB_TESTS 3
/*
* The data is the same for all tests, only the used length changes
*/
static const unsigned char key[] = {
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
};
static const unsigned char iv[] = {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b
};
static const unsigned char ad[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13
};
static const unsigned char msg[] = {
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
};
static const size_t iv_len [NB_TESTS] = { 7, 8, 12 };
static const size_t add_len[NB_TESTS] = { 8, 16, 20 };
static const size_t msg_len[NB_TESTS] = { 4, 16, 24 };
static const size_t tag_len[NB_TESTS] = { 4, 6, 8 };
static const unsigned char res[NB_TESTS][32] = {
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
{ 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
};
int mbedtls_ccm_self_test( int verbose )
{
mbedtls_ccm_context ctx;
unsigned char out[32];
size_t i;
int ret;
mbedtls_ccm_init( &ctx );
if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key, 8 * sizeof key ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( " CCM: setup failed" );
return( 1 );
}
for( i = 0; i < NB_TESTS; i++ )
{
if( verbose != 0 )
mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 );
ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i],
iv, iv_len[i], ad, add_len[i],
msg, out,
out + msg_len[i], tag_len[i] );
if( ret != 0 ||
memcmp( out, res[i], msg_len[i] + tag_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i],
iv, iv_len[i], ad, add_len[i],
res[i], out,
res[i] + msg_len[i], tag_len[i] );
if( ret != 0 ||
memcmp( out, msg, msg_len[i] ) != 0 )
{
if( verbose != 0 )
mbedtls_printf( "failed\n" );
return( 1 );
}
if( verbose != 0 )
mbedtls_printf( "passed\n" );
}
mbedtls_ccm_free( &ctx );
if( verbose != 0 )
mbedtls_printf( "\n" );
return( 0 );
}
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#endif /* MBEDTLS_CCM_C */

917
lib/mbedtls/src/cipher.c Normal file
View File

@ -0,0 +1,917 @@
/**
* \file cipher.c
*
* \brief Generic cipher wrapper for mbed TLS
*
* \author Adriaan de Jong <dejong@fox-it.com>
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#include "mbedtls/cipher_internal.h"
#include <stdlib.h>
#include <string.h>
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
#if defined(MBEDTLS_CCM_C)
#include "mbedtls/ccm.h"
#endif
#if defined(MBEDTLS_CMAC_C)
#include "mbedtls/cmac.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER)
#define MBEDTLS_CIPHER_MODE_STREAM
#endif
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
static int supported_init = 0;
const int *mbedtls_cipher_list( void )
{
const mbedtls_cipher_definition_t *def;
int *type;
if( ! supported_init )
{
def = mbedtls_cipher_definitions;
type = mbedtls_cipher_supported;
while( def->type != 0 )
*type++ = (*def++).type;
*type = 0;
supported_init = 1;
}
return( mbedtls_cipher_supported );
}
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type )
{
const mbedtls_cipher_definition_t *def;
for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
if( def->type == cipher_type )
return( def->info );
return( NULL );
}
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name )
{
const mbedtls_cipher_definition_t *def;
if( NULL == cipher_name )
return( NULL );
for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
if( ! strcmp( def->info->name, cipher_name ) )
return( def->info );
return( NULL );
}
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
int key_bitlen,
const mbedtls_cipher_mode_t mode )
{
const mbedtls_cipher_definition_t *def;
for( def = mbedtls_cipher_definitions; def->info != NULL; def++ )
if( def->info->base->cipher == cipher_id &&
def->info->key_bitlen == (unsigned) key_bitlen &&
def->info->mode == mode )
return( def->info );
return( NULL );
}
void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx )
{
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
}
void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx )
{
if( ctx == NULL )
return;
#if defined(MBEDTLS_CMAC_C)
if( ctx->cmac_ctx )
{
mbedtls_zeroize( ctx->cmac_ctx, sizeof( mbedtls_cmac_context_t ) );
mbedtls_free( ctx->cmac_ctx );
}
#endif
if( ctx->cipher_ctx )
ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx );
mbedtls_zeroize( ctx, sizeof(mbedtls_cipher_context_t) );
}
int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info )
{
if( NULL == cipher_info || NULL == ctx )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) );
if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) )
return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED );
ctx->cipher_info = cipher_info;
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
/*
* Ignore possible errors caused by a cipher mode that doesn't use padding
*/
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
(void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 );
#else
(void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE );
#endif
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
return( 0 );
}
int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key,
int key_bitlen, const mbedtls_operation_t operation )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 &&
(int) ctx->cipher_info->key_bitlen != key_bitlen )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
ctx->key_bitlen = key_bitlen;
ctx->operation = operation;
/*
* For CFB and CTR mode always use the encryption key schedule
*/
if( MBEDTLS_ENCRYPT == operation ||
MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode )
{
return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key,
ctx->key_bitlen );
}
if( MBEDTLS_DECRYPT == operation )
return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key,
ctx->key_bitlen );
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len )
{
size_t actual_iv_size;
if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
/* avoid buffer overflow in ctx->iv */
if( iv_len > MBEDTLS_MAX_IV_LENGTH )
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 )
actual_iv_size = iv_len;
else
{
actual_iv_size = ctx->cipher_info->iv_size;
/* avoid reading past the end of input buffer */
if( actual_iv_size > iv_len )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
memcpy( ctx->iv, iv, actual_iv_size );
ctx->iv_size = actual_iv_size;
return( 0 );
}
int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
ctx->unprocessed_len = 0;
return( 0 );
}
#if defined(MBEDTLS_GCM_C)
int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len )
{
if( NULL == ctx || NULL == ctx->cipher_info )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation,
ctx->iv, ctx->iv_size, ad, ad_len );
}
return( 0 );
}
#endif /* MBEDTLS_GCM_C */
int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input,
size_t ilen, unsigned char *output, size_t *olen )
{
int ret;
size_t block_size = 0;
if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
*olen = 0;
block_size = mbedtls_cipher_get_block_size( ctx );
if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB )
{
if( ilen != block_size )
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
*olen = ilen;
if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx,
ctx->operation, input, output ) ) )
{
return( ret );
}
return( 0 );
}
#if defined(MBEDTLS_GCM_C)
if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM )
{
*olen = ilen;
return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input,
output );
}
#endif
if ( 0 == block_size )
{
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
}
if( input == output &&
( ctx->unprocessed_len != 0 || ilen % block_size ) )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC )
{
size_t copy_len = 0;
/*
* If there is not enough data for a full block, cache it.
*/
if( ( ctx->operation == MBEDTLS_DECRYPT &&
ilen + ctx->unprocessed_len <= block_size ) ||
( ctx->operation == MBEDTLS_ENCRYPT &&
ilen + ctx->unprocessed_len < block_size ) )
{
memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
ilen );
ctx->unprocessed_len += ilen;
return( 0 );
}
/*
* Process cached data first
*/
if( 0 != ctx->unprocessed_len )
{
copy_len = block_size - ctx->unprocessed_len;
memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
copy_len );
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
ctx->operation, block_size, ctx->iv,
ctx->unprocessed_data, output ) ) )
{
return( ret );
}
*olen += block_size;
output += block_size;
ctx->unprocessed_len = 0;
input += copy_len;
ilen -= copy_len;
}
/*
* Cache final, incomplete block
*/
if( 0 != ilen )
{
if( 0 == block_size )
{
return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
}
copy_len = ilen % block_size;
if( copy_len == 0 && ctx->operation == MBEDTLS_DECRYPT )
copy_len = block_size;
memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ),
copy_len );
ctx->unprocessed_len += copy_len;
ilen -= copy_len;
}
/*
* Process remaining full blocks
*/
if( ilen )
{
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
ctx->operation, ilen, ctx->iv, input, output ) ) )
{
return( ret );
}
*olen += ilen;
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB )
{
if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx,
ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv,
input, output ) ) )
{
return( ret );
}
*olen = ilen;
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR )
{
if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx,
ilen, &ctx->unprocessed_len, ctx->iv,
ctx->unprocessed_data, input, output ) ) )
{
return( ret );
}
*olen = ilen;
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM )
{
if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx,
ilen, input, output ) ) )
{
return( ret );
}
*olen = ilen;
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_STREAM */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
/*
* PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len
*/
static void add_pkcs_padding( unsigned char *output, size_t output_len,
size_t data_len )
{
size_t padding_len = output_len - data_len;
unsigned char i;
for( i = 0; i < padding_len; i++ )
output[data_len + i] = (unsigned char) padding_len;
}
static int get_pkcs_padding( unsigned char *input, size_t input_len,
size_t *data_len )
{
size_t i, pad_idx;
unsigned char padding_len, bad = 0;
if( NULL == input || NULL == data_len )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
padding_len = input[input_len - 1];
*data_len = input_len - padding_len;
/* Avoid logical || since it results in a branch */
bad |= padding_len > input_len;
bad |= padding_len == 0;
/* The number of bytes checked must be independent of padding_len,
* so pick input_len, which is usually 8 or 16 (one block) */
pad_idx = input_len - padding_len;
for( i = 0; i < input_len; i++ )
bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx );
return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
}
#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
/*
* One and zeros padding: fill with 80 00 ... 00
*/
static void add_one_and_zeros_padding( unsigned char *output,
size_t output_len, size_t data_len )
{
size_t padding_len = output_len - data_len;
unsigned char i = 0;
output[data_len] = 0x80;
for( i = 1; i < padding_len; i++ )
output[data_len + i] = 0x00;
}
static int get_one_and_zeros_padding( unsigned char *input, size_t input_len,
size_t *data_len )
{
size_t i;
unsigned char done = 0, prev_done, bad;
if( NULL == input || NULL == data_len )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
bad = 0xFF;
*data_len = 0;
for( i = input_len; i > 0; i-- )
{
prev_done = done;
done |= ( input[i-1] != 0 );
*data_len |= ( i - 1 ) * ( done != prev_done );
bad &= ( input[i-1] ^ 0x80 ) | ( done == prev_done );
}
return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
}
#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
/*
* Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length
*/
static void add_zeros_and_len_padding( unsigned char *output,
size_t output_len, size_t data_len )
{
size_t padding_len = output_len - data_len;
unsigned char i = 0;
for( i = 1; i < padding_len; i++ )
output[data_len + i - 1] = 0x00;
output[output_len - 1] = (unsigned char) padding_len;
}
static int get_zeros_and_len_padding( unsigned char *input, size_t input_len,
size_t *data_len )
{
size_t i, pad_idx;
unsigned char padding_len, bad = 0;
if( NULL == input || NULL == data_len )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
padding_len = input[input_len - 1];
*data_len = input_len - padding_len;
/* Avoid logical || since it results in a branch */
bad |= padding_len > input_len;
bad |= padding_len == 0;
/* The number of bytes checked must be independent of padding_len */
pad_idx = input_len - padding_len;
for( i = 0; i < input_len - 1; i++ )
bad |= input[i] * ( i >= pad_idx );
return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) );
}
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
/*
* Zero padding: fill with 00 ... 00
*/
static void add_zeros_padding( unsigned char *output,
size_t output_len, size_t data_len )
{
size_t i;
for( i = data_len; i < output_len; i++ )
output[i] = 0x00;
}
static int get_zeros_padding( unsigned char *input, size_t input_len,
size_t *data_len )
{
size_t i;
unsigned char done = 0, prev_done;
if( NULL == input || NULL == data_len )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
*data_len = 0;
for( i = input_len; i > 0; i-- )
{
prev_done = done;
done |= ( input[i-1] != 0 );
*data_len |= i * ( done != prev_done );
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
/*
* No padding: don't pad :)
*
* There is no add_padding function (check for NULL in mbedtls_cipher_finish)
* but a trivial get_padding function
*/
static int get_no_padding( unsigned char *input, size_t input_len,
size_t *data_len )
{
if( NULL == input || NULL == data_len )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
*data_len = input_len;
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen )
{
if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
*olen = 0;
if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
MBEDTLS_MODE_STREAM == ctx->cipher_info->mode )
{
return( 0 );
}
if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode )
{
if( ctx->unprocessed_len != 0 )
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
return( 0 );
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode )
{
int ret = 0;
if( MBEDTLS_ENCRYPT == ctx->operation )
{
/* check for 'no padding' mode */
if( NULL == ctx->add_padding )
{
if( 0 != ctx->unprocessed_len )
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
return( 0 );
}
ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ),
ctx->unprocessed_len );
}
else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len )
{
/*
* For decrypt operations, expect a full block,
* or an empty block if no padding
*/
if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len )
return( 0 );
return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED );
}
/* cipher block */
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv,
ctx->unprocessed_data, output ) ) )
{
return( ret );
}
/* Set output size for decryption */
if( MBEDTLS_DECRYPT == ctx->operation )
return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ),
olen );
/* Set output size for encryption */
*olen = mbedtls_cipher_get_block_size( ctx );
return( 0 );
}
#else
((void) output);
#endif /* MBEDTLS_CIPHER_MODE_CBC */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode )
{
if( NULL == ctx ||
MBEDTLS_MODE_CBC != ctx->cipher_info->mode )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
switch( mode )
{
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
case MBEDTLS_PADDING_PKCS7:
ctx->add_padding = add_pkcs_padding;
ctx->get_padding = get_pkcs_padding;
break;
#endif
#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
case MBEDTLS_PADDING_ONE_AND_ZEROS:
ctx->add_padding = add_one_and_zeros_padding;
ctx->get_padding = get_one_and_zeros_padding;
break;
#endif
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
case MBEDTLS_PADDING_ZEROS_AND_LEN:
ctx->add_padding = add_zeros_and_len_padding;
ctx->get_padding = get_zeros_and_len_padding;
break;
#endif
#if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
case MBEDTLS_PADDING_ZEROS:
ctx->add_padding = add_zeros_padding;
ctx->get_padding = get_zeros_padding;
break;
#endif
case MBEDTLS_PADDING_NONE:
ctx->add_padding = NULL;
ctx->get_padding = get_no_padding;
break;
default:
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
return( 0 );
}
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
#if defined(MBEDTLS_GCM_C)
int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len )
{
if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( MBEDTLS_ENCRYPT != ctx->operation )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len );
return( 0 );
}
int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len )
{
int ret;
if( NULL == ctx || NULL == ctx->cipher_info ||
MBEDTLS_DECRYPT != ctx->operation )
{
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
unsigned char check_tag[16];
size_t i;
int diff;
if( tag_len > sizeof( check_tag ) )
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx,
check_tag, tag_len ) ) )
{
return( ret );
}
/* Check the tag in "constant-time" */
for( diff = 0, i = 0; i < tag_len; i++ )
diff |= tag[i] ^ check_tag[i];
if( diff != 0 )
return( MBEDTLS_ERR_CIPHER_AUTH_FAILED );
return( 0 );
}
return( 0 );
}
#endif /* MBEDTLS_GCM_C */
/*
* Packet-oriented wrapper for non-AEAD modes
*/
int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen )
{
int ret;
size_t finish_olen;
if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 )
return( ret );
if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 )
return( ret );
if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 )
return( ret );
if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 )
return( ret );
*olen += finish_olen;
return( 0 );
}
#if defined(MBEDTLS_CIPHER_MODE_AEAD)
/*
* Packet-oriented encryption for AEAD modes
*/
int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen,
unsigned char *tag, size_t tag_len )
{
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
*olen = ilen;
return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen,
iv, iv_len, ad, ad_len, input, output,
tag_len, tag ) );
}
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_CCM_C)
if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
{
*olen = ilen;
return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen,
iv, iv_len, ad, ad_len, input, output,
tag, tag_len ) );
}
#endif /* MBEDTLS_CCM_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
/*
* Packet-oriented decryption for AEAD modes
*/
int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen,
const unsigned char *tag, size_t tag_len )
{
#if defined(MBEDTLS_GCM_C)
if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode )
{
int ret;
*olen = ilen;
ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen,
iv, iv_len, ad, ad_len,
tag, tag_len, input, output );
if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED )
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
return( ret );
}
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_CCM_C)
if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode )
{
int ret;
*olen = ilen;
ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen,
iv, iv_len, ad, ad_len,
input, output, tag, tag_len );
if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED )
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
return( ret );
}
#endif /* MBEDTLS_CCM_C */
return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE );
}
#endif /* MBEDTLS_CIPHER_MODE_AEAD */
#endif /* MBEDTLS_CIPHER_C */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
# Ethernet Arduino Library for ESP32
See https://github.com/espressif/arduino-esp32/issues/3554#issuecomment-596902806

View File

@ -0,0 +1,82 @@
#include <ETH.h>
#define ETH_ADDR 1
#define ETH_POWER_PIN 5
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18
#define ETH_TYPE ETH_PHY_IP101
static bool eth_connected = false;
void WiFiEvent(WiFiEvent_t event)
{
switch (event) {
case SYSTEM_EVENT_ETH_START:
Serial.println("ETH Started");
//set eth hostname here
ETH.setHostname("esp32-ethernet");
break;
case SYSTEM_EVENT_ETH_CONNECTED:
Serial.println("ETH Connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
Serial.print("ETH MAC: ");
Serial.print(ETH.macAddress());
Serial.print(", IPv4: ");
Serial.print(ETH.localIP());
if (ETH.fullDuplex()) {
Serial.print(", FULL_DUPLEX");
}
Serial.print(", ");
Serial.print(ETH.linkSpeed());
Serial.println("Mbps");
eth_connected = true;
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
Serial.println("ETH Disconnected");
eth_connected = false;
break;
case SYSTEM_EVENT_ETH_STOP:
Serial.println("ETH Stopped");
eth_connected = false;
break;
default:
break;
}
}
void testClient(const char * host, uint16_t port)
{
Serial.print("\nconnecting to ");
Serial.println(host);
WiFiClient client;
if (!client.connect(host, port)) {
Serial.println("connection failed");
return;
}
client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
while (client.connected() && !client.available());
while (client.available()) {
Serial.write(client.read());
}
Serial.println("closing connection\n");
client.stop();
}
void setup()
{
Serial.begin(115200);
WiFi.onEvent(WiFiEvent);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE);
}
void loop()
{
if (eth_connected) {
testClient("google.com", 80);
}
delay(10000);
}

View File

@ -0,0 +1,17 @@
name=ESP32 Ethernet
version=1.1.0
author=Espressif
maintainer=Espressif
sentence=Ethernet Library for ESP32
paragraph=This library allows ESP32 to use ethernet hardware
category=Communication
url=
architectures=esp32

View File

@ -0,0 +1,299 @@
/*
ETH.h - espre ETH PHY support.
Based on WiFi.h from Arduino WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ETH.h"
#include "eth_phy/phy.h"
#include "eth_phy/phy_tlk110.h"
#include "eth_phy/phy_lan8720.h"
#include "eth_phy/phy_ip101.h"
#include "lwip/err.h"
#include "lwip/dns.h"
extern void tcpipInit();
static int _eth_phy_mdc_pin = -1;
static int _eth_phy_mdio_pin = -1;
static int _eth_phy_power_pin = -1;
static eth_phy_power_enable_func _eth_phy_power_enable_orig = NULL;
static void _eth_phy_config_gpio(void)
{
if(_eth_phy_mdc_pin < 0 || _eth_phy_mdio_pin < 0){
log_e("MDC and MDIO pins are not configured!");
return;
}
phy_rmii_configure_data_interface_pins();
phy_rmii_smi_configure_pins(_eth_phy_mdc_pin, _eth_phy_mdio_pin);
}
static void _eth_phy_power_enable(bool enable)
{
pinMode(_eth_phy_power_pin, OUTPUT);
digitalWrite(_eth_phy_power_pin, enable);
delay(1);
}
ETHClass::ETHClass():initialized(false),started(false),staticIP(false)
{
}
ETHClass::~ETHClass()
{}
bool ETHClass::begin(uint8_t phy_addr, int power, int mdc, int mdio, eth_phy_type_t type, eth_clock_mode_t clock_mode)
{
esp_err_t err;
if(initialized){
err = esp_eth_enable();
if(err){
log_e("esp_eth_enable error: %d", err);
return false;
}
started = true;
return true;
}
_eth_phy_mdc_pin = mdc;
_eth_phy_mdio_pin = mdio;
_eth_phy_power_pin = power;
if(type == ETH_PHY_LAN8720)
{
eth_config_t config = phy_lan8720_default_ethernet_config;
memcpy(&eth_config, &config, sizeof(eth_config_t));
}
else if(type == ETH_PHY_TLK110)
{
eth_config_t config = phy_tlk110_default_ethernet_config;
memcpy(&eth_config, &config, sizeof(eth_config_t));
}
else if(type == ETH_PHY_IP101)
{
eth_config_t config = phy_ip101_default_ethernet_config;
memcpy(&eth_config, &config, sizeof(eth_config_t));
}
else
{
log_e("Bad ETH_PHY type: %u", (uint8_t)type);
return false;
}
eth_config.phy_addr = (eth_phy_base_t)phy_addr;
eth_config.clock_mode = clock_mode;
eth_config.gpio_config = _eth_phy_config_gpio;
eth_config.tcpip_input = tcpip_adapter_eth_input;
if(_eth_phy_power_pin >= 0){
_eth_phy_power_enable_orig = eth_config.phy_power_enable;
eth_config.phy_power_enable = _eth_phy_power_enable;
}
tcpipInit();
err = esp_eth_init(&eth_config);
if(!err){
initialized = true;
err = esp_eth_enable();
if(err){
log_e("esp_eth_enable error: %d", err);
} else {
started = true;
return true;
}
} else {
log_e("esp_eth_init error: %d", err);
}
return false;
}
bool ETHClass::config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1, IPAddress dns2)
{
esp_err_t err = ESP_OK;
tcpip_adapter_ip_info_t info;
if(local_ip != (uint32_t)0x00000000){
info.ip.addr = static_cast<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet);
} else {
info.ip.addr = 0;
info.gw.addr = 0;
info.netmask.addr = 0;
}
err = tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_ETH);
if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED){
log_e("DHCP could not be stopped! Error: %d", err);
return false;
}
err = tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_ETH, &info);
if(err != ERR_OK){
log_e("STA IP could not be configured! Error: %d", err);
return false;
}
if(info.ip.addr){
staticIP = true;
} else {
err = tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_ETH);
if(err != ESP_OK && err != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED){
log_w("DHCP could not be started! Error: %d", err);
return false;
}
staticIP = false;
}
ip_addr_t d;
d.type = IPADDR_TYPE_V4;
if(dns1 != (uint32_t)0x00000000) {
// Set DNS1-Server
d.u_addr.ip4.addr = static_cast<uint32_t>(dns1);
dns_setserver(0, &d);
}
if(dns2 != (uint32_t)0x00000000) {
// Set DNS2-Server
d.u_addr.ip4.addr = static_cast<uint32_t>(dns2);
dns_setserver(1, &d);
}
return true;
}
IPAddress ETHClass::localIP()
{
tcpip_adapter_ip_info_t ip;
if(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)){
return IPAddress();
}
return IPAddress(ip.ip.addr);
}
IPAddress ETHClass::subnetMask()
{
tcpip_adapter_ip_info_t ip;
if(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)){
return IPAddress();
}
return IPAddress(ip.netmask.addr);
}
IPAddress ETHClass::gatewayIP()
{
tcpip_adapter_ip_info_t ip;
if(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)){
return IPAddress();
}
return IPAddress(ip.gw.addr);
}
IPAddress ETHClass::dnsIP(uint8_t dns_no)
{
ip_addr_t dns_ip = dns_getserver(dns_no);
return IPAddress(dns_ip.u_addr.ip4.addr);
}
IPAddress ETHClass::broadcastIP()
{
tcpip_adapter_ip_info_t ip;
if(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)){
return IPAddress();
}
return WiFiGenericClass::calculateBroadcast(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr));
}
IPAddress ETHClass::networkID()
{
tcpip_adapter_ip_info_t ip;
if(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)){
return IPAddress();
}
return WiFiGenericClass::calculateNetworkID(IPAddress(ip.gw.addr), IPAddress(ip.netmask.addr));
}
uint8_t ETHClass::subnetCIDR()
{
tcpip_adapter_ip_info_t ip;
if(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &ip)){
return (uint8_t)0;
}
return WiFiGenericClass::calculateSubnetCIDR(IPAddress(ip.netmask.addr));
}
const char * ETHClass::getHostname()
{
const char * hostname;
if(tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_ETH, &hostname)){
return NULL;
}
return hostname;
}
bool ETHClass::setHostname(const char * hostname)
{
return tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_ETH, hostname) == 0;
}
bool ETHClass::fullDuplex()
{
return eth_config.phy_get_duplex_mode();
}
bool ETHClass::linkUp()
{
return eth_config.phy_check_link();
}
uint8_t ETHClass::linkSpeed()
{
return eth_config.phy_get_speed_mode()?100:10;
}
bool ETHClass::enableIpV6()
{
return tcpip_adapter_create_ip6_linklocal(TCPIP_ADAPTER_IF_ETH) == 0;
}
IPv6Address ETHClass::localIPv6()
{
static ip6_addr_t addr;
if(tcpip_adapter_get_ip6_linklocal(TCPIP_ADAPTER_IF_ETH, &addr)){
return IPv6Address();
}
return IPv6Address(addr.addr);
}
uint8_t * macAddress(uint8_t* mac)
{
if(!mac){
return NULL;
}
esp_eth_get_mac(mac);
return mac;
}
String ETHClass::macAddress(void)
{
uint8_t mac[6];
char macStr[18] = { 0 };
esp_eth_get_mac(mac);
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(macStr);
}
ETHClass ETH;

View File

@ -0,0 +1,95 @@
/*
ETH.h - espre ETH PHY support.
Based on WiFi.h from Ardiono WiFi shield library.
Copyright (c) 2011-2014 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ETH_H_
#define _ETH_H_
#include "WiFi.h"
#include "esp_eth.h"
#ifndef ETH_PHY_ADDR
#define ETH_PHY_ADDR 0
#endif
#ifndef ETH_PHY_TYPE
#define ETH_PHY_TYPE ETH_PHY_LAN8720
#endif
#ifndef ETH_PHY_POWER
#define ETH_PHY_POWER -1
#endif
#ifndef ETH_PHY_MDC
#define ETH_PHY_MDC 23
#endif
#ifndef ETH_PHY_MDIO
#define ETH_PHY_MDIO 18
#endif
#ifndef ETH_CLK_MODE
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN
#endif
typedef enum { ETH_PHY_LAN8720, ETH_PHY_TLK110, ETH_PHY_IP101, ETH_PHY_MAX } eth_phy_type_t;
class ETHClass {
private:
bool initialized;
bool started;
bool staticIP;
eth_config_t eth_config;
public:
ETHClass();
~ETHClass();
bool begin(uint8_t phy_addr=ETH_PHY_ADDR, int power=ETH_PHY_POWER, int mdc=ETH_PHY_MDC, int mdio=ETH_PHY_MDIO, eth_phy_type_t type=ETH_PHY_TYPE, eth_clock_mode_t clk_mode=ETH_CLK_MODE);
bool config(IPAddress local_ip, IPAddress gateway, IPAddress subnet, IPAddress dns1 = (uint32_t)0x00000000, IPAddress dns2 = (uint32_t)0x00000000);
const char * getHostname();
bool setHostname(const char * hostname);
bool fullDuplex();
bool linkUp();
uint8_t linkSpeed();
bool enableIpV6();
IPv6Address localIPv6();
IPAddress localIP();
IPAddress subnetMask();
IPAddress gatewayIP();
IPAddress dnsIP(uint8_t dns_no = 0);
IPAddress broadcastIP();
IPAddress networkID();
uint8_t subnetCIDR();
uint8_t * macAddress(uint8_t* mac);
String macAddress();
friend class WiFiClient;
friend class WiFiServer;
};
extern ETHClass ETH;
#endif /* _ETH_H_ */

View File

@ -1,8 +1,19 @@
## Unreleased (development) ## Unreleased (development)
### 8.3.1.6 20200617
- Add command ``Module2`` to configure fallback module on fast reboot (#8464)
- Add support for Energy sensor (Denky) for French Smart Metering meter provided by global Energy Providers, need a adaptater. See dedicated full [blog](http://hallard.me/category/tinfo/) about French teleinformation stuff
- Add library to be used for decoding Teleinfo (French Metering Smart Meter)
- Add support for single wire LMT01 temperature Sensor by justifiably (#8713)
- Change ESP32 USER GPIO template representation decreasing template message size
- Change define USE_TASMOTA_SLAVE into USE_TASMOTA_CLIENT
- Change commands ``SlaveSend`` and ``SlaveReset`` into ``ClientSend`` and ``ClientReset``
### 8.3.1.5 20200616 ### 8.3.1.5 20200616
- Add ESP32 ethernet commands ``EthType 0/1``, ``EthAddress 0..31`` and ``EthClockMode 0..3`` - Add ESP32 ethernet commands ``EthType 0/1``, ``EthAddress 0..31`` and ``EthClockMode 0..3``
- Add Zigbee initial support for EmberZNet protocol (raw send/receive only)
### 8.3.1.4 20200615 ### 8.3.1.4 20200615

View File

@ -505,10 +505,14 @@
#define D_CMND_ZIGBEE_RESET "Reset" #define D_CMND_ZIGBEE_RESET "Reset"
#define D_JSON_ZIGBEE_CC2530 "CC2530" #define D_JSON_ZIGBEE_CC2530 "CC2530"
#define D_CMND_ZIGBEEZNPRECEIVE "ZNPReceive" // only for debug #define D_CMND_ZIGBEEZNPRECEIVE "ZNPReceive" // only for debug
#define D_CMND_ZIGBEE_EZSP_RECEIVE "EZSPReceive" // only for debug
#define D_CMND_ZIGBEEZNPSEND "ZNPSend" #define D_CMND_ZIGBEEZNPSEND "ZNPSend"
#define D_CMND_ZIGBEE_EZSP_SEND "EZSPSend"
#define D_JSON_ZIGBEE_STATE "ZbState" #define D_JSON_ZIGBEE_STATE "ZbState"
#define D_JSON_ZIGBEEZNPRECEIVED "ZbZNPReceived" #define D_JSON_ZIGBEEZNPRECEIVED "ZbZNPReceived"
#define D_JSON_ZIGBEE_EZSP_RECEIVED "ZbEZSPReceived"
#define D_JSON_ZIGBEEZNPSENT "ZbZNPSent" #define D_JSON_ZIGBEEZNPSENT "ZbZNPSent"
#define D_JSON_ZIGBEE_EZSP_SENT "ZbEZSPSent"
#define D_JSON_ZIGBEEZCL_RECEIVED "ZbZCLReceived" #define D_JSON_ZIGBEEZCL_RECEIVED "ZbZCLReceived"
#define D_JSON_ZIGBEEZCL_RAW_RECEIVED "ZbZCLRawReceived" #define D_JSON_ZIGBEEZCL_RAW_RECEIVED "ZbZCLRawReceived"
#define D_JSON_ZIGBEE_DEVICE "Device" #define D_JSON_ZIGBEE_DEVICE "Device"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Подобрена комуникация" #define D_KNX_ENHANCEMENT "Подобрена комуникация"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Използвана енергия днес" #define D_ENERGY_TODAY "Използвана енергия днес"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Spotřeba Dnes" #define D_ENERGY_TODAY "Spotřeba Dnes"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Erweiterte Kommunikation" #define D_KNX_ENHANCEMENT "Erweiterte Kommunikation"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energie heute" #define D_ENERGY_TODAY "Energie heute"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας" #define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Ενέργεια σήμερα" #define D_ENERGY_TODAY "Ενέργεια σήμερα"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energy Today" #define D_ENERGY_TODAY "Energy Today"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Mejora de Comunicación" #define D_KNX_ENHANCEMENT "Mejora de Comunicación"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX ESCENA TX"
#define D_KNX_RX_SCENE "KNX ESCENA RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energía Hoy" #define D_ENERGY_TODAY "Energía Hoy"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Amélioration de la communication" #define D_KNX_ENHANCEMENT "Amélioration de la communication"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX Scène TX"
#define D_KNX_RX_SCENE "KNX Scène RX"
// xsns_03_energy.ino // xsns_03_energy.ino
#define D_ENERGY_TODAY "Énergie aujourd'hui" #define D_ENERGY_TODAY "Énergie aujourd'hui"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "Hibernation" #define D_SENSOR_DEEPSLEEP "Hibernation"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Esclave TX" #define D_SENSOR_CLIENT_TX "Esclave TX"
#define D_SENSOR_SLAVE_RX "Esclave RX" #define D_SENSOR_CLIENT_RX "Esclave RX"
#define D_SENSOR_SLAVE_RESET "Esclave Rst" #define D_SENSOR_CLIENT_RESET "Esclave Rst"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "שיפור התקשורת" #define D_KNX_ENHANCEMENT "שיפור התקשורת"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "צריכה יומית" #define D_ENERGY_TODAY "צריכה יומית"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Mai energia" #define D_ENERGY_TODAY "Mai energia"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Miglioramento comunicazione" #define D_KNX_ENHANCEMENT "Miglioramento comunicazione"
#define D_KNX_TX_SLOT "KNX - TX" #define D_KNX_TX_SLOT "KNX - TX"
#define D_KNX_RX_SLOT "KNX - RX" #define D_KNX_RX_SLOT "KNX - RX"
#define D_KNX_TX_SCENE "Scena - TX"
#define D_KNX_RX_SCENE "Scena - RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energia - oggi" #define D_ENERGY_TODAY "Energia - oggi"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 - DATI" #define D_SENSOR_SM2135_DAT "SM2135 - DATI"
#define D_SENSOR_DEEPSLEEP "Deep sleep" #define D_SENSOR_DEEPSLEEP "Deep sleep"
#define D_SENSOR_EXS_ENABLE "EXS - Abilita" #define D_SENSOR_EXS_ENABLE "EXS - Abilita"
#define D_SENSOR_SLAVE_TX "Slave - TX" #define D_SENSOR_CLIENT_TX "Client - TX"
#define D_SENSOR_SLAVE_RX "Slave - RX" #define D_SENSOR_CLIENT_RX "Client - RX"
#define D_SENSOR_SLAVE_RESET "Slave - RST" #define D_SENSOR_CLIENT_RESET "Client - RST"
#define D_SENSOR_GPS_RX "GPS - RX" #define D_SENSOR_GPS_RX "GPS - RX"
#define D_SENSOR_GPS_TX "GPS - TX" #define D_SENSOR_GPS_TX "GPS - TX"
#define D_SENSOR_HM10_RX "HM10 - RX" #define D_SENSOR_HM10_RX "HM10 - RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "Velocità vento" #define D_SENSOR_WINDMETER_SPEED "Velocità vento"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "커뮤니케이션 강화" #define D_KNX_ENHANCEMENT "커뮤니케이션 강화"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "금일 전력 사용량" #define D_ENERGY_TODAY "금일 전력 사용량"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Verbeter verbinding" #define D_KNX_ENHANCEMENT "Verbeter verbinding"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Verbruik vandaag" #define D_ENERGY_TODAY "Verbruik vandaag"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Rozszerzenia" #define D_KNX_ENHANCEMENT "Rozszerzenia"
#define D_KNX_TX_SLOT "Gniazdo TX" #define D_KNX_TX_SLOT "Gniazdo TX"
#define D_KNX_RX_SLOT "Gniazdo RX" #define D_KNX_RX_SLOT "Gniazdo RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energia dzisiaj" #define D_ENERGY_TODAY "Energia dzisiaj"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "Głęboko uśpiony" #define D_SENSOR_DEEPSLEEP "Głęboko uśpiony"
#define D_SENSOR_EXS_ENABLE "Załącz EXS" #define D_SENSOR_EXS_ENABLE "Załącz EXS"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Melhoria da comunicação" #define D_KNX_ENHANCEMENT "Melhoria da comunicação"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Consumo energético de hoje" #define D_ENERGY_TODAY "Consumo energético de hoje"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Melhoria de Comunicação" #define D_KNX_ENHANCEMENT "Melhoria de Comunicação"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Consumo energético de hoje" #define D_ENERGY_TODAY "Consumo energético de hoje"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Îmbunătățire Communicație" #define D_KNX_ENHANCEMENT "Îmbunătățire Communicație"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energia de Azi" #define D_ENERGY_TODAY "Energia de Azi"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Энергия Сегодня" #define D_ENERGY_TODAY "Энергия Сегодня"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Spotreba dnes" #define D_ENERGY_TODAY "Spotreba dnes"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Kommuniceringsförbättring" #define D_KNX_ENHANCEMENT "Kommuniceringsförbättring"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energi idag" #define D_ENERGY_TODAY "Energi idag"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energy Today" #define D_ENERGY_TODAY "Energy Today"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Підвищення зв'язку" #define D_KNX_ENHANCEMENT "Підвищення зв'язку"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "Енергія Сьогодні" #define D_ENERGY_TODAY "Енергія Сьогодні"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "通讯增强" #define D_KNX_ENHANCEMENT "通讯增强"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "今日用电量" #define D_ENERGY_TODAY "今日用电量"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -445,6 +445,8 @@
#define D_KNX_ENHANCEMENT "Communication Enhancement" #define D_KNX_ENHANCEMENT "Communication Enhancement"
#define D_KNX_TX_SLOT "KNX TX" #define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX" #define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_TX_SCENE "KNX SCENE TX"
#define D_KNX_RX_SCENE "KNX SCENE RX"
// xdrv_03_energy.ino // xdrv_03_energy.ino
#define D_ENERGY_TODAY "今日用電量" #define D_ENERGY_TODAY "今日用電量"
@ -663,9 +665,9 @@
#define D_SENSOR_SM2135_DAT "SM2135 Dat" #define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep" #define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable" #define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_SLAVE_TX "Slave TX" #define D_SENSOR_CLIENT_TX "Client TX"
#define D_SENSOR_SLAVE_RX "Slave RX" #define D_SENSOR_CLIENT_RX "Client RX"
#define D_SENSOR_SLAVE_RESET "Slave RST" #define D_SENSOR_CLIENT_RESET "Client RST"
#define D_SENSOR_GPS_RX "GPS RX" #define D_SENSOR_GPS_RX "GPS RX"
#define D_SENSOR_GPS_TX "GPS TX" #define D_SENSOR_GPS_TX "GPS TX"
#define D_SENSOR_HM10_RX "HM10 RX" #define D_SENSOR_HM10_RX "HM10 RX"
@ -681,6 +683,7 @@
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd" #define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
#define D_SENSOR_TELEINFO_RX "TInfo Rx" #define D_SENSOR_TELEINFO_RX "TInfo Rx"
#define D_SENSOR_TELEINFO_ENABLE "TInfo EN" #define D_SENSOR_TELEINFO_ENABLE "TInfo EN"
#define D_SENSOR_LMT01_PULSE "LMT01 Pulse"
#define D_GPIO_WEBCAM_PWDN "CAM_PWDN" #define D_GPIO_WEBCAM_PWDN "CAM_PWDN"
#define D_GPIO_WEBCAM_RESET "CAM_RESET" #define D_GPIO_WEBCAM_RESET "CAM_RESET"
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK" #define D_GPIO_WEBCAM_XCLK "CAM_XCLK"

View File

@ -50,7 +50,12 @@
#define PROJECT "tasmota" // PROJECT is used as the default topic delimiter #define PROJECT "tasmota" // PROJECT is used as the default topic delimiter
// If not selected the default will be SONOFF_BASIC // If not selected the default will be SONOFF_BASIC
//#define MODULE SONOFF_BASIC // [Module] Select default model from tasmota_template.h //#define MODULE SONOFF_BASIC // [Module] Select default module from tasmota_template.h
#ifdef ESP8266
#define FALLBACK_MODULE SONOFF_BASIC // [Module2] Select default module on fast reboot where USER_MODULE is user template
#else // ESP32
#define FALLBACK_MODULE WEMOS // [Module2] Select default module on fast reboot where USER_MODULE is user template
#endif
#define SAVE_DATA 1 // [SaveData] Save changed parameters to Flash (0 = disable, 1 - 3600 seconds) #define SAVE_DATA 1 // [SaveData] Save changed parameters to Flash (0 = disable, 1 - 3600 seconds)
#define SAVE_STATE true // [SetOption0] Save changed power state to Flash (false = disable, true = enable) #define SAVE_STATE true // [SetOption0] Save changed power state to Flash (false = disable, true = enable)
@ -135,6 +140,8 @@
// -- MQTT - Home Assistant Discovery ------------- // -- MQTT - Home Assistant Discovery -------------
#define HOME_ASSISTANT_DISCOVERY_ENABLE false // [SetOption19] Home Assistant Discovery (false = Disable, true = Enable) #define HOME_ASSISTANT_DISCOVERY_ENABLE false // [SetOption19] Home Assistant Discovery (false = Disable, true = Enable)
#define HASS_AS_LIGHT false // [SetOption30] Enforce HAss autodiscovery as light #define HASS_AS_LIGHT false // [SetOption30] Enforce HAss autodiscovery as light
//#define DEEPSLEEP_LWT_HA_DISCOVERY // Enable LWT topic and its payloads for read-only sensors (Status sensor not included) and binary_sensors on HAss Discovery (Commented out: all read-only sensors and binary_sensors
// won't be shown as OFFLINE on Home Assistant when the device is DeepSleeping - NOTE: This is only for read-only sensors and binary_sensors, relays will be shown as OFFLINE)
// -- MQTT - Options ------------------------------ // -- MQTT - Options ------------------------------
#define MQTT_RESULT_COMMAND false // [SetOption4] Switch between MQTT RESULT or COMMAND #define MQTT_RESULT_COMMAND false // [SetOption4] Switch between MQTT RESULT or COMMAND
@ -591,12 +598,10 @@
// #define USE_FLOG // Add support for GPS logging in OTA's Flash (Experimental) (+2k9 code, +8 bytes RAM) // #define USE_FLOG // Add support for GPS logging in OTA's Flash (Experimental) (+2k9 code, +8 bytes RAM)
//#define USE_HM10 // (ESP8266 only) Add support for HM-10 as a BLE-bridge (+9k3 code) //#define USE_HM10 // (ESP8266 only) Add support for HM-10 as a BLE-bridge (+9k3 code)
//#define USE_HRXL // Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) //#define USE_HRXL // Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
//#define USE_TASMOTA_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k6 code, 64 mem) //#define USE_TASMOTA_CLIENT // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k6 code, 64 mem)
#define USE_TASMOTA_SLAVE_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants #define USE_TASMOTA_CLIENT_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants
#define USE_TASMOTA_SLAVE_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini #define USE_TASMOTA_CLIENT_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini
//#define USE_OPENTHERM // Add support for OpenTherm (+15k code) //#define USE_OPENTHERM // Add support for OpenTherm (+15k code)
#define USE_TELEINFO // Add support for Teleinfo via serial RX interface
//#define USE_TELEINFO_STANDARD // Use standard mode (9600 bps) else it's historical mode (1200 bps)
// -- Power monitoring sensors -------------------- // -- Power monitoring sensors --------------------
#define USE_ENERGY_MARGIN_DETECTION // Add support for Energy Margin detection (+1k6 code) #define USE_ENERGY_MARGIN_DETECTION // Add support for Energy Margin detection (+1k6 code)
@ -620,6 +625,8 @@
#define LE01MR_SPEED 9600 // LE-01MR modbus baudrate (default: 9600) #define LE01MR_SPEED 9600 // LE-01MR modbus baudrate (default: 9600)
#define LE01MR_ADDR 1 // LE-01MR modbus address (default: 0x01) #define LE01MR_ADDR 1 // LE-01MR modbus address (default: 0x01)
#define USE_BL0940 // Add support for BL0940 Energy monitor as used in Blitzwolf SHP-10 (+1k6 code) #define USE_BL0940 // Add support for BL0940 Energy monitor as used in Blitzwolf SHP-10 (+1k6 code)
//#define USE_TELEINFO // Add support for Teleinfo via serial RX interface (+5k2 code, +168 RAM + SmartMeter LinkedList Values RAM)
// #define USE_TELEINFO_STANDARD // Use standard mode (9600 bps) else it's historical mode (1200 bps)
// -- Low level interface devices ----------------- // -- Low level interface devices -----------------
#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code) #define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor (1k6 code)
@ -630,6 +637,7 @@
#define MAX31865_PTD_RES 100 // Nominal PTD resistance at 0°C (100Ω for a PT100, 1000Ω for a PT1000, YMMV!) #define MAX31865_PTD_RES 100 // Nominal PTD resistance at 0°C (100Ω for a PT100, 1000Ω for a PT1000, YMMV!)
#define MAX31865_REF_RES 430 // Reference resistor (Usually 430Ω for a PT100, 4300Ω for a PT1000) #define MAX31865_REF_RES 430 // Reference resistor (Usually 430Ω for a PT100, 4300Ω for a PT1000)
#define MAX31865_PTD_BIAS 0 // To calibrate your not-so-good PTD #define MAX31865_PTD_BIAS 0 // To calibrate your not-so-good PTD
//#define USE_LMT01 // Add support for TI LMT01 temperature sensor, count pulses on single GPIO (+0k5 code)
// -- IR Remote features - all protocols from IRremoteESP8266 -------------------------- // -- IR Remote features - all protocols from IRremoteESP8266 --------------------------
// IR Full Protocols mode is activated through platform.io only. // IR Full Protocols mode is activated through platform.io only.
@ -654,6 +662,9 @@
// -- Zigbee interface ---------------------------- // -- Zigbee interface ----------------------------
//#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP (+49k code, +3k mem) //#define USE_ZIGBEE // Enable serial communication with Zigbee CC2530 flashed with ZNP (+49k code, +3k mem)
#define USE_ZIGBEE_ZNP // Enable ZNP protocol, needed for CC2530 based devices
// #define USE_ZIGBEE_EZSP // [EXPERIMENTAL - DO NOT USE] Enable EZSP protocol, needed for EFR32 EmberZNet based devices, like Sonoff Zigbee bridge
// Note: USE_ZIGBEE_ZNP and USE_ZIGBEE_EZSP are mutually incompatible, you must select exactly one
#define USE_ZIGBEE_PANID 0x1A63 // arbitrary PAN ID for Zigbee network, must be unique in the home #define USE_ZIGBEE_PANID 0x1A63 // arbitrary PAN ID for Zigbee network, must be unique in the home
// if PANID == 0xFFFF, then the device will act as a Zigbee router, the parameters below are ignored // if PANID == 0xFFFF, then the device will act as a Zigbee router, the parameters below are ignored
// if PANID == 0xFFFE, then the device will act as a Zigbee end-device (non-router), the parameters below are ignored // if PANID == 0xFFFE, then the device will act as a Zigbee end-device (non-router), the parameters below are ignored
@ -732,9 +743,13 @@
//#define USE_ETHERNET // Add support for ethernet (Currently fixed for Olimex ESP32-PoE) //#define USE_ETHERNET // Add support for ethernet (Currently fixed for Olimex ESP32-PoE)
// Olimex ESP32-PoE // Olimex ESP32-PoE
#define ETH_TYPE 0 // [EthType] 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110 #define ETH_TYPE 0 // [EthType] 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110, 2 = ETH_PHY_IP101
#define ETH_ADDR 0 // [EthAddress] 0 = PHY0 .. 31 = PHY31 #define ETH_ADDR 0 // [EthAddress] 0 = PHY0 .. 31 = PHY31
#define ETH_CLKMODE 3 // [EthClockMode] 0 = ETH_CLOCK_GPIO0_IN, 1 = ETH_CLOCK_GPIO0_OUT, 2 = ETH_CLOCK_GPIO16_OUT, 3 = ETH_CLOCK_GPIO17_OUT #define ETH_CLKMODE 3 // [EthClockMode] 0 = ETH_CLOCK_GPIO0_IN, 1 = ETH_CLOCK_GPIO0_OUT, 2 = ETH_CLOCK_GPIO16_OUT, 3 = ETH_CLOCK_GPIO17_OUT
// wESP32-PoE
// #define ETH_TYPE 0 // [EthType] 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110, 2 = ETH_PHY_IP101
// #define ETH_ADDR 0 // [EthAddress] 0 = PHY0 .. 31 = PHY31
// #define ETH_CLKMODE 0 // [EthClockMode] 0 = ETH_CLOCK_GPIO0_IN, 1 = ETH_CLOCK_GPIO0_OUT, 2 = ETH_CLOCK_GPIO16_OUT, 3 = ETH_CLOCK_GPIO17_OUT
//#define USE_SPI // Add support for hardware SPI //#define USE_SPI // Add support for hardware SPI
//#define USE_MI_ESP32 // Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) //#define USE_MI_ESP32 // Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)

View File

@ -567,11 +567,12 @@ struct {
uint16_t windmeter_pulse_debounce; // F3A uint16_t windmeter_pulse_debounce; // F3A
int16_t windmeter_speed_factor; // F3C int16_t windmeter_speed_factor; // F3C
uint8_t windmeter_tele_pchange; // F3E uint8_t windmeter_tele_pchange; // F3E
uint8_t ledpwm_on; // F3F uint8_t ledpwm_on; // F3F
uint8_t ledpwm_off; // F40 uint8_t ledpwm_off; // F40
uint8_t tcp_baudrate; // F41 uint8_t tcp_baudrate; // F41
uint8_t fallback_module; // F42
uint8_t free_f42[118]; // F42 - Decrement if adding new Setting variables just above and below uint8_t free_f43[117]; // F43 - Decrement if adding new Setting variables just above and below
// Only 32 bit boundary variables below // Only 32 bit boundary variables below
uint16_t pulse_counter_debounce_low; // FB8 uint16_t pulse_counter_debounce_low; // FB8

View File

@ -768,6 +768,7 @@ void SettingsDefaultSet2(void)
// flag.interlock |= 0; // flag.interlock |= 0;
Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group
Settings.module = MODULE; Settings.module = MODULE;
Settings.fallback_module = FALLBACK_MODULE;
ModuleDefault(WEMOS); ModuleDefault(WEMOS);
// for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { Settings.my_gp.io[i] = GPIO_NONE; } // for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { Settings.my_gp.io[i] = GPIO_NONE; }
SettingsUpdateText(SET_FRIENDLYNAME1, PSTR(FRIENDLY_NAME)); SettingsUpdateText(SET_FRIENDLYNAME1, PSTR(FRIENDLY_NAME));
@ -1452,12 +1453,15 @@ void SettingsDelta(void)
Settings.flag4.network_wifi = 1; Settings.flag4.network_wifi = 1;
Settings.flag4.network_ethernet = 1; Settings.flag4.network_ethernet = 1;
} }
if (Settings.version < 0x08030105) {
#ifdef ESP32 #ifdef ESP32
if (Settings.version < 0x08030105) {
Settings.eth_type = ETH_TYPE; Settings.eth_type = ETH_TYPE;
Settings.eth_clk_mode = ETH_CLKMODE; Settings.eth_clk_mode = ETH_CLKMODE;
Settings.eth_address = ETH_ADDR; Settings.eth_address = ETH_ADDR;
}
#endif #endif
if (Settings.version < 0x08030106) {
Settings.fallback_module = FALLBACK_MODULE;
} }
Settings.version = VERSION; Settings.version = VERSION;

View File

@ -1359,7 +1359,15 @@ bool JsonTemplate(const char* dataBuf)
} }
if (obj[D_JSON_GPIO].success()) { if (obj[D_JSON_GPIO].success()) {
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) {
#ifdef ESP8266
Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0; Settings.user_template.gp.io[i] = obj[D_JSON_GPIO][i] | 0;
#else // ESP32
uint16_t gpio = obj[D_JSON_GPIO][i] | 0;
if (gpio == (AGPIO(GPIO_NONE) +1)) {
gpio = AGPIO(GPIO_USER);
}
Settings.user_template.gp.io[i] = gpio;
#endif
} }
} }
if (obj[D_JSON_FLAG].success()) { if (obj[D_JSON_FLAG].success()) {
@ -1378,7 +1386,15 @@ void TemplateJson(void)
{ {
Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME)); Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), SettingsText(SET_TEMPLATE_NAME));
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) { for (uint32_t i = 0; i < ARRAY_SIZE(Settings.user_template.gp.io); i++) {
#ifdef ESP8266
ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]);
#else // ESP32
uint16_t gpio = Settings.user_template.gp.io[i];
if (gpio == AGPIO(GPIO_USER)) {
gpio = AGPIO(GPIO_NONE) +1;
}
ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", gpio);
#endif
} }
ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1);
} }
@ -1604,8 +1620,8 @@ void I2cScan(char *devs, unsigned int devs_len)
// Return error codes defined in twi.h and core_esp8266_si2c.c // Return error codes defined in twi.h and core_esp8266_si2c.c
// I2C_OK 0 // I2C_OK 0
// I2C_SCL_HELD_LOW 1 = SCL held low by another device, no procedure available to recover // I2C_SCL_HELD_LOW 1 = SCL held low by another device, no procedure available to recover
// I2C_SCL_HELD_LOW_AFTER_READ 2 = I2C bus error. SCL held low beyond slave clock stretch time // I2C_SCL_HELD_LOW_AFTER_READ 2 = I2C bus error. SCL held low beyond client clock stretch time
// I2C_SDA_HELD_LOW 3 = I2C bus error. SDA line held low by slave/another_master after n bits // I2C_SDA_HELD_LOW 3 = I2C bus error. SDA line held low by client/another_master after n bits
// I2C_SDA_HELD_LOW_AFTER_INIT 4 = line busy. SDA again held low by another device. 2nd master? // I2C_SDA_HELD_LOW_AFTER_INIT 4 = line busy. SDA again held low by another device. 2nd master?
uint8_t error = 0; uint8_t error = 0;

View File

@ -1018,18 +1018,29 @@ void CmndModule(void)
present = ValidTemplateModule(XdrvMailbox.payload); present = ValidTemplateModule(XdrvMailbox.payload);
} }
if (present) { if (present) {
Settings.last_module = Settings.module; if (XdrvMailbox.index == 2) {
Settings.module = XdrvMailbox.payload; Settings.fallback_module = XdrvMailbox.payload;
SetModuleType(); } else {
if (Settings.last_module != XdrvMailbox.payload) { Settings.last_module = Settings.module;
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) { Settings.module = XdrvMailbox.payload;
Settings.my_gp.io[i] = GPIO_NONE; SetModuleType();
if (Settings.last_module != XdrvMailbox.payload) {
for (uint32_t i = 0; i < ARRAY_SIZE(Settings.my_gp.io); i++) {
Settings.my_gp.io[i] = GPIO_NONE;
}
} }
restart_flag = 2;
} }
restart_flag = 2;
} }
} }
Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, ModuleNr(), ModuleName().c_str()); uint8_t module_real = Settings.module;
uint8_t module_number = ModuleNr();
if (XdrvMailbox.index == 2) {
module_real = Settings.fallback_module;
module_number = (USER_MODULE == Settings.fallback_module) ? 0 : Settings.fallback_module +1;
strcat(XdrvMailbox.command, "2");
}
Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, module_number, AnyModuleName(module_real).c_str());
} }
void CmndModules(void) void CmndModules(void)

View File

@ -477,8 +477,8 @@ void GetFeatures(void)
#ifdef USE_EXS_DIMMER #ifdef USE_EXS_DIMMER
feature5 |= 0x00008000; // xdrv_30_exs_dimmer.ino feature5 |= 0x00008000; // xdrv_30_exs_dimmer.ino
#endif #endif
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
feature5 |= 0x00010000; // xdrv_31_arduino_slave.ino feature5 |= 0x00010000; // xdrv_31_tasmota_client.ino
#endif #endif
#ifdef USE_HIH6 #ifdef USE_HIH6
feature5 |= 0x00020000; // xsns_55_hih_series.ino feature5 |= 0x00020000; // xsns_55_hih_series.ino
@ -587,8 +587,9 @@ void GetFeatures(void)
#ifdef USE_TELEINFO #ifdef USE_TELEINFO
feature6 |= 0x00040000; // xnrg_15_teleinfo.ino feature6 |= 0x00040000; // xnrg_15_teleinfo.ino
#endif #endif
#ifdef USE_LMT01
// feature6 |= 0x00080000; feature6 |= 0x00080000; // xsns_74_lmt01.ino
#endif
// feature6 |= 0x00100000; // feature6 |= 0x00100000;
// feature6 |= 0x00200000; // feature6 |= 0x00200000;

View File

@ -379,7 +379,7 @@ void RtcSecond(void)
Rtc.millis = millis(); Rtc.millis = millis();
if (!Rtc.user_time_entry) { if (!Rtc.user_time_entry) {
if (!global_state.wifi_down) { if (!global_state.network_down) {
uint8_t uptime_minute = (uptime / 60) % 60; // 0 .. 59 uint8_t uptime_minute = (uptime / 60) % 60; // 0 .. 59
if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) { if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) {
Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle

View File

@ -203,7 +203,8 @@ const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to
#define KNX_SLOT3 28 #define KNX_SLOT3 28
#define KNX_SLOT4 29 #define KNX_SLOT4 29
#define KNX_SLOT5 30 #define KNX_SLOT5 30
#define KNX_MAX_device_param 30 #define KNX_SCENE 31
#define KNX_MAX_device_param 31
#define MAX_KNXTX_CMNDS 5 #define MAX_KNXTX_CMNDS 5
/*********************************************************************************************\ /*********************************************************************************************\

View File

@ -278,12 +278,8 @@ void setup(void) {
#endif #endif
} }
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times
#ifdef ESP8266 Settings.module = Settings.fallback_module; // Reset module to fallback module
Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic // Settings.last_module = Settings.fallback_module;
// Settings.last_module = SONOFF_BASIC;
#else // ESP32
Settings.module = WEMOS; // Reset module to Wemos
#endif // ESP8266 - ESP32
} }
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count); AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count);
} }

View File

@ -152,7 +152,7 @@
#define USE_HM10 // (ESP8266 only) Add support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) #define USE_HM10 // (ESP8266 only) Add support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code)
//#define USE_MI_ESP32 // (ESP32 only) Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) //#define USE_MI_ESP32 // (ESP32 only) Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
#define USE_HRXL // Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) #define USE_HRXL // Add support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
//#define USE_TASMOTA_SLAVE // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) //#define USE_TASMOTA_CLIENT // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
//#define USE_OPENTHERM // Add support for OpenTherm (+15k code) //#define USE_OPENTHERM // Add support for OpenTherm (+15k code)
//#define USE_MCP9808 // Add support for MCP9808 temperature sensor (+0k9 code) //#define USE_MCP9808 // Add support for MCP9808 temperature sensor (+0k9 code)
//#define USE_HP303B // Add support for HP303B temperature and pressure sensor (I2C address 0x76 or 0x77) (+6k2 code) //#define USE_HP303B // Add support for HP303B temperature and pressure sensor (I2C address 0x76 or 0x77) (+6k2 code)
@ -176,6 +176,7 @@
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram) #define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram)
#define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram) #define USE_IR_RECEIVE // Support for IR receiver (+5k5 code, 264 iram)
#define USE_LMT01 // Add support for TI LMT01 temperature sensor, count pulses on single GPIO (+0k5 code)
#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code) #define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code)
#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) #define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code)
#define USE_HX711 // Add support for HX711 load cell (+1k5 code) #define USE_HX711 // Add support for HX711 load cell (+1k5 code)
@ -382,7 +383,7 @@
#undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) #undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code)
#undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) #undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) #undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
#undef USE_TASMOTA_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
#undef USE_OPENTHERM // Disable support for OpenTherm (+15k code) #undef USE_OPENTHERM // Disable support for OpenTherm (+15k code)
//#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor //#define USE_DHT // Add support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor
@ -487,7 +488,7 @@
#undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) #undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code)
#undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) #undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) #undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
#undef USE_TASMOTA_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
#undef USE_OPENTHERM // Disable support for OpenTherm (+15k code) #undef USE_OPENTHERM // Disable support for OpenTherm (+15k code)
//#undef USE_ENERGY_SENSOR // Disable energy sensors //#undef USE_ENERGY_SENSOR // Disable energy sensors
@ -614,7 +615,7 @@
#undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code) #undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code)
#undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash) #undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7) #undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
#undef USE_TASMOTA_SLAVE // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem) #undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
#undef USE_OPENTHERM // Disable support for OpenTherm (+15k code) #undef USE_OPENTHERM // Disable support for OpenTherm (+15k code)
#undef USE_ENERGY_SENSOR // Disable energy sensors #undef USE_ENERGY_SENSOR // Disable energy sensors

View File

@ -69,6 +69,18 @@ String EthernetMacAddress(void);
#ifdef USE_EMULATION_WEMO #ifdef USE_EMULATION_WEMO
#define USE_EMULATION #define USE_EMULATION
#endif #endif
// Convert legacy slave to client
#ifdef USE_TASMOTA_SLAVE
#define USE_TASMOTA_CLIENT
#endif
#ifdef USE_TASMOTA_SLAVE_FLASH_SPEED
#define USE_TASMOTA_CLIENT_FLASH_SPEED USE_TASMOTA_SLAVE_FLASH_SPEED
#endif
#ifdef USE_TASMOTA_SLAVE_SERIAL_SPEED
#define USE_TASMOTA_CLIENT_SERIAL_SPEED USE_TASMOTA_SLAVE_SERIAL_SPEED
#endif
// See https://github.com/esp8266/Arduino/pull/4889 // See https://github.com/esp8266/Arduino/pull/4889
#undef NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) #undef NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions)
@ -287,6 +299,9 @@ const char kWebColors[] PROGMEM =
#ifndef MODULE #ifndef MODULE
#define MODULE SONOFF_BASIC // [Module] Select default model #define MODULE SONOFF_BASIC // [Module] Select default model
#endif #endif
#ifndef FALLBACK_MODULE
#define FALLBACK_MODULE SONOFF_BASIC // [Module2] Select default module on fast reboot where USER_MODULE is user template
#endif
#ifndef ARDUINO_ESP8266_RELEASE #ifndef ARDUINO_ESP8266_RELEASE
#define ARDUINO_CORE_RELEASE "STAGE" #define ARDUINO_CORE_RELEASE "STAGE"
@ -301,6 +316,9 @@ const char kWebColors[] PROGMEM =
#ifndef MODULE #ifndef MODULE
#define MODULE WEMOS // [Module] Select default model #define MODULE WEMOS // [Module] Select default model
#endif #endif
#ifndef FALLBACK_MODULE
#define FALLBACK_MODULE WEMOS // [Module2] Select default module on fast reboot where USER_MODULE is user template
#endif
#ifndef ARDUINO_ESP32_RELEASE #ifndef ARDUINO_ESP32_RELEASE
#define ARDUINO_CORE_RELEASE "STAGE" #define ARDUINO_CORE_RELEASE "STAGE"

View File

@ -137,8 +137,8 @@ enum UserSelectablePins {
GPIO_TUYA_RX, // Tuya Serial interface GPIO_TUYA_RX, // Tuya Serial interface
GPIO_MGC3130_XFER, // MGC3130 Transfer GPIO_MGC3130_XFER, // MGC3130 Transfer
GPIO_MGC3130_RESET, // MGC3130 Reset GPIO_MGC3130_RESET, // MGC3130 Reset
GPIO_SSPI_MISO, // Software SPI Master Input Slave Output GPIO_SSPI_MISO, // Software SPI Master Input Client Output
GPIO_SSPI_MOSI, // Software SPI Master Output Slave Input GPIO_SSPI_MOSI, // Software SPI Master Output Client Input
GPIO_SSPI_SCLK, // Software SPI Serial Clock GPIO_SSPI_SCLK, // Software SPI Serial Clock
GPIO_SSPI_CS, // Software SPI Chip Select GPIO_SSPI_CS, // Software SPI Chip Select
GPIO_SSPI_DC, // Software SPI Data or Command GPIO_SSPI_DC, // Software SPI Data or Command
@ -210,10 +210,10 @@ enum UserSelectablePins {
GPIO_SM2135_DAT, // SM2135 Dat GPIO_SM2135_DAT, // SM2135 Dat
GPIO_DEEPSLEEP, // Kill switch for deepsleep GPIO_DEEPSLEEP, // Kill switch for deepsleep
GPIO_EXS_ENABLE, // EXS MCU Enable GPIO_EXS_ENABLE, // EXS MCU Enable
GPIO_TASMOTASLAVE_TXD, // Slave TX GPIO_TASMOTACLIENT_TXD, // Client TX
GPIO_TASMOTASLAVE_RXD, // Slave RX GPIO_TASMOTACLIENT_RXD, // Client RX
GPIO_TASMOTASLAVE_RST, // Slave Reset Pin GPIO_TASMOTACLIENT_RST, // Client Reset Pin
GPIO_TASMOTASLAVE_RST_INV, // Slave Reset Inverted GPIO_TASMOTACLIENT_RST_INV, // Client Reset Inverted
GPIO_HPMA_RX, // Honeywell HPMA115S0 Serial interface GPIO_HPMA_RX, // Honeywell HPMA115S0 Serial interface
GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
GPIO_GPS_RX, // GPS serial interface GPIO_GPS_RX, // GPS serial interface
@ -238,6 +238,7 @@ enum UserSelectablePins {
GPIO_TCP_RX, // TCP Serial bridge GPIO_TCP_RX, // TCP Serial bridge
GPIO_TELEINFO_RX, // TELEINFO serial interface GPIO_TELEINFO_RX, // TELEINFO serial interface
GPIO_TELEINFO_ENABLE,// TELEINFO Enable PIN GPIO_TELEINFO_ENABLE,// TELEINFO Enable PIN
GPIO_LMT01, // LMT01 input counting pin
GPIO_SENSOR_END }; GPIO_SENSOR_END };
// Programmer selectable GPIO functionality // Programmer selectable GPIO functionality
@ -316,7 +317,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "i|" D_SENSOR_CLIENT_TX "|" D_SENSOR_CLIENT_RX "|" D_SENSOR_CLIENT_RESET "|" D_SENSOR_CLIENT_RESET "i|"
D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|"
D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|" D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|"
D_SENSOR_DS18X20 "o|" D_SENSOR_DHT11 "o|" D_SENSOR_DS18X20 "o|" D_SENSOR_DHT11 "o|"
@ -328,9 +329,10 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_AS3935 "|" D_SENSOR_PMS5003_TX "|" D_SENSOR_AS3935 "|" D_SENSOR_PMS5003_TX "|"
D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|" D_SENSOR_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
D_SENSOR_WINDMETER_SPEED "|" D_SENSOR_WINDMETER_SPEED "|"
D_SENSOR_BL0940_RX "|" D_SENSOR_BL0940_RX "|"
D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD "|" D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD "|"
D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE "|"
D_SENSOR_LMT01_PULSE
; ;
const char kSensorNamesFixed[] PROGMEM = const char kSensorNamesFixed[] PROGMEM =
@ -430,8 +432,8 @@ const uint8_t kGpioNiceList[] PROGMEM = {
#ifdef USE_SPI #ifdef USE_SPI
GPIO_SPI_CS, // SPI Chip Select GPIO_SPI_CS, // SPI Chip Select
GPIO_SPI_DC, // SPI Data Direction GPIO_SPI_DC, // SPI Data Direction
GPIO_SSPI_MISO, // Software SPI Master Input Slave Output GPIO_SSPI_MISO, // Software SPI Master Input Client Output
GPIO_SSPI_MOSI, // Software SPI Master Output Slave Input GPIO_SSPI_MOSI, // Software SPI Master Output Client Input
GPIO_SSPI_SCLK, // Software SPI Serial Clock GPIO_SSPI_SCLK, // Software SPI Serial Clock
GPIO_SSPI_CS, // Software SPI Chip Select GPIO_SSPI_CS, // Software SPI Chip Select
GPIO_SSPI_DC, // Software SPI Data or Command GPIO_SSPI_DC, // Software SPI Data or Command
@ -450,6 +452,9 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_DSB, // Single wire DS18B20 or DS18S20 GPIO_DSB, // Single wire DS18B20 or DS18S20
GPIO_DSB_OUT, // Pseudo Single wire DS18B20 or DS18S20 GPIO_DSB_OUT, // Pseudo Single wire DS18B20 or DS18S20
#endif #endif
#ifdef USE_LMT01 // LMT01, count pulses on GPIO
GPIO_LMT01,
#endif
// Light // Light
#ifdef USE_LIGHT #ifdef USE_LIGHT
@ -625,11 +630,11 @@ const uint8_t kGpioNiceList[] PROGMEM = {
GPIO_PN532_TXD, // PN532 HSU Tx GPIO_PN532_TXD, // PN532 HSU Tx
GPIO_PN532_RXD, // PN532 HSU Rx GPIO_PN532_RXD, // PN532 HSU Rx
#endif #endif
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
GPIO_TASMOTASLAVE_TXD, // Tasmota Slave TX GPIO_TASMOTACLIENT_TXD, // Tasmota Client TX
GPIO_TASMOTASLAVE_RXD, // Tasmota Slave RX GPIO_TASMOTACLIENT_RXD, // Tasmota Client RX
GPIO_TASMOTASLAVE_RST, // Tasmota Slave Reset GPIO_TASMOTACLIENT_RST, // Tasmota Client Reset
GPIO_TASMOTASLAVE_RST_INV, // Tasmota Slave Reset Inverted GPIO_TASMOTACLIENT_RST_INV, // Tasmota Client Reset Inverted
#endif #endif
#ifdef USE_RDM6300 #ifdef USE_RDM6300
GPIO_RDM6300_RX, GPIO_RDM6300_RX,
@ -783,7 +788,7 @@ enum SupportedModules {
SUPLA1, WITTY, YUNSHAN, MAGICHOME, LUANIHVIO, KMC_70011, ARILUX_LC01, ARILUX_LC11, SONOFF_DUAL_R2, ARILUX_LC06, SUPLA1, WITTY, YUNSHAN, MAGICHOME, LUANIHVIO, KMC_70011, ARILUX_LC01, ARILUX_LC11, SONOFF_DUAL_R2, ARILUX_LC06,
SONOFF_S31, ZENGGE_ZF_WF017, SONOFF_POW_R2, SONOFF_IFAN02, BLITZWOLF_BWSHP, SHELLY1, SHELLY2, PHILIPS, NEO_COOLCAM, ESP_SWITCH, SONOFF_S31, ZENGGE_ZF_WF017, SONOFF_POW_R2, SONOFF_IFAN02, BLITZWOLF_BWSHP, SHELLY1, SHELLY2, PHILIPS, NEO_COOLCAM, ESP_SWITCH,
OBI, TECKIN, APLIC_WDP303075, TUYA_DIMMER, GOSUND, ARMTRONIX_DIMMERS, SK03_TUYA, PS_16_DZ, TECKIN_US, MANZOKU_EU_4, OBI, TECKIN, APLIC_WDP303075, TUYA_DIMMER, GOSUND, ARMTRONIX_DIMMERS, SK03_TUYA, PS_16_DZ, TECKIN_US, MANZOKU_EU_4,
OBI2, YTF_IR_BRIDGE, DIGOO, KA10, ZX2820, MI_DESK_LAMP, SP10, WAGA, SYF05, SONOFF_L1, OBI2, YTF_IR_BRIDGE, DIGOO, KA10, ZX2820, MI_DESK_LAMP, SP10, WAGA, SYF05, SONOFF_L1,
SONOFF_IFAN03, EXS_DIMMER, PWM_DIMMER, SONOFF_D1, SONOFF_IFAN03, EXS_DIMMER, PWM_DIMMER, SONOFF_D1,
MAXMODULE}; MAXMODULE};
@ -2264,10 +2269,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status
0, 0, 0, 0 0, 0, 0, 0
} }
}; };
#endif // ESP8266 #endif // ESP8266
#ifdef ESP32 #ifdef ESP32

View File

@ -102,8 +102,8 @@ enum UserSelectablePins {
GPIO_SM2135_CLK, GPIO_SM2135_DAT, // SM2135 PWM controller GPIO_SM2135_CLK, GPIO_SM2135_DAT, // SM2135 PWM controller
GPIO_DEEPSLEEP, // Kill switch for deepsleep GPIO_DEEPSLEEP, // Kill switch for deepsleep
GPIO_EXS_ENABLE, // EXS MCU Enable GPIO_EXS_ENABLE, // EXS MCU Enable
GPIO_TASMOTASLAVE_TXD, GPIO_TASMOTASLAVE_RXD, // Slave Serial interface GPIO_TASMOTACLIENT_TXD, GPIO_TASMOTACLIENT_RXD, // Client Serial interface
GPIO_TASMOTASLAVE_RST, GPIO_TASMOTASLAVE_RST_INV, // Slave Reset GPIO_TASMOTACLIENT_RST, GPIO_TASMOTACLIENT_RST_INV, // Client Reset
GPIO_HPMA_RX, GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface GPIO_HPMA_RX, GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
GPIO_GPS_RX, GPIO_GPS_TX, // GPS Serial interface GPIO_GPS_RX, GPIO_GPS_TX, // GPS Serial interface
GPIO_HM10_RX, GPIO_HM10_TX, // HM10-BLE-Mijia-bridge Serial interface GPIO_HM10_RX, GPIO_HM10_TX, // HM10-BLE-Mijia-bridge Serial interface
@ -133,6 +133,7 @@ enum UserSelectablePins {
GPIO_ETH_PHY_POWER, GPIO_ETH_PHY_MDC, GPIO_ETH_PHY_MDIO, // Ethernet GPIO_ETH_PHY_POWER, GPIO_ETH_PHY_MDC, GPIO_ETH_PHY_MDIO, // Ethernet
GPIO_TELEINFO_RX, // Teleinfo telemetry data receive pin GPIO_TELEINFO_RX, // Teleinfo telemetry data receive pin
GPIO_TELEINFO_ENABLE, // Teleinfo Enable Receive Pin GPIO_TELEINFO_ENABLE, // Teleinfo Enable Receive Pin
GPIO_LMT01, // LMT01 input counting pin
GPIO_SENSOR_END }; GPIO_SENSOR_END };
enum ProgramSelectablePins { enum ProgramSelectablePins {
@ -199,7 +200,7 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|" D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|" D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|" D_SENSOR_DEEPSLEEP "|" D_SENSOR_EXS_ENABLE "|"
D_SENSOR_SLAVE_TX "|" D_SENSOR_SLAVE_RX "|" D_SENSOR_SLAVE_RESET "|" D_SENSOR_SLAVE_RESET "_i|" D_SENSOR_CLIENT_TX "|" D_SENSOR_CLIENT_RX "|" D_SENSOR_CLIENT_RESET "|" D_SENSOR_CLIENT_RESET "_i|"
D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|" D_SENSOR_HPMA_RX "|" D_SENSOR_HPMA_TX "|"
D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|" D_SENSOR_GPS_RX "|" D_SENSOR_GPS_TX "|"
D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX "|" D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX "|"
@ -225,7 +226,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_BL0940_RX "|" D_SENSOR_BL0940_RX "|"
D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD "|" D_SENSOR_TCP_TXD "|" D_SENSOR_TCP_RXD "|"
D_SENSOR_ETH_PHY_POWER "|" D_SENSOR_ETH_PHY_MDC "|" D_SENSOR_ETH_PHY_MDIO "|" D_SENSOR_ETH_PHY_POWER "|" D_SENSOR_ETH_PHY_MDC "|" D_SENSOR_ETH_PHY_MDIO "|"
D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE "|"
D_SENSOR_LMT01_PULSE
; ;
const char kSensorNamesFixed[] PROGMEM = const char kSensorNamesFixed[] PROGMEM =
@ -269,8 +271,8 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_SPI_CLK), // SPI Clk AGPIO(GPIO_SPI_CLK), // SPI Clk
AGPIO(GPIO_SPI_CS), // SPI Chip Select AGPIO(GPIO_SPI_CS), // SPI Chip Select
AGPIO(GPIO_SPI_DC), // SPI Data Direction AGPIO(GPIO_SPI_DC), // SPI Data Direction
AGPIO(GPIO_SSPI_MISO), // Software SPI Master Input Slave Output AGPIO(GPIO_SSPI_MISO), // Software SPI Master Input Client Output
AGPIO(GPIO_SSPI_MOSI), // Software SPI Master Output Slave Input AGPIO(GPIO_SSPI_MOSI), // Software SPI Master Output Client Input
AGPIO(GPIO_SSPI_SCLK), // Software SPI Serial Clock AGPIO(GPIO_SSPI_SCLK), // Software SPI Serial Clock
AGPIO(GPIO_SSPI_CS), // Software SPI Chip Select AGPIO(GPIO_SSPI_CS), // Software SPI Chip Select
AGPIO(GPIO_SSPI_DC), // Software SPI Data or Command AGPIO(GPIO_SSPI_DC), // Software SPI Data or Command
@ -293,6 +295,9 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_DSB), // Single wire DS18B20 or DS18S20 AGPIO(GPIO_DSB), // Single wire DS18B20 or DS18S20
AGPIO(GPIO_DSB_OUT), // Pseudo Single wire DS18B20 or DS18S20 AGPIO(GPIO_DSB_OUT), // Pseudo Single wire DS18B20 or DS18S20
#endif #endif
#ifdef USE_LMT01
AGPIO(GPIO_LMT01), // LMT01, count pulses on GPIO
#endif
// Light // Light
#ifdef USE_LIGHT #ifdef USE_LIGHT
@ -468,11 +473,11 @@ const uint16_t kGpioNiceList[] PROGMEM = {
AGPIO(GPIO_PN532_TXD), // PN532 HSU Tx AGPIO(GPIO_PN532_TXD), // PN532 HSU Tx
AGPIO(GPIO_PN532_RXD), // PN532 HSU Rx AGPIO(GPIO_PN532_RXD), // PN532 HSU Rx
#endif #endif
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
AGPIO(GPIO_TASMOTASLAVE_TXD), // Tasmota Slave TX AGPIO(GPIO_TASMOTACLIENT_TXD), // Tasmota Client TX
AGPIO(GPIO_TASMOTASLAVE_RXD), // Tasmota Slave RX AGPIO(GPIO_TASMOTACLIENT_RXD), // Tasmota Client RX
AGPIO(GPIO_TASMOTASLAVE_RST), // Tasmota Slave Reset AGPIO(GPIO_TASMOTACLIENT_RST), // Tasmota Client Reset
AGPIO(GPIO_TASMOTASLAVE_RST_INV), // Tasmota Slave Reset Inverted AGPIO(GPIO_TASMOTACLIENT_RST_INV), // Tasmota Client Reset Inverted
#endif #endif
#ifdef USE_RDM6300 #ifdef USE_RDM6300
AGPIO(GPIO_RDM6300_RX), AGPIO(GPIO_RDM6300_RX),
@ -622,20 +627,14 @@ typedef struct MYTMPLT {
/********************************************************************************************/ /********************************************************************************************/
// Supported hardware modules // Supported hardware modules
enum SupportedModules { enum SupportedModules { WEMOS, ESP32_CAM_AITHINKER, MAXMODULE };
WEMOS, ESP32_CAM_AITHINKER,
MAXMODULE};
#define USER_MODULE 255 #define USER_MODULE 255
const char kModuleNames[] PROGMEM = const char kModuleNames[] PROGMEM = "ESP32-DevKit|ESP32 Cam AiThinker";
"ESP32-DevKit|ESP32 Cam AiThinker";
// Default module settings // Default module settings
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { WEMOS, ESP32_CAM_AITHINKER };
WEMOS,
ESP32_CAM_AITHINKER
};
const mytmplt kModules PROGMEM = const mytmplt kModules PROGMEM =
{ // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32) { // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
@ -685,12 +684,12 @@ const mytmplt kModules PROGMEM =
/*********************************************************************************************\ /*********************************************************************************************\
Known templates Known templates
{"NAME":"AITHINKER CAM","GPIO":[4992,65504,65504,65504,65504,5088,65504,65504,65504,65504,65504,65504,65504,65504,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,65504,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":1} {"NAME":"AITHINKER CAM","GPIO":[4992,1,1,1,1,5088,1,1,1,1,1,1,1,1,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,1,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":1}
{"NAME":"Olimex ESP32-PoE","GPIO":[65504,65504,65504,65504,65504,65504,0,0,5536,65504,65504,65504,65504,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,65504,65504,65504,65504,65504,0,0,65504],"FLAG":0,"BASE":1} {"NAME":"Olimex ESP32-PoE","GPIO":[1,1,1,1,1,1,0,0,5536,1,1,1,1,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1],"FLAG":0,"BASE":1}
{"NAME":"wESP32","GPIO":[1,1,1,1,1,1,0,0,0,1,1,1,5568,5600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1],"FLAG":0,"BASE":1}
\*********************************************************************************************/ \*********************************************************************************************/
#endif // ESP32 #endif // ESP32
#endif // _TASMOTA_TEMPLATE_ESP32_H_ #endif // _TASMOTA_TEMPLATE_ESP32_H_

View File

@ -20,7 +20,7 @@
#ifndef _TASMOTA_VERSION_H_ #ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_
const uint32_t VERSION = 0x08030105; const uint32_t VERSION = 0x08030106;
// Lowest compatible version // Lowest compatible version
const uint32_t VERSION_COMPATIBLE = 0x07010006; const uint32_t VERSION_COMPATIBLE = 0x07010006;

View File

@ -44,7 +44,7 @@ const uint16_t HTTP_OTA_RESTART_RECONNECT_TIME = 28000; // milliseconds - Allow
uint8_t *efm8bb1_update = nullptr; uint8_t *efm8bb1_update = nullptr;
#endif // USE_RF_FLASH #endif // USE_RF_FLASH
enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTASLAVE }; enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTACLIENT };
static const char * HEADER_KEYS[] = { "User-Agent", }; static const char * HEADER_KEYS[] = { "User-Agent", };
@ -2022,8 +2022,8 @@ void ModuleSaveSettings(void)
/*-------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------*/
const char kUnescapeCode[] = "&><\"\'"; const char kUnescapeCode[] = "&><\"\'\\";
const char kEscapeCode[] PROGMEM = "&amp;|&gt;|&lt;|&quot;|&apos;"; const char kEscapeCode[] PROGMEM = "&amp;|&gt;|&lt;|&quot;|&apos;|&#92;";
String HtmlEscape(const String unescaped) { String HtmlEscape(const String unescaped) {
char escaped[10]; char escaped[10];
@ -2327,22 +2327,6 @@ void OtherSaveSettings(void)
} }
AddLog_P(LOG_LEVEL_INFO, message); AddLog_P(LOG_LEVEL_INFO, message);
/*
// This sometimes provides intermittent watchdog
bool template_activate = Webserver->hasArg("t2"); // Try this to tackle intermittent watchdog after execution of Template command
WebGetArg("t1", tmp, sizeof(tmp));
if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255}
char svalue[128];
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_TEMPLATE " %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI);
if (template_activate) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_MODULE " 0"));
ExecuteWebCommand(svalue, SRC_WEBGUI);
}
}
// Try async execution of commands
*/
WebGetArg("t1", tmp, sizeof(tmp)); WebGetArg("t1", tmp, sizeof(tmp));
if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255} if (strlen(tmp)) { // {"NAME":"12345678901234","GPIO":[255,255,255,255,255,255,255,255,255,255,255,255,255],"FLAG":255,"BASE":255}
snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : ""); snprintf_P(message, sizeof(message), PSTR(D_CMND_BACKLOG " " D_CMND_TEMPLATE " %s%s"), tmp, (Webserver->hasArg("t2")) ? "; " D_CMND_MODULE " 0" : "");
@ -2489,7 +2473,7 @@ void HandleInformation(void)
#endif #endif
if (Settings.flag4.network_wifi) { if (Settings.flag4.network_wifi) {
int32_t rssi = WiFi.RSSI(); int32_t rssi = WiFi.RSSI();
WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, SettingsText(SET_STASSID1 + Settings.sta_active), WifiGetRssiAsQuality(rssi), rssi); WSContentSend_P(PSTR("}1" D_AP "%d " D_SSID " (" D_RSSI ")}2%s (%d%%, %d dBm)"), Settings.sta_active +1, HtmlEscape(SettingsText(SET_STASSID1 + Settings.sta_active)).c_str(), WifiGetRssiAsQuality(rssi), rssi);
WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Mdns.begun) ? ".local" : ""); WSContentSend_P(PSTR("}1" D_HOSTNAME "}2%s%s"), my_hostname, (Mdns.begun) ? ".local" : "");
#if LWIP_IPV6 #if LWIP_IPV6
String ipv6_addr = WifiGetIPv6(); String ipv6_addr = WifiGetIPv6();
@ -2508,7 +2492,7 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str()); WSContentSend_P(PSTR("}1" D_SUBNET_MASK "}2%s"), IPAddress(Settings.ip_address[2]).toString().c_str());
WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str()); WSContentSend_P(PSTR("}1" D_DNS_SERVER "}2%s"), IPAddress(Settings.ip_address[3]).toString().c_str());
} }
if (static_cast<uint32_t>(WiFi.softAPIP()) != 0) { if ((WiFi.getMode() >= WIFI_AP) && (static_cast<uint32_t>(WiFi.softAPIP()) != 0)) {
WSContentSend_P(PSTR("}1<hr/>}2<hr/>")); WSContentSend_P(PSTR("}1<hr/>}2<hr/>"));
WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str()); WSContentSend_P(PSTR("}1" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().c_str());
WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (AP)}2%s"), WiFi.softAPIP().toString().c_str()); WSContentSend_P(PSTR("}1" D_IP_ADDRESS " (AP)}2%s"), WiFi.softAPIP().toString().c_str());
@ -2667,8 +2651,8 @@ void HandleUploadDone(void)
WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "</font></b><br>"), WebColor(COL_TEXT_SUCCESS)); WSContentSend_P(PSTR("%06x'>" D_SUCCESSFUL "</font></b><br>"), WebColor(COL_TEXT_SUCCESS));
WSContentSend_P(HTTP_MSG_RSTRT); WSContentSend_P(HTTP_MSG_RSTRT);
ShowWebSource(SRC_WEBGUI); ShowWebSource(SRC_WEBGUI);
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
if (TasmotaSlave_GetFlagFlashing()) { if (TasmotaClient_GetFlagFlashing()) {
restart_flag = 0; restart_flag = 0;
} else { // It was a normal firmware file, or we are ready to restart device } else { // It was a normal firmware file, or we are ready to restart device
restart_flag = 2; restart_flag = 2;
@ -2681,9 +2665,9 @@ void HandleUploadDone(void)
WSContentSend_P(PSTR("</div><br>")); WSContentSend_P(PSTR("</div><br>"));
WSContentSpaceButton(BUTTON_MAIN); WSContentSpaceButton(BUTTON_MAIN);
WSContentStop(); WSContentStop();
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
if (TasmotaSlave_GetFlagFlashing()) { if (TasmotaClient_GetFlagFlashing()) {
TasmotaSlave_Flash(); TasmotaClient_Flash();
} }
#endif #endif
} }
@ -2753,11 +2737,11 @@ void HandleUploadLoop(void)
if (Web.upload_error != 0) { return; } if (Web.upload_error != 0) { return; }
} else } else
#endif // USE_RF_FLASH #endif // USE_RF_FLASH
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO SLAVE hex file if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO CLIENT hex file
Update.end(); // End esp8266 update session Update.end(); // End esp8266 update session
Web.upload_file_type = UPL_TASMOTASLAVE; Web.upload_file_type = UPL_TASMOTACLIENT;
Web.upload_error = TasmotaSlave_UpdateInit(); // 0 Web.upload_error = TasmotaClient_UpdateInit(); // 0
if (Web.upload_error != 0) { return; } if (Web.upload_error != 0) { return; }
} else } else
#endif #endif
@ -2821,9 +2805,9 @@ void HandleUploadLoop(void)
} }
} }
#endif // USE_RF_FLASH #endif // USE_RF_FLASH
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
else if (UPL_TASMOTASLAVE == Web.upload_file_type) { else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
TasmotaSlave_WriteBuffer(upload.buf, upload.currentSize); TasmotaClient_WriteBuffer(upload.buf, upload.currentSize);
} }
#endif #endif
else { // firmware else { // firmware
@ -2887,10 +2871,10 @@ void HandleUploadLoop(void)
Web.upload_file_type = UPL_TASMOTA; Web.upload_file_type = UPL_TASMOTA;
} }
#endif // USE_RF_FLASH #endif // USE_RF_FLASH
#ifdef USE_TASMOTA_SLAVE #ifdef USE_TASMOTA_CLIENT
else if (UPL_TASMOTASLAVE == Web.upload_file_type) { else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
// Done writing the hex to SPI flash // Done writing the hex to SPI flash
TasmotaSlave_SetFlagFlashing(true); // So we know on upload success page if it needs to flash hex or do a normal restart TasmotaClient_SetFlagFlashing(true); // So we know on upload success page if it needs to flash hex or do a normal restart
Web.upload_file_type = UPL_TASMOTA; Web.upload_file_type = UPL_TASMOTA;
} }
#endif #endif

View File

@ -397,7 +397,7 @@ void ScriptEverySecond(void) {
if (bitRead(Settings.rule_enabled, 0)) { if (bitRead(Settings.rule_enabled, 0)) {
struct T_INDEX *vtp=glob_script_mem.type; struct T_INDEX *vtp=glob_script_mem.type;
float delta=(millis()-script_lastmillis)/1000; float delta=(millis()-script_lastmillis)/1000.0;
script_lastmillis=millis(); script_lastmillis=millis();
for (uint8_t count=0; count<glob_script_mem.numvars; count++) { for (uint8_t count=0; count<glob_script_mem.numvars; count++) {
if (vtp[count].bits.is_timer) { if (vtp[count].bits.is_timer) {

View File

@ -114,6 +114,7 @@ device_parameters_t device_param[] = {
{ KNX_SLOT3 , false, false, KNX_Empty }, { KNX_SLOT3 , false, false, KNX_Empty },
{ KNX_SLOT4 , false, false, KNX_Empty }, { KNX_SLOT4 , false, false, KNX_Empty },
{ KNX_SLOT5 , false, false, KNX_Empty }, { KNX_SLOT5 , false, false, KNX_Empty },
{ KNX_SCENE , false, false, KNX_Empty },
{ KNX_Empty, false, false, KNX_Empty} { KNX_Empty, false, false, KNX_Empty}
}; };
@ -149,6 +150,7 @@ const char * device_param_ga[] = {
D_KNX_TX_SLOT " 3", D_KNX_TX_SLOT " 3",
D_KNX_TX_SLOT " 4", D_KNX_TX_SLOT " 4",
D_KNX_TX_SLOT " 5", D_KNX_TX_SLOT " 5",
D_KNX_TX_SCENE ,
nullptr nullptr
}; };
@ -184,6 +186,7 @@ const char *device_param_cb[] = {
D_KNX_RX_SLOT " 3", D_KNX_RX_SLOT " 3",
D_KNX_RX_SLOT " 4", D_KNX_RX_SLOT " 4",
D_KNX_RX_SLOT " 5", D_KNX_RX_SLOT " 5",
D_KNX_RX_SCENE ,
nullptr nullptr
}; };
@ -196,12 +199,14 @@ const char *device_param_cb[] = {
#define D_CMND_KNX_PA "_PA" #define D_CMND_KNX_PA "_PA"
#define D_CMND_KNX_GA "_GA" #define D_CMND_KNX_GA "_GA"
#define D_CMND_KNX_CB "_CB" #define D_CMND_KNX_CB "_CB"
#define D_CMND_KNXTXSCENE "Tx_Scene"
const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" // Prefix const char kKnxCommands[] PROGMEM = D_PRFX_KNX "|" // Prefix
D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB ; D_CMND_KNXTXCMND "|" D_CMND_KNXTXVAL "|" D_CMND_KNX_ENABLED "|" D_CMND_KNX_ENHANCED "|" D_CMND_KNX_PA "|" D_CMND_KNX_GA "|" D_CMND_KNX_CB "|" D_CMND_KNXTXSCENE ;
void (* const KnxCommand[])(void) PROGMEM = { void (* const KnxCommand[])(void) PROGMEM = {
&CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb }; &CmndKnxTxCmnd, &CmndKnxTxVal, &CmndKnxEnabled, &CmndKnxEnhanced, &CmndKnxPa, &CmndKnxGa, &CmndKnxCb, &CmndKnxTxScene };
uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 ) uint8_t KNX_GA_Search( uint8_t param, uint8_t start = 0 )
{ {
@ -518,6 +523,7 @@ void KNX_INIT(void)
device_param[KNX_SLOT3-1].show = true; device_param[KNX_SLOT3-1].show = true;
device_param[KNX_SLOT4-1].show = true; device_param[KNX_SLOT4-1].show = true;
device_param[KNX_SLOT5-1].show = true; device_param[KNX_SLOT5-1].show = true;
device_param[KNX_SCENE-1].show = true;
#endif #endif
// Delete from KNX settings all configuration is not anymore related to this device // Delete from KNX settings all configuration is not anymore related to this device
@ -557,7 +563,11 @@ void KNX_CB_Action(message_t const &msg, void *arg)
if (msg.data_len == 1) { if (msg.data_len == 1) {
// COMMAND // COMMAND
sprintf(tempchar,"%d",msg.data[0]); sprintf(tempchar,"%d",msg.data[0]);
} else { } else if (chan->type == KNX_SCENE) {
// VALUE
uint8_t tempvar = knx.data_to_1byte_uint(msg.data);
dtostrfd(tempvar,2,tempchar);
} else {
// VALUE // VALUE
float tempvar = knx.data_to_2byte_float(msg.data); float tempvar = knx.data_to_2byte_float(msg.data);
dtostrfd(tempvar,2,tempchar); dtostrfd(tempvar,2,tempchar);
@ -602,6 +612,18 @@ void KNX_CB_Action(message_t const &msg, void *arg)
} }
} }
} }
else if (chan->type == KNX_SCENE) // KNX RX SCENE SLOT (write command)
{
if (!toggle_inhibit) {
char command[25];
// Value received
snprintf_P(command, sizeof(command), PSTR("event KNX_SCENE=%s"), tempchar);
ExecuteCommand(command, SRC_KNX);
if (Settings.flag.knx_enable_enhancement) {
toggle_inhibit = TOGGLE_INHIBIT_TIME;
}
}
}
#endif #endif
break; break;
@ -1054,6 +1076,31 @@ void CmndKnxTxVal(void)
} }
} }
void CmndKnxTxScene(void)
{
if ( (XdrvMailbox.data_len > 0) && Settings.flag.knx_enabled ) {
// XdrvMailbox.payload <- scene number to send
uint8_t i = KNX_GA_Search(KNX_SCENE);
if ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
uint8_t tempvar = TextToInt(XdrvMailbox.data);
dtostrfd(tempvar,0,XdrvMailbox.data);
knx.write_1byte_uint(KNX_addr, tempvar);
if (Settings.flag.knx_enable_enhancement) {
knx.write_1byte_uint(KNX_addr, tempvar);
knx.write_1byte_uint(KNX_addr, tempvar);
}
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_KNX "%s = %s " D_SENT_TO " %d.%d.%d"),
device_param_ga[KNX_SCENE-1], XdrvMailbox.data,
KNX_addr.ga.area, KNX_addr.ga.line, KNX_addr.ga.member);
ResponseCmndIdxChar (XdrvMailbox.data);
}
}
}
void CmndKnxEnabled(void) void CmndKnxEnabled(void)
{ {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {

View File

@ -27,14 +27,14 @@ const char kHAssJsonSensorTypes[] PROGMEM =
D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|" D_JSON_APPARENT_POWERUSAGE "|Battery|" D_JSON_CURRENT "|" D_JSON_DISTANCE "|" D_JSON_FREQUENCY "|" D_JSON_HUMIDITY "|" D_JSON_ILLUMINANCE "|"
D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" D_JSON_TOTAL_START_TIME "|" D_JSON_MOISTURE "|PB0.3|PB0.5|PB1|PB2.5|PB5|PB10|PM1|PM2.5|PM10|" D_JSON_POWERFACTOR "|" D_JSON_POWERUSAGE "|" D_JSON_TOTAL_START_TIME "|"
D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY "|" D_JSON_REACTIVE_POWERUSAGE "|" D_JSON_TODAY "|" D_JSON_TOTAL "|" D_JSON_VOLTAGE "|" D_JSON_WEIGHT "|" D_JSON_YESTERDAY "|"
D_JSON_CO2 "|" D_JSON_ECO2 "|" D_JSON_TVOC "|"; D_JSON_CO2 "|" D_JSON_ECO2 "|" D_JSON_TVOC "|" D_COLOR_RED "|" D_COLOR_GREEN "|" D_COLOR_BLUE"|" D_CCT "|" D_PROXIMITY "|Ambient|";
const char kHAssJsonSensorUnits[] PROGMEM = const char kHAssJsonSensorUnits[] PROGMEM =
"||||" "||||"
"VA|%|A|Cm|Hz|%|LX|" "VA|%|A|Cm|Hz|%|LX|"
"%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³|Cos φ|W| |" "%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³|Cos φ|W| |"
"VAr|kWh|kWh|V|Kg|kWh|" "VAr|kWh|kWh|V|Kg|kWh|"
"ppm|ppm|ppb|"; "ppm|ppm|ppb|R|G|B|" D_UNIT_KELVIN "| |LX|";
const char kHAssJsonSensorDevCla[] PROGMEM = const char kHAssJsonSensorDevCla[] PROGMEM =
"dev_cla\":\"temperature|ic\":\"mdi:weather-rainy|dev_cla\":\"pressure|dev_cla\":\"pressure|" "dev_cla\":\"temperature|ic\":\"mdi:weather-rainy|dev_cla\":\"pressure|dev_cla\":\"pressure|"
@ -42,61 +42,64 @@ const char kHAssJsonSensorDevCla[] PROGMEM =
"ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|" "ic\":\"mdi:cup-water|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|ic\":\"mdi:flask|"
"ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|ic\":\"mdi:progress-clock|" "ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:air-filter|ic\":\"mdi:alpha-f-circle-outline|dev_cla\":\"power|ic\":\"mdi:progress-clock|"
"dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power|" "dev_cla\":\"power|dev_cla\":\"power|dev_cla\":\"power|ic\":\"mdi:alpha-v-circle-outline|ic\":\"mdi:scale|dev_cla\":\"power|"
"ic\":\"mdi:periodic-table-co2|ic\":\"mdi:air-filter|ic\":\"mdi:periodic-table-co2|"; "ic\":\"mdi:periodic-table-co2|ic\":\"mdi:air-filter|ic\":\"mdi:periodic-table-co2|"
"ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:palette|ic\":\"mdi:temperature-kelvin|ic\":\"mdi:ruler|dev_cla\":\"illuminance|";
//"ic\":\"mdi:weather-windy|ic\":\"mdi:weather-windy|ic\":\"mdi:weather-windy|ic\":\"mdi:weather-windy|" //"ic\":\"mdi:weather-windy|ic\":\"mdi:weather-windy|ic\":\"mdi:weather-windy|ic\":\"mdi:weather-windy|"
// List of sensors ready for discovery // List of sensors ready for discovery
const char HASS_DISCOVER_SENSOR[] PROGMEM =
",\"unit_of_meas\":\"%s\",\"%s\"," // unit of measure and class (or icon)
"\"frc_upd\":true," // force update for better graph representation
"\"val_tpl\":\"{{value_json['%s']['%s']"; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER']['C1']
const char HASS_DISCOVER_BASE[] PROGMEM = const char HASS_DISCOVER_BASE[] PROGMEM =
"{\"name\":\"%s\"," // dualr2 1 "{\"name\":\"%s\"," // dualr2 1
"\"stat_t\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",") "\"stat_t\":\"%s\""; // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",")
"\"avty_t\":\"%s\"," // tele/dualr2/LWT
"\"pl_avail\":\"" D_ONLINE "\"," // Online const char HASS_DISCOVER_SENSOR[] PROGMEM =
"\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline ",\"unit_of_meas\":\"%s\",\"%s\"," // unit of measure and class (or icon)
"\"frc_upd\":true," // force update for better graph representation
"\"val_tpl\":\"{{value_json['%s']['%s']"; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER']['C1']
const char HASS_DISCOVER_SENSOR_LWT[] PROGMEM =
",\"avty_t\":\"%s\"," // tele/dualr2/LWT
"\"pl_avail\":\"" D_ONLINE "\"," // Online
"\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline
const char HASS_DISCOVER_RELAY[] PROGMEM = const char HASS_DISCOVER_RELAY[] PROGMEM =
",\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2 ",\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2
"\"val_tpl\":\"{{value_json.%s}}\"," // POWER2 "\"val_tpl\":\"{{value_json.%s}}\"," // POWER2
"\"pl_off\":\"%s\"," // OFF "\"pl_off\":\"%s\"," // OFF
"\"pl_on\":\"%s\""; // ON "\"pl_on\":\"%s\""; // ON
const char HASS_DISCOVER_BIN_SWITCH[] PROGMEM = const char HASS_DISCOVER_BIN_SWITCH[] PROGMEM =
",\"val_tpl\":\"{{value_json.%s}}\"," // STATE ",\"val_tpl\":\"{{value_json.%s}}\"," // STATE
"\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work "\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work
"\"pl_on\":\"%s\"," // ON "\"pl_on\":\"%s\"," // ON
"\"pl_off\":\"%s\""; // OFF "\"pl_off\":\"%s\""; // OFF
const char HASS_DISCOVER_BIN_PIR[] PROGMEM = const char HASS_DISCOVER_BIN_PIR[] PROGMEM =
",\"val_tpl\":\"{{value_json.%s}}\"," // STATE ",\"val_tpl\":\"{{value_json.%s}}\"," // STATE
"\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work "\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work
"\"pl_on\":\"%s\"," // ON "\"pl_on\":\"%s\"," // ON
"\"off_dly\":1"; // Switchmode13 and Switchmode14 doesn't transmit an OFF state. "\"off_dly\":1"; // Switchmode13 and Switchmode14 doesn't transmit an OFF state.
const char HASS_DISCOVER_BASE_LIGHT[] PROGMEM = const char HASS_DISCOVER_BASE_LIGHT[] PROGMEM =
",\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer ",\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer
"\"bri_stat_t\":\"%s\"," // stat/led2/RESULT "\"bri_stat_t\":\"%s\"," // stat/led2/RESULT
"\"bri_scl\":100," // 100% "\"bri_scl\":100," // 100%
"\"on_cmd_type\":\"%s\"," // power on (first), power on (last), no power on (brightness) "\"on_cmd_type\":\"%s\"," // power on (first), power on (last), no power on (brightness)
"\"bri_val_tpl\":\"{{value_json.%s}}\""; "\"bri_val_tpl\":\"{{value_json.%s}}\"";
const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM =
",\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 ",\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2
"\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT
"\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\"";
const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM =
",\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White ",\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White
"\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT "\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT
"\"whit_val_scl\":100," "\"whit_val_scl\":100,"
"\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\"";
const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = const char HASS_DISCOVER_LIGHT_CT[] PROGMEM =
",\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT ",\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT
"\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT
"\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\"";
const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM =
@ -141,7 +144,7 @@ const char kHAssTriggerStringButtons[] PROGMEM =
"|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|HOLD|"; "|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|HOLD|";
const char kHAssError1[] PROGMEM = const char kHAssError1[] PROGMEM =
"HASS: MQTT discovery failed due to too long topic or friendly name. Please shorten topic and/or friendly name. Failed to format"; "HASS: MQTT discovery failed due to too long topic or device/friendly name. Please shorten topic and/or device/friendly name. Failed to format";
const char kHAssError2[] PROGMEM = const char kHAssError2[] PROGMEM =
"HASS: The configuration of the Relays is wrong, there is a Light that is using an index higher than the number of the validated relay.\n " "HASS: The configuration of the Relays is wrong, there is a Light that is using an index higher than the number of the validated relay.\n "
@ -195,13 +198,22 @@ void HAssAnnounceRelayLight(void)
bool ct_light = false; // Controls a CT Light when SetOption37 is >= 128 bool ct_light = false; // Controls a CT Light when SetOption37 is >= 128
bool wt_light = false; // Controls a White Light when SetOption37 is >= 128 bool wt_light = false; // Controls a White Light when SetOption37 is >= 128
bool err_flag = false; // When true it blocks the creation of entities if the order of the Relays is not correct to avoid issue with Lights bool err_flag = false; // When true it blocks the creation of entities if the order of the Relays is not correct to avoid issue with Lights
bool TuyaMod = false; // Controls Tuya MCU modules
bool PwmMod = false; // Controls PWM_DIMMER module bool PwmMod = false; // Controls PWM_DIMMER module
bool FanMod = false; // Controls SONOFF_IFAN0X modules
uint8_t dimmer = 1; uint8_t dimmer = 1;
uint8_t valid_relay = 0;
uint8_t max_lights = 1; uint8_t max_lights = 1;
uint8_t TuyaRel = 0;
uint8_t TuyaRelInv = 0;
uint8_t TuyaDim = 0;
#ifdef ESP8266 #ifdef ESP8266
if (PWM_DIMMER == my_module_type) { PwmMod = true; } if (PWM_DIMMER == my_module_type ) { PwmMod = true; } //
if (SONOFF_IFAN02 == my_module_type || SONOFF_IFAN03 == my_module_type) { FanMod = true; }
if (SONOFF_DUAL == my_module_type) { valid_relay = 2; }
if (TUYA_DIMMER == my_module_type || SK03_TUYA == my_module_type) { TuyaMod = true; }
#endif //ESP8266 #endif //ESP8266
// If there is a special Light to be enabled and managed with SetOption68 or SetOption37 >= 128, Discovery calculates the maximum number of entities to be generated in advance // If there is a special Light to be enabled and managed with SetOption68 or SetOption37 >= 128, Discovery calculates the maximum number of entities to be generated in advance
@ -209,17 +221,21 @@ void HAssAnnounceRelayLight(void)
if (PwmMulti) { max_lights = Light.subtype; } if (PwmMulti) { max_lights = Light.subtype; }
if (!LightControl) { if (!LightControl) {
ind_light = 1; ind_light = true;
if (!PwmMulti) { max_lights = 2;} if (!PwmMulti) { max_lights = 2;}
} }
// Lights types: 0 = LST_NONE / 1 = LST_SINGLE / 2 = LST_COLDWARM / 3 = LST_RGB / 4 = LST_RGBW / 5 = LST_RGBCW
for (uint32_t i = 1; i <= MAX_RELAYS; i++) for (uint32_t i = 1; i <= MAX_RELAYS; i++)
{ {
bool RelayX = PinUsed(GPIO_REL1 +i-1);
is_topic_light = Settings.flag.hass_light && RelayX || light_type && !RelayX || PwmMod; // SetOption30 - Enforce HAss autodiscovery as light
#ifdef USE_TUYA_MCU
TuyaRel = TuyaGetDpId((TUYA_MCU_FUNC_REL1+ i-1) + active_device - 1);
TuyaRelInv = TuyaGetDpId((TUYA_MCU_FUNC_REL1_INV+ i-1) + active_device - 1);
TuyaDim = TuyaGetDpId((TUYA_MCU_FUNC_DIMMER) + active_device - 1);
#endif //USE_TUYA_MCU
bool RelayX = PinUsed(GPIO_REL1 +i-1) || (valid_relay >= i) || (TuyaRel > 0 && TuyaMod) || (TuyaRelInv > 0 && TuyaMod); // Check if the gpio is configured as Relay or force it for Sonoff DUAL R1 with MCU and Tuya MCU
is_topic_light = Settings.flag.hass_light && RelayX || light_type && !RelayX || PwmMod || (TuyaDim > 0 && TuyaMod); // SetOption30 - Enforce HAss autodiscovery as light
mqtt_data[0] = '\0'; // Clear retained message mqtt_data[0] = '\0'; // Clear retained message
// Clear "other" topic first in case the device has been reconfigured from light to switch or vice versa // Clear "other" topic first in case the device has been reconfigured from light to switch or vice versa
@ -255,13 +271,14 @@ void HAssAnnounceRelayLight(void)
GetTopic_P(command_topic, CMND, mqtt_topic, value_template); GetTopic_P(command_topic, CMND, mqtt_topic, value_template);
GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE); GetTopic_P(state_topic, TELE, mqtt_topic, D_RSLT_STATE);
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); Response_P(HASS_DISCOVER_BASE, name, state_topic);
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2)); TryResponseAppend_P(HASS_DISCOVER_RELAY, command_topic, value_template, SettingsText(SET_STATE_TXT1), SettingsText(SET_STATE_TXT2));
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId());
#ifdef USE_LIGHT #ifdef USE_LIGHT
if (i >= Light.device) { if (i >= Light.device) {
if (!RelayX || PwmMod) { if (!RelayX || PwmMod || (TuyaDim > 0 && TuyaMod)) {
char *brightness_command_topic = stemp1; char *brightness_command_topic = stemp1;
strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); // SetOption20 - Control power in relation to Dimmer/Color/Ct changes strncpy_P(stemp3, Settings.flag.not_power_linked ? PSTR("last") : PSTR("brightness"), sizeof(stemp3)); // SetOption20 - Control power in relation to Dimmer/Color/Ct changes
char channel_num[9]; char channel_num[9];
@ -411,6 +428,14 @@ void HAssAnnouncerBinSensors(uint8_t device, uint8_t present, uint8_t dual, uint
TryResponseAppend_P(HASS_DISCOVER_BIN_PIR, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2)); TryResponseAppend_P(HASS_DISCOVER_BIN_PIR, PSTR(D_RSLT_STATE), SettingsText(SET_STATE_TXT2));
} }
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId());
#ifdef DEEPSLEEP_LWT_HA_DISCOVERY
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
#else
if (Settings.deepsleep == 0)
{
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
}
#endif //DEEPSLEEP_LWT_HA_DISCOVERY
TryResponseAppend_P(PSTR("}")); TryResponseAppend_P(PSTR("}"));
} }
} }
@ -505,7 +530,7 @@ void HAssAnnounceButtons(void)
{ {
button_present = 1; button_present = 1;
} else } else
#endif #endif // ESP8266
{ {
if (PinUsed(GPIO_KEY1, button_index)) { if (PinUsed(GPIO_KEY1, button_index)) {
button_present = 1; button_present = 1;
@ -557,12 +582,21 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const
char prefix[TOPSZ]; char prefix[TOPSZ];
char *state_topic = stemp1; char *state_topic = stemp1;
char *availability_topic = stemp2; char *availability_topic = stemp2;
//bool LwtSensor = MQTT_LWT_DISCOVERY;
GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR)); GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_SENSOR));
snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_DEVICENAME), sensorname, MultiSubName); snprintf_P(name, sizeof(name), PSTR("%s %s %s"), SettingsText(SET_DEVICENAME), sensorname, MultiSubName);
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); Response_P(HASS_DISCOVER_BASE, name, state_topic);
#ifdef DEEPSLEEP_LWT_HA_DISCOVERY
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
#else
if (Settings.deepsleep == 0)
{
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
}
#endif //DEEPSLEEP_LWT_HA_DISCOVERY
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId()); TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP_getChipId());
@ -629,8 +663,8 @@ void HAssAnnounceSensors(void)
sensordata[0] = '{'; sensordata[0] = '{';
snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}} snprintf_P(sensordata, sizeof(sensordata), PSTR("%s}"), sensordata); // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}}
// USE THE FOLLOWING LINE TO TEST JSON // USE THE FOLLOWING LINE TO TEST JSON
//snprintf_P(sensordata, sizeof(sensordata), PSTR("{\"HX711\":{\"Weight\":[22,34,1023.4]}}")); //snprintf_P(sensordata, sizeof(sensordata), PSTR("{\"APDS9960\":{\"Red\":282,\"Green\":252,\"Blue\":196,\"Ambient\":169,\"CCT\":4217,\"Proximity\":9}}"));
//snprintf_P(sensordata, sizeof(sensordata), PSTR("{\"ENERGY\":{\"TotalStartTime\":\"2018-11-23T15:33:47\",\"Total\":0.017,\"TotalTariff\":[0.000,0.017],\"Yesterday\":0.000,\"Today\":0.002,\"ExportActive\":0.000,\"ExportTariff\":[0.000,0.000],\"Period\":0.00,\"Power\":0.00,\"ApparentPower\":7.84,\"ReactivePower\":-7.21,\"Factor\":0.39,\"Frequency\":50.0,\"Voltage\":234.31,\"Current\":0.039,\"ImportActive\":12.580,\"ImportReactive\":0.002,\"ExportReactive\":39.131,\"PhaseAngle\":290.45}}"));
StaticJsonBuffer<500> jsonBuffer; StaticJsonBuffer<500> jsonBuffer;
JsonObject &root = jsonBuffer.parseObject(sensordata); JsonObject &root = jsonBuffer.parseObject(sensordata);
@ -703,7 +737,8 @@ void HAssAnnounceDeviceInfoAndStatusSensor(void)
GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE));
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
Response_P(HASS_DISCOVER_BASE, name, state_topic, availability_topic); Response_P(HASS_DISCOVER_BASE, name, state_topic);
TryResponseAppend_P(HASS_DISCOVER_SENSOR_LWT, availability_topic);
TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic);
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP_getChipId(), SettingsText(SET_DEVICENAME), TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP_getChipId(), SettingsText(SET_DEVICENAME),
ModuleName().c_str(), my_version, my_image); ModuleName().c_str(), my_version, my_image);
@ -719,7 +754,7 @@ void HAssPublishStatus(void)
"\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"" D_JSON_SIGNAL " (dBm)""\":\"%d\"," "\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"" D_JSON_SIGNAL " (dBm)""\":\"%d\","
"\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"LoadAvg\":%lu}"), "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"LoadAvg\":%lu}"),
my_version, my_image, GetBuildDateAndTime().c_str(), ModuleName().c_str(), GetResetReason().c_str(), my_version, my_image, GetBuildDateAndTime().c_str(), ModuleName().c_str(), GetResetReason().c_str(),
GetUptime().c_str(), NetworkHostname(), WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), GetUptime().c_str(), my_hostname, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()),
WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), loop_load_avg); WiFi.RSSI(), WifiLinkCount(), WifiDowntime().c_str(), MqttConnectCount(), loop_load_avg);
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE)); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE));
} }
@ -812,7 +847,6 @@ void HAssAnyKey(void)
bool Xdrv12(uint8_t function) bool Xdrv12(uint8_t function)
{ {
bool result = false; bool result = false;
if (Settings.flag.mqtt_enabled) if (Settings.flag.mqtt_enabled)
{ // SetOption3 - Enable MQTT { // SetOption3 - Enable MQTT
switch (function) switch (function)
@ -844,10 +878,13 @@ bool Xdrv12(uint8_t function)
case FUNC_MQTT_INIT: case FUNC_MQTT_INIT:
hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set
hass_init_step = 2; // Delayed discovery hass_init_step = 2; // Delayed discovery
// if (!Settings.flag.hass_discovery) {
// AddLog_P2(LOG_LEVEL_INFO, PSTR("MQT: homeassistant/49A3BC/Discovery = {\"dev\":{\"ids\":[\"49A3BC\"]},\"cmd_t\":\"cmnd/test1/\",\"Discovery\":0}"));
// }
break; break;
} }
} }
return result; return result;
} }
#endif // USE_HOME_ASSISTANT #endif // USE_HOME_ASSISTANT

View File

@ -19,6 +19,13 @@
#ifdef USE_ZIGBEE #ifdef USE_ZIGBEE
#if defined(USE_ZIGBEE_ZNP) && defined(USE_ZIGBEE_EZSP)
#error "#define USE_ZIGBEE_ZNP and #define USE_ZIGBEE_EZSP are mutually incompatible"
#endif
#if !defined(USE_ZIGBEE_ZNP) && !defined(USE_ZIGBEE_EZSP)
#error "You must select one of: #define USE_ZIGBEE_ZNP or #define USE_ZIGBEE_EZSP"
#endif
#define OCCUPANCY "Occupancy" // global define for Aqara #define OCCUPANCY "Occupancy" // global define for Aqara
typedef uint64_t Z_IEEEAddress; typedef uint64_t Z_IEEEAddress;
@ -26,6 +33,7 @@ typedef uint16_t Z_ShortAddress;
const uint16_t BAD_SHORTADDR = 0xFFFE; const uint16_t BAD_SHORTADDR = 0xFFFE;
#ifdef USE_ZIGBEE_ZNP
enum ZnpCommandType { enum ZnpCommandType {
Z_POLL = 0x00, Z_POLL = 0x00,
Z_SREQ = 0x20, Z_SREQ = 0x20,
@ -45,6 +53,7 @@ enum ZnpSubsystem {
Z_DEBUG = 0x08, Z_DEBUG = 0x08,
Z_APP = 0x09 Z_APP = 0x09
}; };
#endif // USE_ZIGBEE_ZNP
// Commands in the SYS subsystem // Commands in the SYS subsystem
enum SysCommand { enum SysCommand {

View File

@ -168,6 +168,8 @@ SBuffer *zigbee_buffer = nullptr;
#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL)) #define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL))
#ifdef USE_ZIGBEE_ZNP
// ZBS_* Zigbee Send // ZBS_* Zigbee Send
// ZBR_* Zigbee Recv // ZBR_* Zigbee Recv
ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) // 410001 SYS_RESET_REQ Hardware reset ZBM(ZBS_RESET, Z_AREQ | Z_SYS, SYS_RESET, 0x00 ) // 410001 SYS_RESET_REQ Hardware reset
@ -611,6 +613,30 @@ static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_STOP(ZIGBEE_LABEL_ABORT) ZI_STOP(ZIGBEE_LABEL_ABORT)
}; };
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
// Update the relevant commands with Settings
void Z_UpdateConfig(uint8_t zb_channel, uint16_t zb_pan_id, uint64_t zb_ext_panid, uint64_t zb_precfgkey_l, uint64_t zb_precfgkey_h) {
}
static const Zigbee_Instruction zb_prog[] PROGMEM = {
ZI_LABEL(0)
ZI_NOOP()
ZI_ON_ERROR_GOTO(ZIGBEE_LABEL_ABORT)
ZI_ON_TIMEOUT_GOTO(ZIGBEE_LABEL_ABORT)
// ZI_ON_RECV_UNEXPECTED(&Z_Recv_Default)
// ZI_WAIT(10500) // wait for 10 seconds for Tasmota to stabilize
ZI_LABEL(ZIGBEE_LABEL_MAIN_LOOP)
ZI_WAIT_FOREVER()
ZI_GOTO(ZIGBEE_LABEL_READY)
};
#endif // USE_ZIGBEE_EZSP
uint8_t ZigbeeGetInstructionSize(uint8_t instr) { // in Zigbee_Instruction lines (words) uint8_t ZigbeeGetInstructionSize(uint8_t instr) { // in Zigbee_Instruction lines (words)
if (instr >= ZGB_INSTR_12_BYTES) { if (instr >= ZGB_INSTR_12_BYTES) {
return 3; return 3;
@ -770,7 +796,9 @@ void ZigbeeStateMachine_Run(void) {
} }
break; break;
case ZGB_INSTR_SEND: case ZGB_INSTR_SEND:
#ifdef USE_ZIGBEE_ZNP
ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 /* len */); ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 /* len */);
#endif // USE_ZIGBEE_ZNP
break; break;
case ZGB_INSTR_WAIT_UNTIL: case ZGB_INSTR_WAIT_UNTIL:
zigbee.recv_until = true; // and reuse ZGB_INSTR_WAIT_RECV zigbee.recv_until = true; // and reuse ZGB_INSTR_WAIT_RECV

View File

@ -552,6 +552,7 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
return -1; return -1;
} }
#ifdef USE_ZIGBEE_ZNP
/*********************************************************************************************\ /*********************************************************************************************\
* Send specific ZNP messages * Send specific ZNP messages
\*********************************************************************************************/ \*********************************************************************************************/
@ -589,6 +590,32 @@ void Z_SendAFInfoRequest(uint16_t shortaddr) {
ZigbeeZNPSend(AFInfoReq, sizeof(AFInfoReq)); ZigbeeZNPSend(AFInfoReq, sizeof(AFInfoReq));
} }
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
/*********************************************************************************************\
* Send specific EZS¨ messages
\*********************************************************************************************/
//
// Send ZDO_IEEE_ADDR_REQ request to get IEEE long address
//
void Z_SendIEEEAddrReq(uint16_t shortaddr) {
}
//
// Send ACTIVE_EP_REQ to collect active endpoints for this address
//
void Z_SendActiveEpReq(uint16_t shortaddr) {
}
//
// Send AF Info Request
//
void Z_SendAFInfoRequest(uint16_t shortaddr) {
}
#endif // USE_ZIGBEE_EZSP
/*********************************************************************************************\ /*********************************************************************************************\
* Callbacks * Callbacks
@ -718,6 +745,8 @@ typedef struct Z_Dispatcher {
ZB_RecvMsgFunc func; ZB_RecvMsgFunc func;
} Z_Dispatcher; } Z_Dispatcher;
#ifdef USE_ZIGBEE_ZNP
// Ffilters based on ZNP frames // Ffilters based on ZNP frames
ZBM(AREQ_AF_DATA_CONFIRM, Z_AREQ | Z_AF, AF_DATA_CONFIRM) // 4480 ZBM(AREQ_AF_DATA_CONFIRM, Z_AREQ | Z_AF, AF_DATA_CONFIRM) // 4480
ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481 ZBM(AREQ_AF_INCOMING_MESSAGE, Z_AREQ | Z_AF, AF_INCOMING_MSG) // 4481
@ -767,6 +796,8 @@ int32_t Z_Recv_Default(int32_t res, const class SBuffer &buf) {
} }
} }
#endif // USE_ZIGBEE_ZNP
/*********************************************************************************************\ /*********************************************************************************************\
* Functions called by State Machine * Functions called by State Machine
\*********************************************************************************************/ \*********************************************************************************************/

View File

@ -21,18 +21,32 @@
#define XDRV_23 23 #define XDRV_23 23
#ifdef USE_ZIGBEE_ZNP
const uint32_t ZIGBEE_BUFFER_SIZE = 256; // Max ZNP frame is SOF+LEN+CMD1+CMD2+250+FCS = 255 const uint32_t ZIGBEE_BUFFER_SIZE = 256; // Max ZNP frame is SOF+LEN+CMD1+CMD2+250+FCS = 255
const uint8_t ZIGBEE_SOF = 0xFE; const uint8_t ZIGBEE_SOF = 0xFE;
const uint8_t ZIGBEE_SOF_ALT = 0xFF; const uint8_t ZIGBEE_SOF_ALT = 0xFF;
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
const uint32_t ZIGBEE_BUFFER_SIZE = 256;
const uint8_t ZIGBEE_EZSP_CANCEL = 0x1A; // cancel byte
const uint8_t ZIGBEE_EZSP_EOF = 0x7E; // end of frame
const uint8_t ZIGBEE_EZSP_ESCAPE = 0x7D; // escape byte
#endif // USE_ZIGBEE_EZSP
#include <TasmotaSerial.h> #include <TasmotaSerial.h>
TasmotaSerial *ZigbeeSerial = nullptr; TasmotaSerial *ZigbeeSerial = nullptr;
const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix
D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|" #ifdef USE_ZIGBEE_ZNP
D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEEZNPRECEIVE "|"
D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEEZNPRECEIVE "|" #endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
D_CMND_ZIGBEE_EZSP_SEND "|" D_CMND_ZIGBEE_EZSP_RECEIVE "|"
#endif // USE_ZIGBEE_EZSP
D_CMND_ZIGBEE_PERMITJOIN "|"
D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|" D_CMND_ZIGBEE_PROBE "|"
D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|" D_CMND_ZIGBEE_FORGET "|" D_CMND_ZIGBEE_SAVE "|" D_CMND_ZIGBEE_NAME "|"
D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|" D_CMND_ZIGBEE_BIND "|" D_CMND_ZIGBEE_UNBIND "|" D_CMND_ZIGBEE_PING "|" D_CMND_ZIGBEE_MODELID "|"
D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|" D_CMND_ZIGBEE_LIGHT "|" D_CMND_ZIGBEE_RESTORE "|" D_CMND_ZIGBEE_BIND_STATE "|"
@ -40,9 +54,14 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix
; ;
void (* const ZigbeeCommand[])(void) PROGMEM = { void (* const ZigbeeCommand[])(void) PROGMEM = {
&CmndZbZNPSend, &CmndZbPermitJoin, #ifdef USE_ZIGBEE_ZNP
&CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbZNPSend, &CmndZbZNPReceive,
&CmndZbProbe, &CmndZbZNPReceive, #endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
&CmndZbEZSPSend, &CmndZbEZSPReceive,
#endif // USE_ZIGBEE_EZSP
&CmndZbPermitJoin,
&CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe,
&CmndZbForget, &CmndZbSave, &CmndZbName, &CmndZbForget, &CmndZbSave, &CmndZbName,
&CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId, &CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId,
&CmndZbLight, &CmndZbRestore, &CmndZbBindState, &CmndZbLight, &CmndZbRestore, &CmndZbBindState,
@ -52,11 +71,12 @@ void (* const ZigbeeCommand[])(void) PROGMEM = {
// //
// Called at event loop, checks for incoming data from the CC2530 // Called at event loop, checks for incoming data from the CC2530
// //
void ZigbeeInputLoop(void) void ZigbeeInputLoop(void) {
{
static uint32_t zigbee_polling_window = 0; #ifdef USE_ZIGBEE_ZNP
static uint32_t zigbee_polling_window = 0; // number of milliseconds since first byte
static uint8_t fcs = ZIGBEE_SOF; static uint8_t fcs = ZIGBEE_SOF;
static uint32_t zigbee_frame_len = 5; // minimal zigbee frame lenght, will be updated when buf[1] is read static uint32_t zigbee_frame_len = 5; // minimal zigbee frame length, will be updated when buf[1] is read
// Receive only valid ZNP frames: // Receive only valid ZNP frames:
// 00 - SOF = 0xFE // 00 - SOF = 0xFE
// 01 - Length of Data Field - 0..250 // 01 - Length of Data Field - 0..250
@ -140,6 +160,127 @@ void ZigbeeInputLoop(void)
} }
zigbee_buffer->setLen(0); // empty buffer zigbee_buffer->setLen(0); // empty buffer
} }
#endif // USE_ZIGBEE_ZNP
#ifdef USE_ZIGBEE_EZSP
static uint32_t zigbee_polling_window = 0; // number of milliseconds since first byte
bool escape = false; // was the previous byte an escape?
bool frame_complete = false; // frame is ready and complete
// Receive only valid EZSP frames:
// 1A - Cancel - cancel all previous bytes
// 7D - Escape byte - following byte is escaped
// 7E - end of frame
while (ZigbeeSerial->available()) {
yield();
uint8_t zigbee_in_byte = ZigbeeSerial->read();
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: ZbInput byte=0x%02X len=%d"), zigbee_in_byte, zigbee_buffer->len());
// if (0 == zigbee_buffer->len()) { // make sure all variables are correctly initialized
// escape = false;
// frame_complete = false;
// }
if ((0x11 == zigbee_in_byte) || (0x13 == zigbee_in_byte)) {
continue; // ignore reserved bytes XON/XOFF
}
if (ZIGBEE_EZSP_ESCAPE == zigbee_in_byte) {
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: Escape byte received"));
escape = true;
continue;
}
if (ZIGBEE_EZSP_CANCEL == zigbee_in_byte) {
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZIG: ZbInput byte=0x1A, cancel byte received, discarding %d bytes"), zigbee_buffer->len());
zigbee_buffer->setLen(0); // empty buffer
escape = false;
frame_complete = false;
continue; // re-loop
}
if (ZIGBEE_EZSP_EOF == zigbee_in_byte) {
// end of frame
frame_complete = true;
break;
}
if (zigbee_buffer->len() < ZIGBEE_BUFFER_SIZE) {
if (escape) {
// invert bit 5
zigbee_in_byte ^= 0x20;
escape = false;
}
zigbee_buffer->add8(zigbee_in_byte);
zigbee_polling_window = millis(); // Wait for more data
} // adding bytes
} // while (ZigbeeSerial->available())
uint32_t frame_len = zigbee_buffer->len();
if (frame_complete || (frame_len && (millis() > (zigbee_polling_window + ZIGBEE_POLLING)))) {
char hex_char[frame_len * 2 + 2];
ToHex_P((unsigned char*)zigbee_buffer->getBuffer(), zigbee_buffer->len(), hex_char, sizeof(hex_char));
AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_ZIGBEE "Bytes follow_read_metric = %0d"), ZigbeeSerial->getLoopReadMetric());
if ((frame_complete) && (frame_len >= 3)) {
// frame received and has at least 3 bytes (without EOF), checking CRC
// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": received raw frame %s"), hex_char);
uint16_t crc = 0xFFFF; // frame CRC
// compute CRC
for (uint32_t i=0; i<frame_len-2; i++) {
crc = crc ^ ((uint16_t)zigbee_buffer->get8(i) << 8);
for (uint32_t i=0; i<8; i++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021; // polynom is x^16 + x^12 + x^5 + 1, CCITT standard
} else {
crc <<= 1;
}
}
}
uint16_t crc_received = zigbee_buffer->get8(frame_len - 2) << 8 | zigbee_buffer->get8(frame_len - 1);
// remove 2 last bytes
if (crc_received != crc) {
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": bad crc (received 0x%04X, computed 0x%04X) %s"), crc_received, crc, hex_char);
} else {
// copy buffer
SBuffer ezsp_buffer = zigbee_buffer->subBuffer(0, frame_len - 2); // CRC
// CRC is correct, apply de-stuffing if DATA frame
if (0 == (ezsp_buffer.get8(0) & 0x80)) {
// DATA frame
uint8_t rand = 0x42;
for (uint32_t i=1; i<ezsp_buffer.len(); i++) {
ezsp_buffer.set8(i, ezsp_buffer.get8(i) ^ rand);
if (rand & 1) { rand = (rand >> 1) ^ 0xB8; }
else { rand = (rand >> 1); }
}
}
ToHex_P((unsigned char*)ezsp_buffer.getBuffer(), ezsp_buffer.len(), hex_char, sizeof(hex_char));
Response_P(PSTR("{\"" D_JSON_ZIGBEE_EZSP_RECEIVED "\":\"%s\"}"), hex_char);
if (Settings.flag3.tuya_serial_mqtt_publish) {
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR));
XdrvRulesProcess();
} else {
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_ZIGBEE "%s"), mqtt_data); // TODO move to LOG_LEVEL_DEBUG when stable
}
// now process the message
ZigbeeProcessInput(ezsp_buffer);
}
} else {
// the buffer timed-out, print error and discard
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_JSON_ZIGBEE_EZSP_RECEIVED ": time-out, discarding %s, %d"), hex_char);
}
zigbee_buffer->setLen(0); // empty buffer
escape = false;
frame_complete = false;
}
#endif // USE_ZIGBEE_EZSP
} }
/********************************************************************************************/ /********************************************************************************************/
@ -201,15 +342,20 @@ uint32_t strToUInt(const JsonVariant &val) {
return 0; // couldn't parse anything return 0; // couldn't parse anything
} }
#ifdef USE_ZIGBEE_ZNP
// Do a factory reset of the CC2530 // Do a factory reset of the CC2530
const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM = const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM =
{ Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 /* len */, 0x01 /* STARTOPT_CLEAR_CONFIG */}; { Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 /* len */, 0x01 /* STARTOPT_CLEAR_CONFIG */};
//"2605030101"; // Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 len, 0x01 STARTOPT_CLEAR_CONFIG //"2605030101"; // Z_SREQ | Z_SAPI, SAPI_WRITE_CONFIGURATION, CONF_STARTUP_OPTION, 0x01 len, 0x01 STARTOPT_CLEAR_CONFIG
#endif // USE_ZIGBEE_ZNP
void CmndZbReset(void) { void CmndZbReset(void) {
if (ZigbeeSerial) { if (ZigbeeSerial) {
switch (XdrvMailbox.payload) { switch (XdrvMailbox.payload) {
case 1: case 1:
#ifdef USE_ZIGBEE_ZNP
ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET)); ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET));
#endif // USE_ZIGBEE_ZNP
eraseZigbeeDevices(); eraseZigbeeDevices();
restart_flag = 2; restart_flag = 2;
ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING)); ResponseCmndChar_P(PSTR(D_JSON_ZIGBEE_CC2530 " " D_JSON_RESET_AND_RESTARTING));
@ -220,6 +366,38 @@ void CmndZbReset(void) {
} }
} }
#ifdef USE_ZIGBEE_ZNP
void ZigbeeZNPSend(const uint8_t *msg, size_t len) {
if ((len < 2) || (len > 252)) {
// abort, message cannot be less than 2 bytes for CMD1 and CMD2
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len);
return;
}
uint8_t data_len = len - 2; // removing CMD1 and CMD2
if (ZigbeeSerial) {
uint8_t fcs = data_len;
ZigbeeSerial->write(ZIGBEE_SOF); // 0xFE
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend SOF %02X"), ZIGBEE_SOF);
ZigbeeSerial->write(data_len);
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend LEN %02X"), data_len);
for (uint32_t i = 0; i < len; i++) {
uint8_t b = pgm_read_byte(msg + i);
ZigbeeSerial->write(b);
fcs ^= b;
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend byt %02X"), b);
}
ZigbeeSerial->write(fcs); // finally send fcs checksum byte
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend FCS %02X"), fcs);
}
// Now send a MQTT message to report the sent message
char hex_char[(len * 2) + 2];
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"),
ToHex_P(msg, len, hex_char, sizeof(hex_char)));
}
// //
// Same code for `ZbZNPSend` and `ZbZNPReceive` // Same code for `ZbZNPSend` and `ZbZNPReceive`
// building the complete message (intro, length) // building the complete message (intro, length)
@ -264,36 +442,138 @@ void CmndZbZNPSend(void)
CmndZbZNPSendOrReceive(true); CmndZbZNPSendOrReceive(true);
} }
void ZigbeeZNPSend(const uint8_t *msg, size_t len) { #endif // USE_ZIGBEE_ZNP
if ((len < 2) || (len > 252)) {
#ifdef USE_ZIGBEE_EZSP
// internal function to output a byte, and escape it (stuffing) if needed
void ZigbeeEZSPSend_Out(uint8_t out_byte) {
switch (out_byte) {
case 0x7E: // Flag byte
case 0x11: // XON
case 0x13: // XOFF
case 0x18: // Substitute byte
case 0x1A: // Cancel byte
case 0x7D: // Escape byte
ZigbeeSerial->write(ZIGBEE_EZSP_ESCAPE); // send Escape byte 0x7D
ZigbeeSerial->write(out_byte ^ 0x20); // send with bit 5 inverted
break;
default:
ZigbeeSerial->write(out_byte); // send unchanged
break;
}
}
// Send low-level EZSP frames
//
// The frame should contain the Control Byte and Data Field
// The frame shouldn't be escaped, nor randomized
//
// Before sending:
// - send Cancel byte (0x1A) if requested
// - randomize Data Field if DATA Frame
// - compute CRC16
// - escape (stuff) reserved bytes
// - add EOF (0x7E)
// - send frame
// send_cancel: should we first send a EZSP_CANCEL (0x1A) before the message to clear any leftover
void ZigbeeEZSPSend(const uint8_t *msg, size_t len, bool send_cancel = false) {
if ((len < 1) || (len > 252)) {
// abort, message cannot be less than 2 bytes for CMD1 and CMD2 // abort, message cannot be less than 2 bytes for CMD1 and CMD2
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEEZNPSENT ": bad message len %d"), len); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_JSON_ZIGBEE_EZSP_SENT ": bad message len %d"), len);
return; return;
} }
uint8_t data_len = len - 2; // removing CMD1 and CMD2 uint8_t data_len = len - 2; // removing CMD1 and CMD2
if (ZigbeeSerial) { if (ZigbeeSerial) {
uint8_t fcs = data_len; if (send_cancel) {
ZigbeeSerial->write(ZIGBEE_EZSP_CANCEL); // 0x1A
}
ZigbeeSerial->write(ZIGBEE_SOF); // 0xFE bool data_frame = (0 == (msg[0] & 0x80));
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend SOF %02X"), ZIGBEE_SOF); uint8_t rand = 0x42; // pseudo-randomizer initial value
ZigbeeSerial->write(data_len); uint16_t crc = 0xFFFF; // CRC16 CCITT initialization
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend LEN %02X"), data_len);
for (uint32_t i = 0; i < len; i++) { for (uint32_t i=0; i<len; i++) {
uint8_t b = pgm_read_byte(msg + i); uint8_t out_byte = msg[i];
ZigbeeSerial->write(b);
fcs ^= b; // apply randomization if DATA field
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend byt %02X"), b); if (data_frame && (i > 0)) {
} out_byte ^= rand;
ZigbeeSerial->write(fcs); // finally send fcs checksum byte if (rand & 1) { rand = (rand >> 1) ^ 0xB8; }
//AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("ZNPSend FCS %02X"), fcs); else { rand = (rand >> 1); }
}
// compute CRC
crc = crc ^ ((uint16_t)out_byte << 8);
for (uint32_t i=0; i<8; i++) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021; // polynom is x^16 + x^12 + x^5 + 1, CCITT standard
} else {
crc <<= 1;
}
}
// output byte
ZigbeeEZSPSend_Out(out_byte);
}
// send CRC16 in big-endian
ZigbeeEZSPSend_Out(crc >> 8);
ZigbeeEZSPSend_Out(crc & 0xFF);
// finally send End of Frame
ZigbeeSerial->write(ZIGBEE_EZSP_EOF); // 0x1A
} }
// Now send a MQTT message to report the sent message // Now send a MQTT message to report the sent message
char hex_char[(len * 2) + 2]; char hex_char[(len * 2) + 2];
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEEZNPSENT " %s"), AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_ZIGBEE D_JSON_ZIGBEE_EZSP_SENT " %s"),
ToHex_P(msg, len, hex_char, sizeof(hex_char))); ToHex_P(msg, len, hex_char, sizeof(hex_char)));
} }
//
// Same code for `ZbZNPSend` and `ZbZNPReceive`
// building the complete message (intro, length)
//
void CmndZbEZSPSendOrReceive(bool send)
{
if (ZigbeeSerial && (XdrvMailbox.data_len > 0)) {
uint8_t code;
char *codes = RemoveSpace(XdrvMailbox.data);
int32_t size = strlen(XdrvMailbox.data);
SBuffer buf((size+1)/2);
while (size > 1) {
char stemp[3];
strlcpy(stemp, codes, sizeof(stemp));
code = strtol(stemp, nullptr, 16);
buf.add8(code);
size -= 2;
codes += 2;
}
if (send) {
// Command was `ZbEZSPSend`
ZigbeeEZSPSend(buf.getBuffer(), buf.len());
} else {
// Command was `ZbEZSPReceive`
ZigbeeProcessInput(buf);
}
}
ResponseCmndDone();
}
// For debug purposes only, simulates a message received
void CmndZbEZSPReceive(void)
{
CmndZbEZSPSendOrReceive(false);
}
void CmndZbEZSPSend(void)
{
CmndZbEZSPSendOrReceive(true);
}
#endif // USE_ZIGBEE_EZSP
// //
// Internal function, send the low-level frame // Internal function, send the low-level frame
// Input: // Input:
@ -311,6 +591,7 @@ void ZigbeeZNPSend(const uint8_t *msg, size_t len) {
// //
void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, uint16_t manuf, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) { void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterId, uint8_t endpoint, uint8_t cmdId, bool clusterSpecific, uint16_t manuf, const uint8_t *msg, size_t len, bool needResponse, uint8_t transacId) {
#ifdef USE_ZIGBEE_ZNP
SBuffer buf(32+len); SBuffer buf(32+len);
buf.add8(Z_SREQ | Z_AF); // 24 buf.add8(Z_SREQ | Z_AF); // 24
buf.add8(AF_DATA_REQUEST_EXT); // 02 buf.add8(AF_DATA_REQUEST_EXT); // 02
@ -342,6 +623,7 @@ void ZigbeeZCLSend_Raw(uint16_t shortaddr, uint16_t groupaddr, uint16_t clusterI
} }
ZigbeeZNPSend(buf.getBuffer(), buf.len()); ZigbeeZNPSend(buf.getBuffer(), buf.len());
#endif // USE_ZIGBEE_ZNP
} }
/********************************************************************************************/ /********************************************************************************************/
@ -914,6 +1196,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
if (&to_group && dstLongAddr) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; } if (&to_group && dstLongAddr) { ResponseCmndChar_P(PSTR("Cannot have both \"ToDevice\" and \"ToGroup\"")); return; }
if (!&to_group && !dstLongAddr) { ResponseCmndChar_P(PSTR("Missing \"ToDevice\" or \"ToGroup\"")); return; } if (!&to_group && !dstLongAddr) { ResponseCmndChar_P(PSTR("Missing \"ToDevice\" or \"ToGroup\"")); return; }
#ifdef USE_ZIGBEE_ZNP
SBuffer buf(34); SBuffer buf(34);
buf.add8(Z_SREQ | Z_ZDO); buf.add8(Z_SREQ | Z_ZDO);
if (unbind) { if (unbind) {
@ -935,6 +1218,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
} }
ZigbeeZNPSend(buf.getBuffer(), buf.len()); ZigbeeZNPSend(buf.getBuffer(), buf.len());
#endif // USE_ZIGBEE_ZNP
ResponseCmndDone(); ResponseCmndDone();
} }
@ -961,6 +1245,7 @@ void CmndZbBindState(void) {
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data); uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; } if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
#ifdef USE_ZIGBEE_ZNP
SBuffer buf(10); SBuffer buf(10);
buf.add8(Z_SREQ | Z_ZDO); // 25 buf.add8(Z_SREQ | Z_ZDO); // 25
buf.add8(ZDO_MGMT_BIND_REQ); // 33 buf.add8(ZDO_MGMT_BIND_REQ); // 33
@ -968,6 +1253,7 @@ void CmndZbBindState(void) {
buf.add8(0); // StartIndex = 0 buf.add8(0); // StartIndex = 0
ZigbeeZNPSend(buf.getBuffer(), buf.len()); ZigbeeZNPSend(buf.getBuffer(), buf.len());
#endif // USE_ZIGBEE_ZNP
ResponseCmndDone(); ResponseCmndDone();
} }
@ -1191,6 +1477,7 @@ void CmndZbPermitJoin(void) {
duration = 0xFF; // unlimited time duration = 0xFF; // unlimited time
} }
#ifdef USE_ZIGBEE_ZNP
SBuffer buf(34); SBuffer buf(34);
buf.add8(Z_SREQ | Z_ZDO); // 25 buf.add8(Z_SREQ | Z_ZDO); // 25
buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); // 36 buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); // 36
@ -1200,6 +1487,7 @@ void CmndZbPermitJoin(void) {
buf.add8(0x00); // TCSignificance buf.add8(0x00); // TCSignificance
ZigbeeZNPSend(buf.getBuffer(), buf.len()); ZigbeeZNPSend(buf.getBuffer(), buf.len());
#endif // USE_ZIGBEE_ZNP
ResponseCmndDone(); ResponseCmndDone();
} }

View File

@ -0,0 +1,585 @@
/*
xdrv_31_tasmota_client.ino - Support for external microcontroller on serial
Copyright (C) 2020 Andre Thomas and Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_TASMOTA_CLIENT
/*********************************************************************************************\
* Tasmota to microcontroller
\*********************************************************************************************/
#define XDRV_31 31
#define CONST_STK_CRC_EOP 0x20
#define CMND_STK_GET_SYNC 0x30
#define CMND_STK_SET_DEVICE 0x42
#define CMND_STK_SET_DEVICE_EXT 0x45
#define CMND_STK_ENTER_PROGMODE 0x50
#define CMND_STK_LEAVE_PROGMODE 0x51
#define CMND_STK_LOAD_ADDRESS 0x55
#define CMND_STK_PROG_PAGE 0x64
/*************************************************\
* Tasmota Client Specific Commands
\*************************************************/
#define CMND_START 0xFC
#define CMND_END 0xFD
#define CMND_FEATURES 0x01
#define CMND_JSON 0x02
#define CMND_FUNC_EVERY_SECOND 0x03
#define CMND_FUNC_EVERY_100_MSECOND 0x04
#define CMND_CLIENT_SEND 0x05
#define CMND_PUBLISH_TELE 0x06
#define CMND_EXECUTE_CMND 0x07
#define PARAM_DATA_START 0xFE
#define PARAM_DATA_END 0xFF
#include <TasmotaSerial.h>
/*
* Embedding class in here since its rather specific to Arduino bootloader
*/
class SimpleHexParse {
public:
SimpleHexParse(void);
uint8_t parseLine(char *hexline);
uint8_t ptr_l = 0;
uint8_t ptr_h = 0;
bool PageIsReady = false;
bool firstrun = true;
bool EndOfFile = false;
uint8_t FlashPage[128];
uint8_t FlashPageIdx = 0;
uint8_t layoverBuffer[16];
uint8_t layoverIdx = 0;
uint8_t getByte(char *hexline, uint8_t idx);
};
SimpleHexParse::SimpleHexParse(void) {
}
uint8_t SimpleHexParse::parseLine(char *hexline) {
if (layoverIdx) {
memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx);
FlashPageIdx = layoverIdx;
layoverIdx = 0;
}
uint8_t len = getByte(hexline, 1);
uint8_t addr_h = getByte(hexline, 2);
uint8_t addr_l = getByte(hexline, 3);
uint8_t rectype = getByte(hexline, 4);
for (uint8_t idx = 0; idx < len; idx++) {
if (FlashPageIdx < 128) {
FlashPage[FlashPageIdx] = getByte(hexline, idx+5);
FlashPageIdx++;
} else { // We have layover bytes
layoverBuffer[layoverIdx] = getByte(hexline, idx+5);
layoverIdx++;
}
}
if (1 == rectype) {
EndOfFile = true;
while (FlashPageIdx < 128) {
FlashPage[FlashPageIdx] = 0xFF;
FlashPageIdx++;
}
}
if (FlashPageIdx == 128) {
if (firstrun) {
firstrun = false;
} else {
ptr_l += 0x40;
if (ptr_l == 0) {
ptr_l = 0;
ptr_h++;
}
}
firstrun = false;
PageIsReady = true;
}
return 0;
}
uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx) {
char buff[3];
buff[3] = '\0';
memcpy(&buff, &hexline[(idx*2)-1], 2);
return strtol(buff, 0, 16);
}
/*
* End of embedded class SimpleHexParse
*/
struct TCLIENT {
uint32_t spi_hex_size = 0;
uint32_t spi_sector_counter = 0;
uint8_t spi_sector_cursor = 0;
uint8_t inverted = LOW;
bool type = false;
bool flashing = false;
bool SerialEnabled = false;
uint8_t waitstate = 0; // We use this so that features detection does not slow down other stuff on startup
bool unsupported = false;
} TClient;
typedef union {
uint32_t data;
struct {
uint32_t func_json_append : 1; // Client supports providing a JSON for TELEPERIOD
uint32_t func_every_second : 1; // Client supports receiving a FUNC_EVERY_SECOND callback with no response
uint32_t func_every_100_msecond : 1; // Client supports receiving a FUNC_EVERY_100_MSECOND callback with no response
uint32_t func_client_send : 1; // Client supports receiving commands with "client send xxx"
uint32_t spare4 : 1;
uint32_t spare5 : 1;
uint32_t spare6 : 1;
uint32_t spare7 : 1;
uint32_t spare8 : 1;
uint32_t spare9 : 1;
uint32_t spare10 : 1;
uint32_t spare11 : 1;
uint32_t spare12 : 1;
uint32_t spare13 : 1;
uint32_t spare14 : 1;
uint32_t spare15 : 1;
uint32_t spare16 : 1;
uint32_t spare17 : 1;
uint32_t spare18 : 1;
uint32_t spare19 : 1;
uint32_t spare20 : 1;
uint32_t spare21 : 1;
uint32_t spare22 : 1;
uint32_t spare23 : 1;
uint32_t spare24 : 1;
uint32_t spare25 : 1;
uint32_t spare26 : 1;
uint32_t spare27 : 1;
uint32_t spare28 : 1;
uint32_t spare29 : 1;
uint32_t spare30 : 1;
uint32_t spare31 : 1;
};
} TClientFeatureCfg;
/*
* The structure below must remain 4 byte aligned to be compatible with
* Tasmota as master
*/
struct TCLIENT_FEATURES {
uint32_t features_version;
TClientFeatureCfg features;
} TClientSettings;
struct TCLIENT_COMMAND {
uint8_t command;
uint8_t parameter;
uint8_t unused2;
uint8_t unused3;
} TClientCommand;
TasmotaSerial *TasmotaClient_Serial;
uint32_t TasmotaClient_FlashStart(void) {
return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side
}
uint8_t TasmotaClient_UpdateInit(void) {
TClient.spi_hex_size = 0;
TClient.spi_sector_counter = TasmotaClient_FlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored
TClient.spi_sector_cursor = 0;
return 0;
}
void TasmotaClient_Reset(void) {
if (TClient.SerialEnabled) {
digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), !TClient.inverted);
delay(1);
digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), TClient.inverted);
delay(1);
digitalWrite(Pin(GPIO_TASMOTACLIENT_RST), !TClient.inverted);
delay(5);
}
}
uint8_t TasmotaClient_waitForSerialData(int dataCount, int timeout) {
int timer = 0;
while (timer < timeout) {
if (TasmotaClient_Serial->available() >= dataCount) {
return 1;
}
delay(1);
timer++;
}
return 0;
}
uint8_t TasmotaClient_sendBytes(uint8_t* bytes, int count) {
TasmotaClient_Serial->write(bytes, count);
TasmotaClient_waitForSerialData(2, 250);
uint8_t sync = TasmotaClient_Serial->read();
uint8_t ok = TasmotaClient_Serial->read();
if ((sync == 0x14) && (ok == 0x10)) {
return 1;
}
return 0;
}
uint8_t TasmotaClient_execCmd(uint8_t cmd) {
uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP };
return TasmotaClient_sendBytes(bytes, 2);
}
uint8_t TasmotaClient_execParam(uint8_t cmd, uint8_t* params, int count) {
uint8_t bytes[32];
bytes[0] = cmd;
int i = 0;
while (i < count) {
bytes[i + 1] = params[i];
i++;
}
bytes[i + 1] = CONST_STK_CRC_EOP;
return TasmotaClient_sendBytes(bytes, i + 2);
}
uint8_t TasmotaClient_exitProgMode(void) {
return TasmotaClient_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode
}
uint8_t TasmotaClient_SetupFlash(void) {
uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00};
uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00};
TasmotaClient_Serial->begin(USE_TASMOTA_CLIENT_FLASH_SPEED);
if (TasmotaClient_Serial->hardwareSerial()) {
ClaimSerial();
}
TasmotaClient_Reset();
uint8_t timeout = 0;
uint8_t no_error = 0;
while (50 > timeout) {
if (TasmotaClient_execCmd(CMND_STK_GET_SYNC)) {
timeout = 200;
no_error = 1;
}
timeout++;
delay(1);
}
if (no_error) {
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Found bootloader"));
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Bootloader could not be found"));
}
if (no_error) {
if (TasmotaClient_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) {
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Could not configure device for programming (1)"));
}
}
if (no_error) {
if (TasmotaClient_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) {
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Could not configure device for programming (2)"));
}
}
if (no_error) {
if (TasmotaClient_execCmd(CMND_STK_ENTER_PROGMODE)) {
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Failed to put bootloader into programming mode"));
}
}
return no_error;
}
uint8_t TasmotaClient_loadAddress(uint8_t adrHi, uint8_t adrLo) {
uint8_t params[] = { adrLo, adrHi };
return TasmotaClient_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params));
}
void TasmotaClient_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data) {
uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46};
TasmotaClient_loadAddress(addr_h, addr_l);
TasmotaClient_Serial->write(Header, 4);
for (int i = 0; i < 128; i++) {
TasmotaClient_Serial->write(data[i]);
}
TasmotaClient_Serial->write(CONST_STK_CRC_EOP);
TasmotaClient_waitForSerialData(2, 250);
TasmotaClient_Serial->read();
TasmotaClient_Serial->read();
}
void TasmotaClient_Flash(void) {
bool reading = true;
uint32_t read = 0;
uint32_t processed = 0;
char thishexline[50];
uint8_t position = 0;
char* flash_buffer;
SimpleHexParse hexParse = SimpleHexParse();
if (!TasmotaClient_SetupFlash()) {
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flashing aborted!"));
TClient.flashing = false;
restart_flag = 2;
return;
}
flash_buffer = new char[SPI_FLASH_SEC_SIZE];
uint32_t flash_start = TasmotaClient_FlashStart() * SPI_FLASH_SEC_SIZE;
while (reading) {
ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE);
read = read + SPI_FLASH_SEC_SIZE;
if (read >= TClient.spi_hex_size) {
reading = false;
}
for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) {
processed++;
if ((processed <= TClient.spi_hex_size) && (!hexParse.EndOfFile)) {
if (':' == flash_buffer[ca]) {
position = 0;
}
if (0x0D == flash_buffer[ca]) {
thishexline[position] = 0;
hexParse.parseLine(thishexline);
if (hexParse.PageIsReady) {
TasmotaClient_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage);
hexParse.PageIsReady = false;
hexParse.FlashPageIdx = 0;
}
} else {
if (0x0A != flash_buffer[ca]) {
thishexline[position] = flash_buffer[ca];
position++;
}
}
}
}
}
TasmotaClient_exitProgMode();
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Flash done!"));
TClient.flashing = false;
restart_flag = 2;
}
void TasmotaClient_SetFlagFlashing(bool value) {
TClient.flashing = value;
}
bool TasmotaClient_GetFlagFlashing(void) {
return TClient.flashing;
}
void TasmotaClient_WriteBuffer(uint8_t *buf, size_t size) {
if (0 == TClient.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
ESP.flashEraseSector(TClient.spi_sector_counter);
}
TClient.spi_sector_cursor++;
ESP.flashWrite((TClient.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TClient.spi_sector_cursor-1)*2048), (uint32_t*)buf, size);
TClient.spi_hex_size = TClient.spi_hex_size + size;
if (2 == TClient.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase
TClient.spi_sector_cursor = 0;
TClient.spi_sector_counter++;
}
}
void TasmotaClient_Init(void) {
if (TClient.type) {
return;
}
if (10 > TClient.waitstate) {
TClient.waitstate++;
return;
}
if (!TClient.SerialEnabled) {
if (PinUsed(GPIO_TASMOTACLIENT_RXD) && PinUsed(GPIO_TASMOTACLIENT_TXD) &&
(PinUsed(GPIO_TASMOTACLIENT_RST) || PinUsed(GPIO_TASMOTACLIENT_RST_INV))) {
TasmotaClient_Serial = new TasmotaSerial(Pin(GPIO_TASMOTACLIENT_RXD), Pin(GPIO_TASMOTACLIENT_TXD), 1, 0, 200);
if (TasmotaClient_Serial->begin(USE_TASMOTA_CLIENT_SERIAL_SPEED)) {
if (TasmotaClient_Serial->hardwareSerial()) {
ClaimSerial();
}
TasmotaClient_Serial->setTimeout(100); // Theo 20200502 - increase from 50
if (PinUsed(GPIO_TASMOTACLIENT_RST_INV)) {
SetPin(Pin(GPIO_TASMOTACLIENT_RST_INV), GPIO_TASMOTACLIENT_RST);
TClient.inverted = HIGH;
}
pinMode(Pin(GPIO_TASMOTACLIENT_RST), OUTPUT);
TClient.SerialEnabled = true;
TasmotaClient_Reset();
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Enabled"));
}
}
}
if (TClient.SerialEnabled) { // All go for hardware now we need to detect features if there are any
TasmotaClient_sendCmnd(CMND_FEATURES, 0);
char buffer[32] = { 0 };
TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer));
uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer));
if (len) { AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, len); } // Theo 20200502 - DMP: 99 17 34 01 02 00 00 00
memcpy(&TClientSettings, &buffer, sizeof(TClientSettings));
if (20191129 == TClientSettings.features_version) {
TClient.type = true;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Version %u"), TClientSettings.features_version);
} else {
if ((!TClient.unsupported) && (TClientSettings.features_version > 0)) {
AddLog_P2(LOG_LEVEL_INFO, PSTR("TCL: Version %u not supported!"), TClientSettings.features_version);
TClient.unsupported = true;
}
}
}
}
void TasmotaClient_Show(void) {
if ((TClient.type) && (TClientSettings.features.func_json_append)) {
char buffer[100];
TasmotaClient_sendCmnd(CMND_JSON, 0);
TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1);
uint8_t len = TasmotaClient_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1);
buffer[len] = '\0';
ResponseAppend_P(PSTR(",\"TasmotaClient\":%s"), buffer);
}
}
void TasmotaClient_sendCmnd(uint8_t cmnd, uint8_t param) {
TClientCommand.command = cmnd;
TClientCommand.parameter = param;
char buffer[sizeof(TClientCommand)+2];
buffer[0] = CMND_START;
memcpy(&buffer[1], &TClientCommand, sizeof(TClientCommand));
buffer[sizeof(TClientCommand)+1] = CMND_END;
TasmotaClient_Serial->flush(); // Theo 20200502
for (uint8_t ca = 0; ca < sizeof(buffer); ca++) {
TasmotaClient_Serial->write(buffer[ca]);
}
}
#define D_PRFX_CLIENT "Client"
#define D_CMND_CLIENT_RESET "Reset"
#define D_CMND_CLIENT_SEND "Send"
const char kTasmotaClientCommands[] PROGMEM = D_PRFX_CLIENT "|"
D_CMND_CLIENT_RESET "|" D_CMND_CLIENT_SEND;
void (* const TasmotaClientCommand[])(void) PROGMEM = {
&CmndClientReset, &CmndClientSend };
void CmndClientReset(void) {
TasmotaClient_Reset();
TClient.type = false; // Force redetection
TClient.waitstate = 7; // give it at least 3 seconds to restart from bootloader
TClient.unsupported = false; // Reset unsupported flag
ResponseCmndDone();
}
void CmndClientSend(void) {
if (0 < XdrvMailbox.data_len) {
TasmotaClient_sendCmnd(CMND_CLIENT_SEND, XdrvMailbox.data_len);
TasmotaClient_Serial->write(char(PARAM_DATA_START));
for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) {
TasmotaClient_Serial->write(XdrvMailbox.data[idx]);
}
TasmotaClient_Serial->write(char(PARAM_DATA_END));
}
ResponseCmndDone();
}
void TasmotaClient_ProcessIn(void) {
uint8_t cmnd = TasmotaClient_Serial->read();
if (CMND_START == cmnd) {
TasmotaClient_waitForSerialData(sizeof(TClientCommand),50);
uint8_t buffer[sizeof(TClientCommand)];
for (uint8_t idx = 0; idx < sizeof(TClientCommand); idx++) {
buffer[idx] = TasmotaClient_Serial->read();
}
TasmotaClient_Serial->read(); // read trailing byte of command
memcpy(&TClientCommand, &buffer, sizeof(TClientCommand));
char inbuf[TClientCommand.parameter+1];
TasmotaClient_waitForSerialData(TClientCommand.parameter, 50);
TasmotaClient_Serial->read(); // Read leading byte
for (uint8_t idx = 0; idx < TClientCommand.parameter; idx++) {
inbuf[idx] = TasmotaClient_Serial->read();
}
TasmotaClient_Serial->read(); // Read trailing byte
inbuf[TClientCommand.parameter] = '\0';
if (CMND_PUBLISH_TELE == TClientCommand.command) { // We need to publish stat/ with incoming stream as content
Response_P(PSTR("{\"TasmotaClient\":"));
ResponseAppend_P("%s", inbuf);
ResponseJsonEnd();
MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data);
XdrvRulesProcess();
}
if (CMND_EXECUTE_CMND == TClientCommand.command) { // We need to execute the incoming command
ExecuteCommand(inbuf, SRC_IGNORE);
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv31(uint8_t function) {
bool result = false;
switch (function) {
case FUNC_EVERY_100_MSECOND:
if (TClient.type) {
if (TasmotaClient_Serial->available()) {
TasmotaClient_ProcessIn();
}
if (TClientSettings.features.func_every_100_msecond) {
TasmotaClient_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0);
}
}
break;
case FUNC_EVERY_SECOND:
if ((TClient.type) && (TClientSettings.features.func_every_second)) {
TasmotaClient_sendCmnd(CMND_FUNC_EVERY_SECOND, 0);
}
TasmotaClient_Init();
break;
case FUNC_JSON_APPEND:
if ((TClient.type) && (TClientSettings.features.func_json_append)) {
TasmotaClient_Show();
}
break;
case FUNC_COMMAND:
result = DecodeCommand(kTasmotaClientCommands, TasmotaClientCommand);
break;
}
return result;
}
#endif // USE_TASMOTA_CLIENT

View File

@ -1,615 +0,0 @@
/*
xdrv_31_tasmota_slave.ino - Support for external microcontroller slave on serial
Copyright (C) 2020 Andre Thomas and Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_TASMOTA_SLAVE
/*********************************************************************************************\
* Tasmota slave
\*********************************************************************************************/
#define XDRV_31 31
#define CONST_STK_CRC_EOP 0x20
#define CMND_STK_GET_SYNC 0x30
#define CMND_STK_SET_DEVICE 0x42
#define CMND_STK_SET_DEVICE_EXT 0x45
#define CMND_STK_ENTER_PROGMODE 0x50
#define CMND_STK_LEAVE_PROGMODE 0x51
#define CMND_STK_LOAD_ADDRESS 0x55
#define CMND_STK_PROG_PAGE 0x64
/*************************************************\
* Tasmota Slave Specific Commands
\*************************************************/
#define CMND_START 0xFC
#define CMND_END 0xFD
#define CMND_FEATURES 0x01
#define CMND_JSON 0x02
#define CMND_FUNC_EVERY_SECOND 0x03
#define CMND_FUNC_EVERY_100_MSECOND 0x04
#define CMND_SLAVE_SEND 0x05
#define CMND_PUBLISH_TELE 0x06
#define CMND_EXECUTE_CMND 0x07
#define PARAM_DATA_START 0xFE
#define PARAM_DATA_END 0xFF
#include <TasmotaSerial.h>
/*
* Embedding class in here since its rather specific to Arduino bootloader
*/
class SimpleHexParse {
public:
SimpleHexParse(void);
uint8_t parseLine(char *hexline);
uint8_t ptr_l = 0;
uint8_t ptr_h = 0;
bool PageIsReady = false;
bool firstrun = true;
bool EndOfFile = false;
uint8_t FlashPage[128];
uint8_t FlashPageIdx = 0;
uint8_t layoverBuffer[16];
uint8_t layoverIdx = 0;
uint8_t getByte(char *hexline, uint8_t idx);
};
SimpleHexParse::SimpleHexParse(void)
{
}
uint8_t SimpleHexParse::parseLine(char *hexline)
{
if (layoverIdx) {
memcpy(&FlashPage[0], &layoverBuffer[0], layoverIdx);
FlashPageIdx = layoverIdx;
layoverIdx = 0;
}
uint8_t len = getByte(hexline, 1);
uint8_t addr_h = getByte(hexline, 2);
uint8_t addr_l = getByte(hexline, 3);
uint8_t rectype = getByte(hexline, 4);
for (uint8_t idx = 0; idx < len; idx++) {
if (FlashPageIdx < 128) {
FlashPage[FlashPageIdx] = getByte(hexline, idx+5);
FlashPageIdx++;
} else { // We have layover bytes
layoverBuffer[layoverIdx] = getByte(hexline, idx+5);
layoverIdx++;
}
}
if (1 == rectype) {
EndOfFile = true;
while (FlashPageIdx < 128) {
FlashPage[FlashPageIdx] = 0xFF;
FlashPageIdx++;
}
}
if (FlashPageIdx == 128) {
if (firstrun) {
firstrun = false;
} else {
ptr_l += 0x40;
if (ptr_l == 0) {
ptr_l = 0;
ptr_h++;
}
}
firstrun = false;
PageIsReady = true;
}
return 0;
}
uint8_t SimpleHexParse::getByte(char* hexline, uint8_t idx)
{
char buff[3];
buff[3] = '\0';
memcpy(&buff, &hexline[(idx*2)-1], 2);
return strtol(buff, 0, 16);
}
/*
* End of embedded class SimpleHexParse
*/
struct TSLAVE {
uint32_t spi_hex_size = 0;
uint32_t spi_sector_counter = 0;
uint8_t spi_sector_cursor = 0;
uint8_t inverted = LOW;
bool type = false;
bool flashing = false;
bool SerialEnabled = false;
uint8_t waitstate = 0; // We use this so that features detection does not slow down other stuff on startup
bool unsupported = false;
} TSlave;
typedef union {
uint32_t data;
struct {
uint32_t func_json_append : 1; // Slave supports providing a JSON for TELEPERIOD
uint32_t func_every_second : 1; // Slave supports receiving a FUNC_EVERY_SECOND callback with no response
uint32_t func_every_100_msecond : 1; // Slave supports receiving a FUNC_EVERY_100_MSECOND callback with no response
uint32_t func_slave_send : 1; // Slave supports receiving commands with "slave send xxx"
uint32_t spare4 : 1;
uint32_t spare5 : 1;
uint32_t spare6 : 1;
uint32_t spare7 : 1;
uint32_t spare8 : 1;
uint32_t spare9 : 1;
uint32_t spare10 : 1;
uint32_t spare11 : 1;
uint32_t spare12 : 1;
uint32_t spare13 : 1;
uint32_t spare14 : 1;
uint32_t spare15 : 1;
uint32_t spare16 : 1;
uint32_t spare17 : 1;
uint32_t spare18 : 1;
uint32_t spare19 : 1;
uint32_t spare20 : 1;
uint32_t spare21 : 1;
uint32_t spare22 : 1;
uint32_t spare23 : 1;
uint32_t spare24 : 1;
uint32_t spare25 : 1;
uint32_t spare26 : 1;
uint32_t spare27 : 1;
uint32_t spare28 : 1;
uint32_t spare29 : 1;
uint32_t spare30 : 1;
uint32_t spare31 : 1;
};
} TSlaveFeatureCfg;
/*
* The structure below must remain 4 byte aligned to be compatible with
* Tasmota as master
*/
struct TSLAVE_FEATURES {
uint32_t features_version;
TSlaveFeatureCfg features;
} TSlaveSettings;
struct TSLAVE_COMMAND {
uint8_t command;
uint8_t parameter;
uint8_t unused2;
uint8_t unused3;
} TSlaveCommand;
TasmotaSerial *TasmotaSlave_Serial;
uint32_t TasmotaSlave_FlashStart(void)
{
return (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 2; // Stay on the safe side
}
uint8_t TasmotaSlave_UpdateInit(void)
{
TSlave.spi_hex_size = 0;
TSlave.spi_sector_counter = TasmotaSlave_FlashStart(); // Reset the pre-defined write address where firmware will temporarily be stored
TSlave.spi_sector_cursor = 0;
return 0;
}
void TasmotaSlave_Reset(void)
{
if (TSlave.SerialEnabled) {
digitalWrite(Pin(GPIO_TASMOTASLAVE_RST), !TSlave.inverted);
delay(1);
digitalWrite(Pin(GPIO_TASMOTASLAVE_RST), TSlave.inverted);
delay(1);
digitalWrite(Pin(GPIO_TASMOTASLAVE_RST), !TSlave.inverted);
delay(5);
}
}
uint8_t TasmotaSlave_waitForSerialData(int dataCount, int timeout)
{
int timer = 0;
while (timer < timeout) {
if (TasmotaSlave_Serial->available() >= dataCount) {
return 1;
}
delay(1);
timer++;
}
return 0;
}
uint8_t TasmotaSlave_sendBytes(uint8_t* bytes, int count)
{
TasmotaSlave_Serial->write(bytes, count);
TasmotaSlave_waitForSerialData(2, 250);
uint8_t sync = TasmotaSlave_Serial->read();
uint8_t ok = TasmotaSlave_Serial->read();
if ((sync == 0x14) && (ok == 0x10)) {
return 1;
}
return 0;
}
uint8_t TasmotaSlave_execCmd(uint8_t cmd)
{
uint8_t bytes[] = { cmd, CONST_STK_CRC_EOP };
return TasmotaSlave_sendBytes(bytes, 2);
}
uint8_t TasmotaSlave_execParam(uint8_t cmd, uint8_t* params, int count)
{
uint8_t bytes[32];
bytes[0] = cmd;
int i = 0;
while (i < count) {
bytes[i + 1] = params[i];
i++;
}
bytes[i + 1] = CONST_STK_CRC_EOP;
return TasmotaSlave_sendBytes(bytes, i + 2);
}
uint8_t TasmotaSlave_exitProgMode(void)
{
return TasmotaSlave_execCmd(CMND_STK_LEAVE_PROGMODE); // Exit programming mode
}
uint8_t TasmotaSlave_SetupFlash(void)
{
uint8_t ProgParams[] = {0x86, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x80, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00};
uint8_t ExtProgParams[] = {0x05, 0x04, 0xd7, 0xc2, 0x00};
TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_FLASH_SPEED);
if (TasmotaSlave_Serial->hardwareSerial()) {
ClaimSerial();
}
TasmotaSlave_Reset();
uint8_t timeout = 0;
uint8_t no_error = 0;
while (50 > timeout) {
if (TasmotaSlave_execCmd(CMND_STK_GET_SYNC)) {
timeout = 200;
no_error = 1;
}
timeout++;
delay(1);
}
if (no_error) {
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Found bootloader"));
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Bootloader could not be found"));
}
if (no_error) {
if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE, ProgParams, sizeof(ProgParams))) {
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (1)"));
}
}
if (no_error) {
if (TasmotaSlave_execParam(CMND_STK_SET_DEVICE_EXT, ExtProgParams, sizeof(ExtProgParams))) {
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Could not configure device for programming (2)"));
}
}
if (no_error) {
if (TasmotaSlave_execCmd(CMND_STK_ENTER_PROGMODE)) {
} else {
no_error = 0;
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Failed to put bootloader into programming mode"));
}
}
return no_error;
}
uint8_t TasmotaSlave_loadAddress(uint8_t adrHi, uint8_t adrLo)
{
uint8_t params[] = { adrLo, adrHi };
return TasmotaSlave_execParam(CMND_STK_LOAD_ADDRESS, params, sizeof(params));
}
void TasmotaSlave_FlashPage(uint8_t addr_h, uint8_t addr_l, uint8_t* data)
{
uint8_t Header[] = {CMND_STK_PROG_PAGE, 0x00, 0x80, 0x46};
TasmotaSlave_loadAddress(addr_h, addr_l);
TasmotaSlave_Serial->write(Header, 4);
for (int i = 0; i < 128; i++) {
TasmotaSlave_Serial->write(data[i]);
}
TasmotaSlave_Serial->write(CONST_STK_CRC_EOP);
TasmotaSlave_waitForSerialData(2, 250);
TasmotaSlave_Serial->read();
TasmotaSlave_Serial->read();
}
void TasmotaSlave_Flash(void)
{
bool reading = true;
uint32_t read = 0;
uint32_t processed = 0;
char thishexline[50];
uint8_t position = 0;
char* flash_buffer;
SimpleHexParse hexParse = SimpleHexParse();
if (!TasmotaSlave_SetupFlash()) {
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flashing aborted!"));
TSlave.flashing = false;
restart_flag = 2;
return;
}
flash_buffer = new char[SPI_FLASH_SEC_SIZE];
uint32_t flash_start = TasmotaSlave_FlashStart() * SPI_FLASH_SEC_SIZE;
while (reading) {
ESP.flashRead(flash_start + read, (uint32_t*)flash_buffer, SPI_FLASH_SEC_SIZE);
read = read + SPI_FLASH_SEC_SIZE;
if (read >= TSlave.spi_hex_size) {
reading = false;
}
for (uint32_t ca = 0; ca < SPI_FLASH_SEC_SIZE; ca++) {
processed++;
if ((processed <= TSlave.spi_hex_size) && (!hexParse.EndOfFile)) {
if (':' == flash_buffer[ca]) {
position = 0;
}
if (0x0D == flash_buffer[ca]) {
thishexline[position] = 0;
hexParse.parseLine(thishexline);
if (hexParse.PageIsReady) {
TasmotaSlave_FlashPage(hexParse.ptr_h, hexParse.ptr_l, hexParse.FlashPage);
hexParse.PageIsReady = false;
hexParse.FlashPageIdx = 0;
}
} else {
if (0x0A != flash_buffer[ca]) {
thishexline[position] = flash_buffer[ca];
position++;
}
}
}
}
}
TasmotaSlave_exitProgMode();
AddLog_P2(LOG_LEVEL_INFO, PSTR("TasmotaSlave: Flash done!"));
TSlave.flashing = false;
restart_flag = 2;
}
void TasmotaSlave_SetFlagFlashing(bool value)
{
TSlave.flashing = value;
}
bool TasmotaSlave_GetFlagFlashing(void)
{
return TSlave.flashing;
}
void TasmotaSlave_WriteBuffer(uint8_t *buf, size_t size)
{
if (0 == TSlave.spi_sector_cursor) { // Starting a new sector write so we need to erase it first
ESP.flashEraseSector(TSlave.spi_sector_counter);
}
TSlave.spi_sector_cursor++;
ESP.flashWrite((TSlave.spi_sector_counter * SPI_FLASH_SEC_SIZE) + ((TSlave.spi_sector_cursor-1)*2048), (uint32_t*)buf, size);
TSlave.spi_hex_size = TSlave.spi_hex_size + size;
if (2 == TSlave.spi_sector_cursor) { // The web upload sends 2048 bytes at a time so keep track of the cursor position to reset it for the next flash sector erase
TSlave.spi_sector_cursor = 0;
TSlave.spi_sector_counter++;
}
}
void TasmotaSlave_Init(void)
{
if (TSlave.type) {
return;
}
if (10 > TSlave.waitstate) {
TSlave.waitstate++;
return;
}
if (!TSlave.SerialEnabled) {
if (PinUsed(GPIO_TASMOTASLAVE_RXD) && PinUsed(GPIO_TASMOTASLAVE_TXD) &&
(PinUsed(GPIO_TASMOTASLAVE_RST) || PinUsed(GPIO_TASMOTASLAVE_RST_INV))) {
TasmotaSlave_Serial = new TasmotaSerial(Pin(GPIO_TASMOTASLAVE_RXD), Pin(GPIO_TASMOTASLAVE_TXD), 1, 0, 200);
if (TasmotaSlave_Serial->begin(USE_TASMOTA_SLAVE_SERIAL_SPEED)) {
if (TasmotaSlave_Serial->hardwareSerial()) {
ClaimSerial();
}
TasmotaSlave_Serial->setTimeout(100); // Theo 20200502 - increase from 50
if (PinUsed(GPIO_TASMOTASLAVE_RST_INV)) {
SetPin(Pin(GPIO_TASMOTASLAVE_RST_INV), GPIO_TASMOTASLAVE_RST);
TSlave.inverted = HIGH;
}
pinMode(Pin(GPIO_TASMOTASLAVE_RST), OUTPUT);
TSlave.SerialEnabled = true;
TasmotaSlave_Reset();
AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Enabled"));
}
}
}
if (TSlave.SerialEnabled) { // All go for hardware now we need to detect features if there are any
TasmotaSlave_sendCmnd(CMND_FEATURES, 0);
char buffer[32] = { 0 };
TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer));
uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer));
if (len) { AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)buffer, len); } // Theo 20200502 - DMP: 99 17 34 01 02 00 00 00
memcpy(&TSlaveSettings, &buffer, sizeof(TSlaveSettings));
if (20191129 == TSlaveSettings.features_version) {
TSlave.type = true;
AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u"), TSlaveSettings.features_version);
} else {
if ((!TSlave.unsupported) && (TSlaveSettings.features_version > 0)) {
AddLog_P2(LOG_LEVEL_INFO, PSTR("Tasmota Slave Version %u not supported!"), TSlaveSettings.features_version);
TSlave.unsupported = true;
}
}
}
}
void TasmotaSlave_Show(void)
{
if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) {
char buffer[100];
TasmotaSlave_sendCmnd(CMND_JSON, 0);
TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_START), buffer, sizeof(buffer)-1);
uint8_t len = TasmotaSlave_Serial->readBytesUntil(char(PARAM_DATA_END), buffer, sizeof(buffer)-1);
buffer[len] = '\0';
ResponseAppend_P(PSTR(",\"TasmotaSlave\":%s"), buffer);
}
}
void TasmotaSlave_sendCmnd(uint8_t cmnd, uint8_t param)
{
TSlaveCommand.command = cmnd;
TSlaveCommand.parameter = param;
char buffer[sizeof(TSlaveCommand)+2];
buffer[0] = CMND_START;
memcpy(&buffer[1], &TSlaveCommand, sizeof(TSlaveCommand));
buffer[sizeof(TSlaveCommand)+1] = CMND_END;
TasmotaSlave_Serial->flush(); // Theo 20200502
for (uint8_t ca = 0; ca < sizeof(buffer); ca++) {
TasmotaSlave_Serial->write(buffer[ca]);
}
}
#define D_PRFX_SLAVE "Slave"
#define D_CMND_SLAVE_RESET "Reset"
#define D_CMND_SLAVE_SEND "Send"
const char kTasmotaSlaveCommands[] PROGMEM = D_PRFX_SLAVE "|"
D_CMND_SLAVE_RESET "|" D_CMND_SLAVE_SEND;
void (* const TasmotaSlaveCommand[])(void) PROGMEM = {
&CmndTasmotaSlaveReset, &CmndTasmotaSlaveSend };
void CmndTasmotaSlaveReset(void)
{
TasmotaSlave_Reset();
TSlave.type = false; // Force redetection
TSlave.waitstate = 7; // give it at least 3 seconds to restart from bootloader
TSlave.unsupported = false; // Reset unsupported flag
ResponseCmndDone();
}
void CmndTasmotaSlaveSend(void)
{
if (0 < XdrvMailbox.data_len) {
TasmotaSlave_sendCmnd(CMND_SLAVE_SEND, XdrvMailbox.data_len);
TasmotaSlave_Serial->write(char(PARAM_DATA_START));
for (uint8_t idx = 0; idx < XdrvMailbox.data_len; idx++) {
TasmotaSlave_Serial->write(XdrvMailbox.data[idx]);
}
TasmotaSlave_Serial->write(char(PARAM_DATA_END));
}
ResponseCmndDone();
}
void TasmotaSlave_ProcessIn(void)
{
uint8_t cmnd = TasmotaSlave_Serial->read();
switch (cmnd) {
case CMND_START:
TasmotaSlave_waitForSerialData(sizeof(TSlaveCommand),50);
uint8_t buffer[sizeof(TSlaveCommand)];
for (uint8_t idx = 0; idx < sizeof(TSlaveCommand); idx++) {
buffer[idx] = TasmotaSlave_Serial->read();
}
TasmotaSlave_Serial->read(); // read trailing byte of command
memcpy(&TSlaveCommand, &buffer, sizeof(TSlaveCommand));
char inbuf[TSlaveCommand.parameter+1];
TasmotaSlave_waitForSerialData(TSlaveCommand.parameter, 50);
TasmotaSlave_Serial->read(); // Read leading byte
for (uint8_t idx = 0; idx < TSlaveCommand.parameter; idx++) {
inbuf[idx] = TasmotaSlave_Serial->read();
}
TasmotaSlave_Serial->read(); // Read trailing byte
inbuf[TSlaveCommand.parameter] = '\0';
if (CMND_PUBLISH_TELE == TSlaveCommand.command) { // We need to publish stat/ with incoming stream as content
Response_P(PSTR("{\"TasmotaSlave\":"));
ResponseAppend_P("%s", inbuf);
ResponseJsonEnd();
MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data);
XdrvRulesProcess();
}
if (CMND_EXECUTE_CMND == TSlaveCommand.command) { // We need to execute the incoming command
ExecuteCommand(inbuf, SRC_IGNORE);
}
break;
default:
break;
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv31(uint8_t function)
{
bool result = false;
switch (function) {
case FUNC_EVERY_100_MSECOND:
if (TSlave.type) {
if (TasmotaSlave_Serial->available()) {
TasmotaSlave_ProcessIn();
}
if (TSlaveSettings.features.func_every_100_msecond) {
TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_100_MSECOND, 0);
}
}
break;
case FUNC_EVERY_SECOND:
if ((TSlave.type) && (TSlaveSettings.features.func_every_second)) {
TasmotaSlave_sendCmnd(CMND_FUNC_EVERY_SECOND, 0);
}
TasmotaSlave_Init();
break;
case FUNC_JSON_APPEND:
if ((TSlave.type) && (TSlaveSettings.features.func_json_append)) {
TasmotaSlave_Show();
}
break;
case FUNC_COMMAND:
result = DecodeCommand(kTasmotaSlaveCommands, TasmotaSlaveCommand);
break;
}
return result;
}
#endif // USE_TASMOTA_SLAVE

View File

@ -322,7 +322,7 @@ String TelegramExecuteCommand(const char *svalue) {
} }
void TelegramLoop(void) { void TelegramLoop(void) {
if (!global_state.wifi_down && (Telegram.recv_enable || Telegram.echo_enable)) { if (!global_state.network_down && (Telegram.recv_enable || Telegram.echo_enable)) {
switch (Telegram.state) { switch (Telegram.state) {
case 0: case 0:
TelegramInit(); TelegramInit();

View File

@ -23,7 +23,7 @@
* ESP32 webcam based on example in Arduino-ESP32 library * ESP32 webcam based on example in Arduino-ESP32 library
* *
* Template as used on ESP32-CAM WiFi + bluetooth Camera Module Development Board ESP32 With Camera Module OV2640 Geekcreit for Arduino * Template as used on ESP32-CAM WiFi + bluetooth Camera Module Development Board ESP32 With Camera Module OV2640 Geekcreit for Arduino
* {"NAME":"AITHINKER CAM No SPI","GPIO":[4992,65504,65504,65504,65504,5088,65504,65504,65504,65504,65504,65504,65504,65504,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,65504,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":1} * {"NAME":"AITHINKER CAM","GPIO":[4992,1,1,1,1,5088,1,1,1,1,1,1,1,1,5089,5090,0,5091,5184,5152,0,5120,5024,5056,0,0,0,0,4928,1,5094,5095,5092,0,0,5093],"FLAG":0,"BASE":1}
* *
* Supported commands: * Supported commands:
* WcStream = Control streaming, 0 = stop, 1 = start * WcStream = Control streaming, 0 = stop, 1 = start
@ -792,7 +792,7 @@ void HandleWebcamRoot(void) {
/*********************************************************************************************/ /*********************************************************************************************/
uint32_t WcSetStreamserver(uint32_t flag) { uint32_t WcSetStreamserver(uint32_t flag) {
if (global_state.wifi_down) { return 0; } if (global_state.network_down) { return 0; }
Wc.stream_active = 0; Wc.stream_active = 0;

View File

@ -31,7 +31,8 @@
* GPIO26 - EMAC_RXD1(RMII) * GPIO26 - EMAC_RXD1(RMII)
* GPIO27 - EMAC_RX_CRS_DV * GPIO27 - EMAC_RX_CRS_DV
* *
* {"NAME":"Olimex ESP32-PoE","GPIO":[65504,65504,65504,65504,65504,65504,0,0,5536,65504,65504,65504,65504,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,65504,65504,65504,65504,65504,0,0,65504],"FLAG":0,"BASE":1} * {"NAME":"Olimex ESP32-PoE","GPIO":[1,1,1,1,1,1,0,0,5536,1,1,1,1,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1],"FLAG":0,"BASE":1}
* {"NAME":"wESP32","GPIO":[1,1,1,1,1,1,0,0,0,1,1,1,5568,5600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,1],"FLAG":0,"BASE":1}
* *
\*********************************************************************************************/ \*********************************************************************************************/
@ -49,7 +50,7 @@
#endif #endif
#ifndef ETH_TYPE #ifndef ETH_TYPE
#define ETH_TYPE ETH_PHY_LAN8720 // ETH.h eth_phy_type_t: 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110 #define ETH_TYPE ETH_PHY_LAN8720 // ETH.h eth_phy_type_t: 0 = ETH_PHY_LAN8720, 1 = ETH_PHY_TLK110, 2 = ETH_PHY_IP101
#endif #endif
#ifndef ETH_CLKMODE #ifndef ETH_CLKMODE
@ -57,36 +58,22 @@
#endif #endif
*/ */
#ifndef ETH_POWER_PIN
#define ETH_POWER_PIN -1
#endif
#ifndef ETH_MDC_PIN
#define ETH_MDC_PIN 23
#endif
#ifndef ETH_MDIO_PIN
#define ETH_MDIO_PIN 18
#endif
#include <ETH.h> #include <ETH.h>
struct { char eth_hostname[sizeof(my_hostname)];
char hostname[33];
} Eth;
void EthernetEvent(WiFiEvent_t event) { void EthernetEvent(WiFiEvent_t event) {
switch (event) { switch (event) {
case SYSTEM_EVENT_ETH_START: case SYSTEM_EVENT_ETH_START:
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION)); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION));
ETH.setHostname(Eth.hostname); ETH.setHostname(eth_hostname);
break; break;
case SYSTEM_EVENT_ETH_CONNECTED: case SYSTEM_EVENT_ETH_CONNECTED:
AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED)); AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED));
break; break;
case SYSTEM_EVENT_ETH_GOT_IP: case SYSTEM_EVENT_ETH_GOT_IP:
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %s, Hostname %s"), AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Mac %s, IPAddress %s, Hostname %s"),
ETH.macAddress().c_str(), ETH.localIP().toString().c_str(), Eth.hostname); ETH.macAddress().c_str(), ETH.localIP().toString().c_str(), eth_hostname);
/* /*
if (ETH.fullDuplex()) { if (ETH.fullDuplex()) {
Serial.print(", FULL_DUPLEX"); Serial.print(", FULL_DUPLEX");
@ -95,6 +82,9 @@ void EthernetEvent(WiFiEvent_t event) {
Serial.print(ETH.linkSpeed()); Serial.print(ETH.linkSpeed());
Serial.println("Mbps"); Serial.println("Mbps");
*/ */
Settings.ip_address[1] = (uint32_t)ETH.gatewayIP();
Settings.ip_address[2] = (uint32_t)ETH.subnetMask();
Settings.ip_address[3] = (uint32_t)ETH.dnsIP();
global_state.eth_down = 0; global_state.eth_down = 0;
break; break;
case SYSTEM_EVENT_ETH_DISCONNECTED: case SYSTEM_EVENT_ETH_DISCONNECTED:
@ -112,13 +102,20 @@ void EthernetEvent(WiFiEvent_t event) {
void EthernetInit(void) { void EthernetInit(void) {
if (!Settings.flag4.network_ethernet) { return; } if (!Settings.flag4.network_ethernet) { return; }
if (!PinUsed(GPIO_ETH_PHY_MDC) && !PinUsed(GPIO_ETH_PHY_MDIO)) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: No ETH MDC and/or ETH MDIO GPIO defined"));
return;
}
// snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s_eth"), my_hostname);
strlcpy(eth_hostname, my_hostname, sizeof(eth_hostname) -5); // Make sure there is room for "_eth"
strcat(eth_hostname, "_eth");
snprintf_P(Eth.hostname, sizeof(Eth.hostname), PSTR("%s_eth"), my_hostname);
WiFi.onEvent(EthernetEvent); WiFi.onEvent(EthernetEvent);
int eth_power = (PinUsed(GPIO_ETH_PHY_POWER)) ? Pin(GPIO_ETH_PHY_POWER) : ETH_POWER_PIN; int eth_power = (PinUsed(GPIO_ETH_PHY_POWER)) ? Pin(GPIO_ETH_PHY_POWER) : -1;
int eth_mdc = (PinUsed(GPIO_ETH_PHY_MDC)) ? Pin(GPIO_ETH_PHY_MDC) : ETH_MDC_PIN; int eth_mdc = Pin(GPIO_ETH_PHY_MDC);
int eth_mdio = (PinUsed(GPIO_ETH_PHY_MDIO)) ? Pin(GPIO_ETH_PHY_MDIO) : ETH_MDIO_PIN; int eth_mdio = Pin(GPIO_ETH_PHY_MDIO);
if (!ETH.begin(Settings.eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings.eth_type, (eth_clock_mode_t)Settings.eth_clk_mode)) { if (!ETH.begin(Settings.eth_address, eth_power, eth_mdc, eth_mdio, (eth_phy_type_t)Settings.eth_type, (eth_clock_mode_t)Settings.eth_clk_mode)) {
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error")); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error"));
}; };
@ -129,7 +126,7 @@ IPAddress EthernetLocalIP(void) {
} }
char* EthernetHostname(void) { char* EthernetHostname(void) {
return Eth.hostname; return eth_hostname;
} }
String EthernetMacAddress(void) { String EthernetMacAddress(void) {
@ -170,7 +167,7 @@ void CmndEthAddress(void)
void CmndEthType(void) void CmndEthType(void)
{ {
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
Settings.eth_type = XdrvMailbox.payload; Settings.eth_type = XdrvMailbox.payload;
restart_flag = 2; restart_flag = 2;
} }

View File

@ -127,15 +127,15 @@ void FifLEEvery250ms(void)
} else { } else {
Energy.data_valid[0] = 0; Energy.data_valid[0] = 0;
// SA=Slave Address, FC=Function Code, BC=Byte Count, B3..B0=Data byte, Ch Cl = crc16 checksum // CA=Client Address, FC=Function Code, BC=Byte Count, B3..B0=Data byte, Ch Cl = crc16 checksum
// U32 registers: // U32 registers:
// 00 01 02 03 04 05 06 07 08 // 00 01 02 03 04 05 06 07 08
// SA FC BC B3 B2 B1 B0 Cl Ch // CA FC BC B3 B2 B1 B0 Cl Ch
// 01 03 04 00 00 00 72 7A 16 = REG[B3..B2=0x0139,B1..B0=0x013A] 114 = 0.114 A // 01 03 04 00 00 00 72 7A 16 = REG[B3..B2=0x0139,B1..B0=0x013A] 114 = 0.114 A
// 01 03 04 00 00 00 B0 FB 87 = REG[B3..B2=0xA01E,B1..B0=0xA01F] 176 = 1.76 kvarh // 01 03 04 00 00 00 B0 FB 87 = REG[B3..B2=0xA01E,B1..B0=0xA01F] 176 = 1.76 kvarh
// U16/S16 registers: // U16/S16 registers:
// 00 01 02 03 04 05 06 // 00 01 02 03 04 05 06
// SA FC BC B1 B0 Cl Ch // CA FC BC B1 B0 Cl Ch
// 01 03 02 5B 02 02 B5 = REG[B1..B0=0x0131] 23298 = 232.98 V // 01 03 02 5B 02 02 B5 = REG[B1..B0=0x0131] 23298 = 232.98 V
// 01 03 02 03 E8 B8 FA = REG[B1..B0=0x0158] 1000 = 1.000 (power factor) // 01 03 02 03 E8 B8 FA = REG[B1..B0=0x0158] 1000 = 1.000 (power factor)
// there are 3 data types used: // there are 3 data types used:

View File

@ -26,7 +26,7 @@
* 2. Configure the module to use I2C on the correct pins. * 2. Configure the module to use I2C on the correct pins.
* 3. Connect your ina226 module(s) to the I2C pins. * 3. Connect your ina226 module(s) to the I2C pins.
* 4. Use the i2cscan console command to probe the modules and check they are present. * 4. Use the i2cscan console command to probe the modules and check they are present.
* 5. Enable the first device at I2C slave address 0x40 using the following console commands: * 5. Enable the first device at I2C address 0x40 using the following console commands:
* a. Sensor54 11 [shunt resistance in ohms] e.g. Sensor54 11 0.1 * a. Sensor54 11 [shunt resistance in ohms] e.g. Sensor54 11 0.1
* b. Sensor54 12 [full scale current in amperes] e.g. Sensor54 12 3.0 * b. Sensor54 12 [full scale current in amperes] e.g. Sensor54 12 3.0
* c. Sensor54 2 saves the settings and restarts Tasmota. The device should show up after the system boots again. * c. Sensor54 2 saves the settings and restarts Tasmota. The device should show up after the system boots again.
@ -35,7 +35,7 @@
* This driver will not probe I2C bus for INA226 devices unless the full scale current is set for a device number. * This driver will not probe I2C bus for INA226 devices unless the full scale current is set for a device number.
* It will map device numbers as follows: * It will map device numbers as follows:
* *
* Device number to I2C slave address mapping * Device number to I2C address mapping
* *
* 1 - 0x40 * 1 - 0x40
* 2 - 0x41 * 2 - 0x41
@ -59,7 +59,7 @@
* *
* Other commands * Other commands
* *
* Sensor54 1 Rescan for devices and return the number of slaves found. * Sensor54 1 Rescan for devices and return the number of INA226 found.
* Sensor54 2 Save the configuration and restart * Sensor54 2 Save the configuration and restart
* *
* *
@ -88,13 +88,13 @@
#define INA226_REG_CALIBRATION (0x05) #define INA226_REG_CALIBRATION (0x05)
typedef struct Ina226SlaveInfo_tag { typedef struct Ina226Info_tag {
uint8_t address; uint8_t address;
uint16_t calibrationValue; uint16_t calibrationValue;
uint16_t config; uint16_t config;
uint8_t present : 1; uint8_t present : 1;
float i_lsb; float i_lsb;
} Ina226SlaveInfo_t; } Ina226Info_t;
/* /*
* Program memory constants * Program memory constants
@ -108,9 +108,9 @@ static const uint8_t PROGMEM probeAddresses[INA226_MAX_ADDRESSES] = {INA226_ADDR
static char Ina226Str[] = "INA226"; static char Ina226Str[] = "INA226";
static uint8_t slavesFound = 0; static uint8_t Ina226sFound = 0;
static uint8_t schedule_reinit = 0; static uint8_t schedule_reinit = 0;
static Ina226SlaveInfo_t slaveInfo[4] = {0}; static Ina226Info_t Ina226Info[4] = {0};
//static uint16_t reinit_count[4]; //static uint16_t reinit_count[4];
static float voltages[4]; static float voltages[4];
static float currents[4]; static float currents[4];
@ -148,10 +148,10 @@ static uint32_t _expand_r_shunt(uint16_t compact_r_shunt)
* Set calibration value for Ina226 * Set calibration value for Ina226
*/ */
void Ina226SetCalibration(uint8_t slaveIndex) void Ina226SetCalibration(uint8_t Ina226Index)
{ {
Ina226SlaveInfo_t *si = slaveInfo + slaveIndex; Ina226Info_t *si = Ina226Info + Ina226Index;
I2cWrite16( si->address, INA226_REG_CALIBRATION, si->calibrationValue); I2cWrite16( si->address, INA226_REG_CALIBRATION, si->calibrationValue);
@ -167,10 +167,10 @@ bool Ina226TestPresence(uint8_t device)
// Read config // Read config
uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG ); uint16_t config = I2cRead16( Ina226Info[device].address, INA226_REG_CONFIG );
//AddLog_P2( LOG_LEVEL_NONE, PSTR("Config register %04x" ), config); //AddLog_P2( LOG_LEVEL_NONE, PSTR("Config register %04x" ), config);
if (config != slaveInfo[device].config) if (config != Ina226Info[device].config)
return false; return false;
return true; return true;
@ -179,10 +179,10 @@ bool Ina226TestPresence(uint8_t device)
void Ina226ResetActive(void) void Ina226ResetActive(void)
{ {
Ina226SlaveInfo_t *p = slaveInfo; Ina226Info_t *p = Ina226Info;
for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) { for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) {
p = &slaveInfo[i]; p = &Ina226Info[i];
// Address // Address
uint8_t addr = p->address; uint8_t addr = p->address;
if (addr) { if (addr) {
@ -199,9 +199,9 @@ void Ina226Init()
{ {
uint32_t i; uint32_t i;
slavesFound = 0; Ina226sFound = 0;
Ina226SlaveInfo_t *p = slaveInfo; Ina226Info_t *p = Ina226Info;
//AddLog_P2( LOG_LEVEL_NONE, "Ina226Init"); //AddLog_P2( LOG_LEVEL_NONE, "Ina226Init");
// AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings)); // AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings));
@ -210,7 +210,7 @@ void Ina226Init()
// AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support"); // AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support");
// Clear slave info data // Clear Ina226 info data
for (i = 0; i < 4; i++){ for (i = 0; i < 4; i++){
*p = {0}; *p = {0};
@ -232,7 +232,7 @@ void Ina226Init()
continue; continue;
//AddLog_P2( LOG_LEVEL_NONE, PSTR("INA226 trying slave address %02x" ), addr ); //AddLog_P2( LOG_LEVEL_NONE, PSTR("INA226 trying address %02x" ), addr );
// Try Resetting the device // Try Resetting the device
@ -257,8 +257,8 @@ void Ina226Init()
if (!I2cWrite16( addr, INA226_REG_CONFIG, config)) if (!I2cWrite16( addr, INA226_REG_CONFIG, config))
continue; // No device continue; // No device
// store data in slave info struct. // store data in info struct.
p = &slaveInfo[i]; p = &Ina226Info[i];
// Address // Address
p->address = addr; p->address = addr;
// Configuration // Configuration
@ -282,7 +282,7 @@ void Ina226Init()
I2cSetActiveFound(addr, Ina226Str); I2cSetActiveFound(addr, Ina226Str);
slavesFound++; Ina226sFound++;
} }
} }
@ -292,7 +292,7 @@ void Ina226Init()
float Ina226ReadBus_v(uint8_t device) float Ina226ReadBus_v(uint8_t device)
{ {
uint8_t addr = slaveInfo[device].address; uint8_t addr = Ina226Info[device].address;
int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE); int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE);
float result = ((float) reg_bus_v) * 0.00125f; float result = ((float) reg_bus_v) * 0.00125f;
@ -307,10 +307,10 @@ float Ina226ReadBus_v(uint8_t device)
float Ina226ReadShunt_i(uint8_t device) float Ina226ReadShunt_i(uint8_t device)
{ {
uint8_t addr = slaveInfo[device].address; uint8_t addr = Ina226Info[device].address;
int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT); int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT);
float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb; float result = ((float) reg_shunt_i) * Ina226Info[device].i_lsb;
return result; return result;
} }
@ -321,10 +321,10 @@ float Ina226ReadShunt_i(uint8_t device)
float Ina226ReadPower_w(uint8_t device) float Ina226ReadPower_w(uint8_t device)
{ {
uint8_t addr = slaveInfo[device].address; uint8_t addr = Ina226Info[device].address;
int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER); int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER);
float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0); float result = ((float) reg_shunt_i) * (Ina226Info[device].i_lsb * 25.0);
return result; return result;
} }
@ -354,19 +354,19 @@ void Ina226EverySecond()
{ {
//AddLog_P2( LOG_LEVEL_NONE, "Ina226EverySecond"); //AddLog_P2( LOG_LEVEL_NONE, "Ina226EverySecond");
for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){ for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){
// If there are slaves, and the device was present, and the device still is present, read its registers // If there are Ina226s, and the device was present, and the device still is present, read its registers
if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){ if (Ina226sFound && Ina226Info[device].present && Ina226TestPresence(device)){
Ina226Read(device); Ina226Read(device);
} }
else { else {
powers[device] = currents[device] = voltages[device] = 0.0f; powers[device] = currents[device] = voltages[device] = 0.0f;
// If device was present, note that it dropped off here // If device was present, note that it dropped off here
//if(slaveInfo[device].present){ //if(Ina226Info[device].present){
//reinit_count[device]++; //reinit_count[device]++;
//AddLog_P2( LOG_LEVEL_DEBUG, "INA226 Device %d dropped off, count: %d", device, reinit_count[device]); //AddLog_P2( LOG_LEVEL_DEBUG, "INA226 Device %d dropped off, count: %d", device, reinit_count[device]);
//} //}
// Device no longer present // Device no longer present
slaveInfo[device].present = false; Ina226Info[device].present = false;
} }
} }
} }
@ -413,7 +413,7 @@ bool Ina226CommandSensor()
case 1: // Rerun init case 1: // Rerun init
Ina226ResetActive(); Ina226ResetActive();
Ina226Init(); Ina226Init();
Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Ina226sFound\":%d}}"),Ina226sFound);
break; break;
case 2: // Save and restart case 2: // Save and restart
@ -497,7 +497,7 @@ void Ina226Show(bool json)
int i, num_found; int i, num_found;
for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) { for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) {
// Skip uninstalled sensors // Skip uninstalled sensors
if (!slaveInfo[i].present) if (!Ina226Info[i].present)
continue; continue;
num_found++; num_found++;

View File

@ -21,6 +21,8 @@
Version yyyymmdd Action Description Version yyyymmdd Action Description
-------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------
0.9.6.0 20200618 integrate - add decryption for LYWSD03
---
0.9.5.0 20200328 integrate - add dew point, multi-page-web ui, refactoring, command interface, 0.9.5.0 20200328 integrate - add dew point, multi-page-web ui, refactoring, command interface,
simple beacon simple beacon
--- ---
@ -62,6 +64,7 @@
#define XSNS_61 61 #define XSNS_61 61
#include <vector> #include <vector>
#include <mbedtls/ccm.h>
#define FLORA 1 #define FLORA 1
#define MJ_HT_V1 2 #define MJ_HT_V1 2
@ -74,14 +77,15 @@
const char S_JSON_NRF_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_NRF "%s\":%d}"; const char S_JSON_NRF_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_NRF "%s\":%d}";
const char S_JSON_NRF_COMMAND[] PROGMEM = "{\"" D_CMND_NRF "%s\":\"%s\"}"; const char S_JSON_NRF_COMMAND[] PROGMEM = "{\"" D_CMND_NRF "%s\":\"%s\"}";
const char kNRF_Commands[] PROGMEM = "Ignore|Page|Scan|Beacon|Chan"; const char kNRF_Commands[] PROGMEM = "Ignore|Page|Scan|Beacon|Chan|Key";
enum NRF_Commands { // commands useable in console or rules enum NRF_Commands { // commands useable in console or rules
CMND_NRF_IGNORE, // ignore specific sensor type (1-6) CMND_NRF_IGNORE, // ignore specific sensor type (1-6)
CMND_NRF_PAGE, // sensor entries per web page, which will be shown alternated CMND_NRF_PAGE, // sensor entries per web page, which will be shown alternated
CMND_NRF_SCAN, // simplified passive BLE adv scan CMND_NRF_SCAN, // simplified passive BLE adv scan
CMND_NRF_BEACON, // even more simplified Beacon, reports time since last sighting CMND_NRF_BEACON, // even more simplified Beacon, reports time since last sighting
CMND_NRF_CHAN // ignore channel 0-2 (translates to 37-39) CMND_NRF_CHAN, // ignore channel 0-2 (translates to 37-39)
CMND_NRF_KEY // add bind_key to a MAC for payload decryption
}; };
const uint16_t kMINRFSlaveID[6]={ 0x0098, // Flora const uint16_t kMINRFSlaveID[6]={ 0x0098, // Flora
@ -104,8 +108,8 @@ const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMIN
const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46}; const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46};
const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5}; const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5};
const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71dafb46}; const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71dafb46};
// const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0xffffffff}; //encrypted - 58 58 const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0x33049deb}; //encrypted - 58 58
const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; //unencrypted - 30 58 // const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; //unencrypted - 30 58
const uint32_t kMINRFCGGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd}; const uint32_t kMINRFCGGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd};
const uint32_t kMINRFCGDPDU[3] = {0x5da0d752,0xc10c16e7,0x29c497c1}; const uint32_t kMINRFCGDPDU[3] = {0x5da0d752,0xc10c16e7,0x29c497c1};
@ -155,6 +159,28 @@ struct bleAdvPacket_t { // for nRF24L01 max 32 bytes = 2+6+24
uint8_t mac[6]; uint8_t mac[6];
}; };
struct encPayload_t {
uint8_t cipher[5];
uint8_t ExtCnt[3];
uint8_t tag[4];
};
struct encPacket_t{
// the packet is longer, but this part is enough to decrypt
uint16_t PID;
uint8_t frameCnt;
uint8_t MAC[6];
encPayload_t payload;
};
union mi_bindKey_t{
struct{
uint8_t key[16];
uint8_t MAC[6];
};
uint8_t buf[22];
};
union FIFO_t{ union FIFO_t{
bleAdvPacket_t bleAdv; bleAdvPacket_t bleAdv;
mi_beacon_t miBeacon; mi_beacon_t miBeacon;
@ -223,6 +249,7 @@ struct scan_entry_t {
std::vector<mi_sensor_t> MIBLEsensors; std::vector<mi_sensor_t> MIBLEsensors;
std::vector<scan_entry_t> MINRFscanResult; std::vector<scan_entry_t> MINRFscanResult;
std::vector<mi_bindKey_t> MIBLEbindKeys;
static union{ static union{
scan_entry_t MINRFdummyEntry; scan_entry_t MINRFdummyEntry;
@ -564,6 +591,61 @@ void MINRFcomputeBeaconPDU(void){
} }
} }
int MINRFdecryptPacket(char *_buf){
encPacket_t *packet = (encPacket_t*)_buf;
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("to decrypt: %02x %02x %02x %02x %02x %02x %02x %02x"),(uint8_t)_buf[0],(uint8_t)_buf[1],(uint8_t)_buf[2],(uint8_t)_buf[3],(uint8_t)_buf[4],(uint8_t)_buf[5],(uint8_t)_buf[6],(uint8_t)_buf[7]);
int ret = 0;
unsigned char output[10] = {0};
uint8_t nonce[12];
const unsigned char authData[1] = {0x11};
// nonce: device MAC, device type, frame cnt, ext. cnt
for (uint32_t i = 0; i<6; i++){
nonce[i] = packet->MAC[5-i];
}
memcpy((uint8_t*)&nonce+6,(uint8_t*)&packet->PID,2);
nonce[8] = packet->frameCnt;
memcpy((uint8_t*)&nonce+9,(uint8_t*)&packet->payload.ExtCnt,3);
uint8_t _bindkey[16] = {0x0};
for(uint32_t i=0; i<MIBLEbindKeys.size(); i++){
if(memcmp(packet->MAC,MIBLEbindKeys[i].MAC,sizeof(packet->MAC))==0){
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("have key"));
memcpy(_bindkey,MIBLEbindKeys[i].key,sizeof(_bindkey));
break;
}
// else{
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mac in packet: %02x %02x %02x %02x %02x %02x"), packet->MAC[0], packet->MAC[1], packet->MAC[2], packet->MAC[3], packet->MAC[4], packet->MAC[5]);
// AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Mac in vector: %02x %02x %02x %02x %02x %02x"), MIBLEbindKeys[i].MAC[0], MIBLEbindKeys[i].MAC[1], MIBLEbindKeys[i].MAC[2], MIBLEbindKeys[i].MAC[3], MIBLEbindKeys[i].MAC[4], MIBLEbindKeys[i].MAC[5]);
// }
}
// init
mbedtls_ccm_context ctx;
mbedtls_ccm_init(&ctx);
// set bind key
ret = mbedtls_ccm_setkey(&ctx,
MBEDTLS_CIPHER_ID_AES,
_bindkey,
16 * 8 //bits
);
ret = mbedtls_ccm_auth_decrypt(&ctx,5,
(const unsigned char*)&nonce, sizeof(nonce),
authData, sizeof(authData),
packet->payload.cipher, output,
packet->payload.tag,sizeof(packet->payload.tag));
AddLog_P2(LOG_LEVEL_DEBUG,PSTR("Err:%i, Decrypted : %02x %02x %02x %02x %02x "), ret, output[0],output[1],output[2],output[3],output[4]);
// put decrypted data in place
memcpy((uint8_t*)(packet->payload.cipher)+1,output,sizeof(packet->payload.cipher));
// clean up
mbedtls_ccm_free(&ctx);
return ret;
}
/*********************************************************************************************\ /*********************************************************************************************\
* helper functions * helper functions
\*********************************************************************************************/ \*********************************************************************************************/
@ -581,6 +663,46 @@ void MINRFreverseMAC(uint8_t _mac[]){
memcpy(_mac,_reversedMAC, sizeof(_reversedMAC)); memcpy(_mac,_reversedMAC, sizeof(_reversedMAC));
} }
void MINRFAddKey(char* payload){
mi_bindKey_t keyMAC;
memset(keyMAC.buf,0,sizeof(keyMAC));
MINRFKeyMACStringToBytes(payload,keyMAC.buf);
bool unknownKey = true;
for(uint32_t i=0; i<MIBLEbindKeys.size(); i++){
if(memcmp(keyMAC.MAC,MIBLEbindKeys[i].MAC,sizeof(keyMAC.MAC))==0){
DEBUG_SENSOR_LOG(PSTR("Known MAC for key"));
unknownKey=false;
}
}
if(unknownKey){
DEBUG_SENSOR_LOG(PSTR("Key for new MAC"));
MIBLEbindKeys.push_back(keyMAC);
}
}
/**
* @brief Convert combined key-MAC-string to
*
* @param _string input string in format: AABBCCDDEEFF... (upper case!), must be 44 chars!!
* @param _mac target byte array with fixed size of 16 + 6
*/
void MINRFKeyMACStringToBytes(char* _string,uint8_t _keyMac[]) { //uppercase
uint32_t index = 0;
while (index < 44) {
char c = _string[index];
uint8_t value = 0;
if(c >= '0' && c <= '9')
value = (c - '0');
else if (c >= 'A' && c <= 'F')
value = (10 + (c - 'A'));
_keyMac[(index/2)] += value << (((index + 1) % 2) * 4);
index++;
}
DEBUG_SENSOR_LOG(PSTR("MINRF: %s to:"),_string);
DEBUG_SENSOR_LOG(PSTR("MINRF: key-array: %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"),_keyMac[0],_keyMac[1],_keyMac[2],_keyMac[3],_keyMac[4],_keyMac[5],_keyMac[6],_keyMac[7],_keyMac[8],_keyMac[9],_keyMac[10],_keyMac[11],_keyMac[12],_keyMac[13],_keyMac[14],_keyMac[15]);
DEBUG_SENSOR_LOG(PSTR("MINRF: MAC-array: %02X%02X%02X%02X%02X%02X"),_keyMac[16],_keyMac[17],_keyMac[18],_keyMac[19],_keyMac[20],_keyMac[21]);
}
/** /**
* @brief * @brief
* *
@ -754,14 +876,19 @@ void MINRFhandleMiBeaconPacket(void){
uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.Mac, MINRF.buffer.miBeacon.productID); uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.Mac, MINRF.buffer.miBeacon.productID);
if(_slot==0xff) return; if(_slot==0xff) return;
DEBUG_SENSOR_LOG(PSTR("MINRF: slot %u, size vector: %u %u"),_slot,MIBLEsensors.size()); DEBUG_SENSOR_LOG(PSTR("MINRF: slot %u, size vector: %u %u"),_slot,MIBLEsensors.size());
mi_sensor_t *_sensorVec = &MIBLEsensors.at(_slot); mi_sensor_t *_sensorVec = &MIBLEsensors.at(_slot);
DEBUG_SENSOR_LOG(PSTR("MINRF: %u %u %u"),_slot,_sensorVec->type,MINRF.buffer.miBeacon.type);
float _tempFloat; float _tempFloat;
if (_sensorVec->type==MJ_HT_V1 || _sensorVec->type==CGG1){ if (_sensorVec->type==MJ_HT_V1 || _sensorVec->type==CGG1){
memcpy(MINRFtempBuf,(uint8_t*)&MINRF.buffer.miBeacon.spare, 32-9); // shift by one byte for the MJ_HT_V1 and CGG1 memcpy(MINRFtempBuf,(uint8_t*)&MINRF.buffer.miBeacon.spare, 32-9); // shift by one byte for the MJ_HT_V1 and CGG1
memcpy((uint8_t*)&MINRF.buffer.miBeacon.type,MINRFtempBuf, 32-9); // shift by one byte for the MJ_HT_V1 and CGG1 memcpy((uint8_t*)&MINRF.buffer.miBeacon.type,MINRFtempBuf, 32-9); // shift by one byte for the MJ_HT_V1 and CGG1
} }
if(_sensorVec->type==LYWSD03){
int decryptRet = -1;
decryptRet = MINRFdecryptPacket((char*)&MINRF.buffer); //start with PID
if(decryptRet==0) _sensorVec->showedUp=255; // if decryption worked, this must be a valid sensor
}
DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kNRFSlaveType[_sensorVec->type-1],_slot); DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kNRFSlaveType[_sensorVec->type-1],_slot);
switch(MINRF.buffer.miBeacon.type){ switch(MINRF.buffer.miBeacon.type){
@ -823,21 +950,6 @@ void MINRFhandleMiBeaconPacket(void){
break; break;
} }
} }
/**
* @brief more or less a placeholder, at least it is technically possible to really decrypt data, but
* the bind_key must be retrieved with 3rd-party-tools -> TODO
*/
void MINRFhandleLYWSD03Packet(void){
// not much to do ATM, just show the sensor without data
MINRFreverseMAC(MINRF.buffer.miBeacon.Mac);
uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.Mac, MINRF.buffer.miBeacon.productID);
DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot);
if(_slot==0xff) return;
MINRF_LOG_BUFFER(MINRF.streamBuffer);
MINRF_LOG_BUFFER(MINRF.lsfrBuffer);
MINRF_LOG_BUFFER(MINRF.buffer.raw);
}
/** /**
* @brief parse the Cleargrass-packet * @brief parse the Cleargrass-packet
@ -901,12 +1013,9 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds
} }
else MINRFhandleScan(); else MINRFhandleScan();
break; break;
case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1: case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1: case LYWSD03:
MINRFhandleMiBeaconPacket(); MINRFhandleMiBeaconPacket();
break; break;
case LYWSD03:
MINRFhandleLYWSD03Packet();
break;
case CGD1: case CGD1:
MINRFhandleCGD1Packet(); MINRFhandleCGD1Packet();
break; break;
@ -1026,6 +1135,12 @@ bool NRFCmd(void) {
} }
Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.channelIgnore); Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.channelIgnore);
break; break;
case CMND_NRF_KEY:
if (XdrvMailbox.data_len==44){ // a KEY-MAC-string
MINRFAddKey(XdrvMailbox.data);
Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data);
}
break;
default: default:
// else for Unknown command // else for Unknown command
serviced = false; serviced = false;
@ -1191,5 +1306,3 @@ bool Xsns61(uint8_t function)
#endif // USE_MIBLE #endif // USE_MIBLE
#endif // USE_NRF24 #endif // USE_NRF24
#endif // USE_SPI #endif // USE_SPI

142
tasmota/xsns_74_lmt01.ino Normal file
View File

@ -0,0 +1,142 @@
/*
xns_74_lmt01.ino - Support for single wire LMT01 Temperature Sensor
Copyright (C) 2020 Theo Arends, Justifiably
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_LMT01
/*********************************************************************************************\
* LMT01 - 0.5°C Accurate 2-Pin Digital Output Temperature Sensor With Pulse Count Interface
*
* Uses fragments of public domain code LMT01_Example.ino released by Texas Instruments, July 10th 2017.
* See https://training.ti.com/how-interface-lmt01-temperature-sensor-arduino
\*********************************************************************************************/
#define XSNS_74 74
#define LMT01_TIMEOUT 200 // ms timeout for a reading cycle
bool lmt01_initialized = false;
float lmt01_temperature = NAN;
void LMT01_Init(void) {
if (PinUsed(GPIO_LMT01)) {
pinMode(Pin(GPIO_LMT01), INPUT);
attachInterrupt(Pin(GPIO_LMT01), LMT01_countPulse, FALLING);
lmt01_initialized = true;
}
}
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // Fix core 2.5.x ISR not in IRAM Exception
void LMT01_countPulse(void) ICACHE_RAM_ATTR;
#endif // ARDUINO_ESP8266_RELEASE_2_3_0
volatile int lmt01_pulseCount = 0;
void LMT01_countPulse(void) {
lmt01_pulseCount++;
}
void LMT01_GetTemperature(void) {
int pulses = 0;
pulses = LMT01_getPulses();
if (pulses >= 0) {
// simple linear conversion, datasheet has a look-up table alternative
// which is accurate over a wider temperature range
lmt01_temperature = ConvertTemp(0.0625 * pulses - 50);
} else {
lmt01_temperature = NAN; // Timeout
}
}
int LMT01_getPulses(void) {
int timeout = LMT01_TIMEOUT;
int hold = -1;
// complete current pulse cycle (50ms max)
while(lmt01_pulseCount != hold && --timeout > 0) {
hold = lmt01_pulseCount;
delay(1);
}
lmt01_pulseCount = 0;
// wait for start of next (54ms max)
while(lmt01_pulseCount == 0 && --timeout > 0) {
delay(1);
}
hold = -1;
// take this count (up to 50ms)
while(lmt01_pulseCount != hold && --timeout > 0) {
hold = lmt01_pulseCount;
delay(1);
}
if (timeout > 0) {
return hold;
}
return -1;
}
void LMT01_Show(bool Json) {
char temp[33];
dtostrfd(lmt01_temperature, Settings.flag2.temperature_resolution, temp);
if (Json) {
ResponseAppend_P(JSON_SNS_TEMP, "LMT01", temp);
#ifdef USE_DOMOTICZ
if (0 == tele_period) {
DomoticzSensor(DZ_TEMP, temp);
}
#endif // USE_DOMOTICZ
#ifdef USE_KNX
if (0 == tele_period) {
KnxSensor(KNX_TEMPERATURE, lmt01_temperature);
}
#endif // USE_KNX
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_TEMP, "LMT01", temp, TempUnit());
#endif // USE_WEBSERVER
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns74(uint8_t function)
{
bool result = false;
if (FUNC_INIT == function) {
LMT01_Init();
}
else if (lmt01_initialized) {
switch (function) {
case FUNC_EVERY_SECOND:
LMT01_GetTemperature();
break;
case FUNC_JSON_APPEND:
LMT01_Show(true);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
LMT01_Show(false);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_LMT01

View File

@ -206,7 +206,7 @@ a_features = [[
"USE_IAQ","USE_DISPLAY_SEVENSEG","USE_AS3935","USE_PING", "USE_IAQ","USE_DISPLAY_SEVENSEG","USE_AS3935","USE_PING",
"USE_WINDMETER","USE_OPENTHERM","USE_THERMOSTAT","USE_VEML6075", "USE_WINDMETER","USE_OPENTHERM","USE_THERMOSTAT","USE_VEML6075",
"USE_VEML7700","USE_MCP9808","USE_BL0940","USE_TELEGRAM", "USE_VEML7700","USE_MCP9808","USE_BL0940","USE_TELEGRAM",
"USE_HP303B","USE_TCP_BRIDGE","","", "USE_HP303B","USE_TCP_BRIDGE","USE_TELEINFO","USE_LMT01",
"","","","", "","","","",
"","","","", "","","","",
"","","USE_ETHERNET","USE_WEBCAM" "","","USE_ETHERNET","USE_WEBCAM"
@ -243,7 +243,7 @@ else:
obj = json.load(fp) obj = json.load(fp)
def StartDecode(): def StartDecode():
print ("\n*** decode-status.py v20200611 by Theo Arends and Jacek Ziolkowski ***") print ("\n*** decode-status.py v20200617 by Theo Arends and Jacek Ziolkowski ***")
# print("Decoding\n{}".format(obj)) # print("Decoding\n{}".format(obj))