mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-23 10:46:31 +00:00
Merge branch 'development' into teleinfo
This commit is contained in:
commit
19a63e944c
@ -77,6 +77,7 @@
|
||||
| USE_MAX31855 | - | - | - | - | x | - | - |
|
||||
| USE_MAX31865 | - | - | - | - | - | - | - |
|
||||
| USE_THERMOSTAT | - | - | - | - | - | - | - |
|
||||
| USE_LMT01 | - | - | - | - | x | - | - |
|
||||
| | | | | | | | |
|
||||
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
|
||||
| USE_I2C | - | - | x | x | x | - | x |
|
||||
@ -181,3 +182,4 @@
|
||||
|-----------------------|---------|-------|--------|-----|---------|----|---------|--------|--------
|
||||
| USE_MI_ESP32 | - | - | - | - | - | - | - | - |
|
||||
| USE_WEBCAM | - | - | - | - | - | - | - | x |
|
||||
| USE_ETHERNET | - | - | - | - | - | - | - | - |
|
||||
|
@ -52,16 +52,20 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
|
||||
|
||||
## Changelog
|
||||
|
||||
### Version 8.3.1.5
|
||||
### Version 8.3.1.6
|
||||
|
||||
- Change IRremoteESP8266 library updated to v2.7.7
|
||||
- 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 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)
|
||||
- Add command ``Rule0`` to change global rule parameters
|
||||
- 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 ``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 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)
|
||||
@ -80,6 +84,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
|
||||
- Add initial support for Telegram bot (#8619)
|
||||
- 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
|
||||
- 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
|
||||
- Added Library to be used for decoding Teleinfo (French Metering Smart Meter)
|
||||
- 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 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)
|
||||
|
@ -398,7 +398,7 @@ typedef struct __callback_assignment
|
||||
} callback_assignment_t;
|
||||
|
||||
// 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 {
|
||||
public:
|
||||
@ -567,7 +567,7 @@ class ESPKNXIP {
|
||||
callback_assignment_id_t __callback_register_assignment(address_t address, callback_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;
|
||||
address_t physaddr;
|
||||
|
1
lib/mbedtls/README.md
Normal file
1
lib/mbedtls/README.md
Normal file
@ -0,0 +1 @@
|
||||
Stripped down library for aes-ccm-decryption in the MI_NRF24.ino.
|
297
lib/mbedtls/include/mbedtls/aes.h
Normal file
297
lib/mbedtls/include/mbedtls/aes.h
Normal 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 */
|
141
lib/mbedtls/include/mbedtls/ccm.h
Normal file
141
lib/mbedtls/include/mbedtls/ccm.h
Normal 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 */
|
628
lib/mbedtls/include/mbedtls/check_config.h
Normal file
628
lib/mbedtls/include/mbedtls/check_config.h
Normal 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 */
|
709
lib/mbedtls/include/mbedtls/cipher.h
Normal file
709
lib/mbedtls/include/mbedtls/cipher.h
Normal 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 */
|
109
lib/mbedtls/include/mbedtls/cipher_internal.h
Normal file
109
lib/mbedtls/include/mbedtls/cipher_internal.h
Normal 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 */
|
2600
lib/mbedtls/include/mbedtls/config.h
Normal file
2600
lib/mbedtls/include/mbedtls/config.h
Normal file
File diff suppressed because it is too large
Load Diff
295
lib/mbedtls/include/mbedtls/platform.h
Normal file
295
lib/mbedtls/include/mbedtls/platform.h
Normal 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 */
|
81
lib/mbedtls/include/mbedtls/platform_time.h
Normal file
81
lib/mbedtls/include/mbedtls/platform_time.h
Normal 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
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
464
lib/mbedtls/src/ccm.c
Normal 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
917
lib/mbedtls/src/cipher.c
Normal 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 */
|
1451
lib/mbedtls/src/cipher_wrap.c
Normal file
1451
lib/mbedtls/src/cipher_wrap.c
Normal file
File diff suppressed because it is too large
Load Diff
4
libesp32/ESP32-Ethernet/README.md
Normal file
4
libesp32/ESP32-Ethernet/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Ethernet Arduino Library for ESP32
|
||||
|
||||
See https://github.com/espressif/arduino-esp32/issues/3554#issuecomment-596902806
|
||||
|
@ -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);
|
||||
}
|
17
libesp32/ESP32-Ethernet/library.properties
Normal file
17
libesp32/ESP32-Ethernet/library.properties
Normal 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
|
299
libesp32/ESP32-Ethernet/src/ETH.cpp
Normal file
299
libesp32/ESP32-Ethernet/src/ETH.cpp
Normal 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(ð_config, &config, sizeof(eth_config_t));
|
||||
}
|
||||
else if(type == ETH_PHY_TLK110)
|
||||
{
|
||||
eth_config_t config = phy_tlk110_default_ethernet_config;
|
||||
memcpy(ð_config, &config, sizeof(eth_config_t));
|
||||
}
|
||||
else if(type == ETH_PHY_IP101)
|
||||
{
|
||||
eth_config_t config = phy_ip101_default_ethernet_config;
|
||||
memcpy(ð_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(ð_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;
|
95
libesp32/ESP32-Ethernet/src/ETH.h
Normal file
95
libesp32/ESP32-Ethernet/src/ETH.h
Normal 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_ */
|
@ -1,8 +1,19 @@
|
||||
## 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
|
||||
|
||||
- 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
|
||||
|
||||
|
@ -505,10 +505,14 @@
|
||||
#define D_CMND_ZIGBEE_RESET "Reset"
|
||||
#define D_JSON_ZIGBEE_CC2530 "CC2530"
|
||||
#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_ZIGBEE_EZSP_SEND "EZSPSend"
|
||||
#define D_JSON_ZIGBEE_STATE "ZbState"
|
||||
#define D_JSON_ZIGBEEZNPRECEIVED "ZbZNPReceived"
|
||||
#define D_JSON_ZIGBEE_EZSP_RECEIVED "ZbEZSPReceived"
|
||||
#define D_JSON_ZIGBEEZNPSENT "ZbZNPSent"
|
||||
#define D_JSON_ZIGBEE_EZSP_SENT "ZbEZSPSent"
|
||||
#define D_JSON_ZIGBEEZCL_RECEIVED "ZbZCLReceived"
|
||||
#define D_JSON_ZIGBEEZCL_RAW_RECEIVED "ZbZCLRawReceived"
|
||||
#define D_JSON_ZIGBEE_DEVICE "Device"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Подобрена комуникация"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Използвана енергия днес"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Spotřeba Dnes"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Erweiterte Kommunikation"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energie heute"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Βελτίωση επικοινωνίας"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Ενέργεια σήμερα"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energy Today"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Mejora de Comunicación"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energía Hoy"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Amélioration de la communication"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Énergie aujourd'hui"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "Hibernation"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Esclave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Esclave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Esclave Rst"
|
||||
#define D_SENSOR_CLIENT_TX "Esclave TX"
|
||||
#define D_SENSOR_CLIENT_RX "Esclave RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Esclave Rst"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "שיפור התקשורת"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "צריכה יומית"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Mai energia"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Miglioramento comunicazione"
|
||||
#define D_KNX_TX_SLOT "KNX - TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energia - oggi"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 - DATI"
|
||||
#define D_SENSOR_DEEPSLEEP "Deep sleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS - Abilita"
|
||||
#define D_SENSOR_SLAVE_TX "Slave - TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave - RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave - RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client - TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client - RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client - RST"
|
||||
#define D_SENSOR_GPS_RX "GPS - RX"
|
||||
#define D_SENSOR_GPS_TX "GPS - TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 - RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "Velocità vento"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "커뮤니케이션 강화"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "금일 전력 사용량"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Verbeter verbinding"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Verbruik vandaag"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Rozszerzenia"
|
||||
#define D_KNX_TX_SLOT "Gniazdo TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energia dzisiaj"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "Głęboko uśpiony"
|
||||
#define D_SENSOR_EXS_ENABLE "Załącz EXS"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Melhoria da comunicação"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Consumo energético de hoje"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Melhoria de Comunicação"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Consumo energético de hoje"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Îmbunătățire Communicație"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energia de Azi"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Энергия Сегодня"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Spotreba dnes"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Kommuniceringsförbättring"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energi idag"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Energy Today"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Підвищення зв'язку"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "Енергія Сьогодні"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "通讯增强"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "今日用电量"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -445,6 +445,8 @@
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
#define D_KNX_TX_SLOT "KNX TX"
|
||||
#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
|
||||
#define D_ENERGY_TODAY "今日用電量"
|
||||
@ -663,9 +665,9 @@
|
||||
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
|
||||
#define D_SENSOR_DEEPSLEEP "DeepSleep"
|
||||
#define D_SENSOR_EXS_ENABLE "EXS Enable"
|
||||
#define D_SENSOR_SLAVE_TX "Slave TX"
|
||||
#define D_SENSOR_SLAVE_RX "Slave RX"
|
||||
#define D_SENSOR_SLAVE_RESET "Slave RST"
|
||||
#define D_SENSOR_CLIENT_TX "Client TX"
|
||||
#define D_SENSOR_CLIENT_RX "Client RX"
|
||||
#define D_SENSOR_CLIENT_RESET "Client RST"
|
||||
#define D_SENSOR_GPS_RX "GPS RX"
|
||||
#define D_SENSOR_GPS_TX "GPS TX"
|
||||
#define D_SENSOR_HM10_RX "HM10 RX"
|
||||
@ -681,6 +683,7 @@
|
||||
#define D_SENSOR_WINDMETER_SPEED "WindMeter Spd"
|
||||
#define D_SENSOR_TELEINFO_RX "TInfo Rx"
|
||||
#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_RESET "CAM_RESET"
|
||||
#define D_GPIO_WEBCAM_XCLK "CAM_XCLK"
|
||||
|
@ -50,7 +50,12 @@
|
||||
#define PROJECT "tasmota" // PROJECT is used as the default topic delimiter
|
||||
|
||||
// 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_STATE true // [SetOption0] Save changed power state to Flash (false = disable, true = enable)
|
||||
@ -135,6 +140,8 @@
|
||||
// -- MQTT - Home Assistant Discovery -------------
|
||||
#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 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 ------------------------------
|
||||
#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_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_TASMOTA_SLAVE // 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_SLAVE_SERIAL_SPEED 57600 // Depends on the sketch that is running on the Uno/Pro Mini
|
||||
//#define USE_TASMOTA_CLIENT // Add support for Arduino Uno/Pro Mini via serial interface including flashing (+2k6 code, 64 mem)
|
||||
#define USE_TASMOTA_CLIENT_FLASH_SPEED 57600 // Usually 57600 for 3.3V variants and 115200 for 5V variants
|
||||
#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_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 --------------------
|
||||
#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_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_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 -----------------
|
||||
#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_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 USE_LMT01 // Add support for TI LMT01 temperature sensor, count pulses on single GPIO (+0k5 code)
|
||||
|
||||
// -- IR Remote features - all protocols from IRremoteESP8266 --------------------------
|
||||
// IR Full Protocols mode is activated through platform.io only.
|
||||
@ -654,6 +662,9 @@
|
||||
|
||||
// -- Zigbee interface ----------------------------
|
||||
//#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
|
||||
// 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
|
||||
@ -732,9 +743,13 @@
|
||||
|
||||
//#define USE_ETHERNET // Add support for ethernet (Currently fixed for 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_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_MI_ESP32 // Add support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
|
||||
|
@ -567,11 +567,12 @@ struct {
|
||||
uint16_t windmeter_pulse_debounce; // F3A
|
||||
int16_t windmeter_speed_factor; // F3C
|
||||
uint8_t windmeter_tele_pchange; // F3E
|
||||
uint8_t ledpwm_on; // F3F
|
||||
uint8_t ledpwm_off; // F40
|
||||
uint8_t ledpwm_on; // F3F
|
||||
uint8_t ledpwm_off; // F40
|
||||
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
|
||||
uint16_t pulse_counter_debounce_low; // FB8
|
||||
|
@ -768,6 +768,7 @@ void SettingsDefaultSet2(void)
|
||||
// flag.interlock |= 0;
|
||||
Settings.interlock[0] = 0xFF; // Legacy support using all relays in one interlock group
|
||||
Settings.module = MODULE;
|
||||
Settings.fallback_module = FALLBACK_MODULE;
|
||||
ModuleDefault(WEMOS);
|
||||
// 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));
|
||||
@ -1452,12 +1453,15 @@ void SettingsDelta(void)
|
||||
Settings.flag4.network_wifi = 1;
|
||||
Settings.flag4.network_ethernet = 1;
|
||||
}
|
||||
if (Settings.version < 0x08030105) {
|
||||
#ifdef ESP32
|
||||
if (Settings.version < 0x08030105) {
|
||||
Settings.eth_type = ETH_TYPE;
|
||||
Settings.eth_clk_mode = ETH_CLKMODE;
|
||||
Settings.eth_address = ETH_ADDR;
|
||||
}
|
||||
#endif
|
||||
if (Settings.version < 0x08030106) {
|
||||
Settings.fallback_module = FALLBACK_MODULE;
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
|
@ -1359,7 +1359,15 @@ bool JsonTemplate(const char* dataBuf)
|
||||
}
|
||||
if (obj[D_JSON_GPIO].success()) {
|
||||
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;
|
||||
#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()) {
|
||||
@ -1378,7 +1386,15 @@ void TemplateJson(void)
|
||||
{
|
||||
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++) {
|
||||
#ifdef ESP8266
|
||||
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);
|
||||
}
|
||||
@ -1604,8 +1620,8 @@ void I2cScan(char *devs, unsigned int devs_len)
|
||||
// Return error codes defined in twi.h and core_esp8266_si2c.c
|
||||
// I2C_OK 0
|
||||
// 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_SDA_HELD_LOW 3 = I2C bus error. SDA line held low by slave/another_master after n bits
|
||||
// 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 client/another_master after n bits
|
||||
// I2C_SDA_HELD_LOW_AFTER_INIT 4 = line busy. SDA again held low by another device. 2nd master?
|
||||
|
||||
uint8_t error = 0;
|
||||
|
@ -1018,18 +1018,29 @@ void CmndModule(void)
|
||||
present = ValidTemplateModule(XdrvMailbox.payload);
|
||||
}
|
||||
if (present) {
|
||||
Settings.last_module = Settings.module;
|
||||
Settings.module = XdrvMailbox.payload;
|
||||
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;
|
||||
if (XdrvMailbox.index == 2) {
|
||||
Settings.fallback_module = XdrvMailbox.payload;
|
||||
} else {
|
||||
Settings.last_module = Settings.module;
|
||||
Settings.module = XdrvMailbox.payload;
|
||||
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)
|
||||
|
@ -477,8 +477,8 @@ void GetFeatures(void)
|
||||
#ifdef USE_EXS_DIMMER
|
||||
feature5 |= 0x00008000; // xdrv_30_exs_dimmer.ino
|
||||
#endif
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
feature5 |= 0x00010000; // xdrv_31_arduino_slave.ino
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
feature5 |= 0x00010000; // xdrv_31_tasmota_client.ino
|
||||
#endif
|
||||
#ifdef USE_HIH6
|
||||
feature5 |= 0x00020000; // xsns_55_hih_series.ino
|
||||
@ -587,8 +587,9 @@ void GetFeatures(void)
|
||||
#ifdef USE_TELEINFO
|
||||
feature6 |= 0x00040000; // xnrg_15_teleinfo.ino
|
||||
#endif
|
||||
|
||||
// feature6 |= 0x00080000;
|
||||
#ifdef USE_LMT01
|
||||
feature6 |= 0x00080000; // xsns_74_lmt01.ino
|
||||
#endif
|
||||
|
||||
// feature6 |= 0x00100000;
|
||||
// feature6 |= 0x00200000;
|
||||
|
@ -379,7 +379,7 @@ void RtcSecond(void)
|
||||
Rtc.millis = millis();
|
||||
|
||||
if (!Rtc.user_time_entry) {
|
||||
if (!global_state.wifi_down) {
|
||||
if (!global_state.network_down) {
|
||||
uint8_t uptime_minute = (uptime / 60) % 60; // 0 .. 59
|
||||
if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) {
|
||||
Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle
|
||||
|
@ -203,7 +203,8 @@ const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to
|
||||
#define KNX_SLOT3 28
|
||||
#define KNX_SLOT4 29
|
||||
#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
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -278,12 +278,8 @@ void setup(void) {
|
||||
#endif
|
||||
}
|
||||
if (RtcReboot.fast_reboot_count > Settings.param[P_BOOT_LOOP_OFFSET] +4) { // Restarted 6 times
|
||||
#ifdef ESP8266
|
||||
Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic
|
||||
// Settings.last_module = SONOFF_BASIC;
|
||||
#else // ESP32
|
||||
Settings.module = WEMOS; // Reset module to Wemos
|
||||
#endif // ESP8266 - ESP32
|
||||
Settings.module = Settings.fallback_module; // Reset module to fallback module
|
||||
// Settings.last_module = Settings.fallback_module;
|
||||
}
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count);
|
||||
}
|
||||
|
@ -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_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_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_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)
|
||||
@ -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_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_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k 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_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_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)
|
||||
|
||||
//#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_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_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_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_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_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_ENERGY_SENSOR // Disable energy sensors
|
||||
|
@ -69,6 +69,18 @@ String EthernetMacAddress(void);
|
||||
#ifdef USE_EMULATION_WEMO
|
||||
#define USE_EMULATION
|
||||
#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
|
||||
#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
|
||||
#define MODULE SONOFF_BASIC // [Module] Select default model
|
||||
#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
|
||||
#define ARDUINO_CORE_RELEASE "STAGE"
|
||||
@ -301,6 +316,9 @@ const char kWebColors[] PROGMEM =
|
||||
#ifndef MODULE
|
||||
#define MODULE WEMOS // [Module] Select default model
|
||||
#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
|
||||
#define ARDUINO_CORE_RELEASE "STAGE"
|
||||
|
@ -137,8 +137,8 @@ enum UserSelectablePins {
|
||||
GPIO_TUYA_RX, // Tuya Serial interface
|
||||
GPIO_MGC3130_XFER, // MGC3130 Transfer
|
||||
GPIO_MGC3130_RESET, // MGC3130 Reset
|
||||
GPIO_SSPI_MISO, // Software SPI Master Input Slave Output
|
||||
GPIO_SSPI_MOSI, // Software SPI Master Output Slave Input
|
||||
GPIO_SSPI_MISO, // Software SPI Master Input Client Output
|
||||
GPIO_SSPI_MOSI, // Software SPI Master Output Client Input
|
||||
GPIO_SSPI_SCLK, // Software SPI Serial Clock
|
||||
GPIO_SSPI_CS, // Software SPI Chip Select
|
||||
GPIO_SSPI_DC, // Software SPI Data or Command
|
||||
@ -210,10 +210,10 @@ enum UserSelectablePins {
|
||||
GPIO_SM2135_DAT, // SM2135 Dat
|
||||
GPIO_DEEPSLEEP, // Kill switch for deepsleep
|
||||
GPIO_EXS_ENABLE, // EXS MCU Enable
|
||||
GPIO_TASMOTASLAVE_TXD, // Slave TX
|
||||
GPIO_TASMOTASLAVE_RXD, // Slave RX
|
||||
GPIO_TASMOTASLAVE_RST, // Slave Reset Pin
|
||||
GPIO_TASMOTASLAVE_RST_INV, // Slave Reset Inverted
|
||||
GPIO_TASMOTACLIENT_TXD, // Client TX
|
||||
GPIO_TASMOTACLIENT_RXD, // Client RX
|
||||
GPIO_TASMOTACLIENT_RST, // Client Reset Pin
|
||||
GPIO_TASMOTACLIENT_RST_INV, // Client Reset Inverted
|
||||
GPIO_HPMA_RX, // Honeywell HPMA115S0 Serial interface
|
||||
GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
|
||||
GPIO_GPS_RX, // GPS serial interface
|
||||
@ -238,6 +238,7 @@ enum UserSelectablePins {
|
||||
GPIO_TCP_RX, // TCP Serial bridge
|
||||
GPIO_TELEINFO_RX, // TELEINFO serial interface
|
||||
GPIO_TELEINFO_ENABLE,// TELEINFO Enable PIN
|
||||
GPIO_LMT01, // LMT01 input counting pin
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality
|
||||
@ -316,7 +317,7 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
|
||||
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
|
||||
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_GPS_RX "|" D_SENSOR_GPS_TX "|"
|
||||
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_BOILER_OT_RX "|" D_SENSOR_BOILER_OT_TX "|"
|
||||
D_SENSOR_WINDMETER_SPEED "|"
|
||||
D_SENSOR_BL0940_RX "|"
|
||||
D_SENSOR_BL0940_RX "|"
|
||||
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 =
|
||||
@ -430,8 +432,8 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
||||
#ifdef USE_SPI
|
||||
GPIO_SPI_CS, // SPI Chip Select
|
||||
GPIO_SPI_DC, // SPI Data Direction
|
||||
GPIO_SSPI_MISO, // Software SPI Master Input Slave Output
|
||||
GPIO_SSPI_MOSI, // Software SPI Master Output Slave Input
|
||||
GPIO_SSPI_MISO, // Software SPI Master Input Client Output
|
||||
GPIO_SSPI_MOSI, // Software SPI Master Output Client Input
|
||||
GPIO_SSPI_SCLK, // Software SPI Serial Clock
|
||||
GPIO_SSPI_CS, // Software SPI Chip Select
|
||||
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_OUT, // Pseudo Single wire DS18B20 or DS18S20
|
||||
#endif
|
||||
#ifdef USE_LMT01 // LMT01, count pulses on GPIO
|
||||
GPIO_LMT01,
|
||||
#endif
|
||||
|
||||
// Light
|
||||
#ifdef USE_LIGHT
|
||||
@ -625,11 +630,11 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
||||
GPIO_PN532_TXD, // PN532 HSU Tx
|
||||
GPIO_PN532_RXD, // PN532 HSU Rx
|
||||
#endif
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
GPIO_TASMOTASLAVE_TXD, // Tasmota Slave TX
|
||||
GPIO_TASMOTASLAVE_RXD, // Tasmota Slave RX
|
||||
GPIO_TASMOTASLAVE_RST, // Tasmota Slave Reset
|
||||
GPIO_TASMOTASLAVE_RST_INV, // Tasmota Slave Reset Inverted
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
GPIO_TASMOTACLIENT_TXD, // Tasmota Client TX
|
||||
GPIO_TASMOTACLIENT_RXD, // Tasmota Client RX
|
||||
GPIO_TASMOTACLIENT_RST, // Tasmota Client Reset
|
||||
GPIO_TASMOTACLIENT_RST_INV, // Tasmota Client Reset Inverted
|
||||
#endif
|
||||
#ifdef USE_RDM6300
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
MAXMODULE};
|
||||
|
||||
@ -2264,10 +2269,8 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
||||
GPIO_LED1_INV, // GPIO13 WiFi Blue Led - Link and Power status
|
||||
0, 0, 0, 0
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // ESP8266
|
||||
|
||||
#ifdef ESP32
|
||||
|
@ -102,8 +102,8 @@ enum UserSelectablePins {
|
||||
GPIO_SM2135_CLK, GPIO_SM2135_DAT, // SM2135 PWM controller
|
||||
GPIO_DEEPSLEEP, // Kill switch for deepsleep
|
||||
GPIO_EXS_ENABLE, // EXS MCU Enable
|
||||
GPIO_TASMOTASLAVE_TXD, GPIO_TASMOTASLAVE_RXD, // Slave Serial interface
|
||||
GPIO_TASMOTASLAVE_RST, GPIO_TASMOTASLAVE_RST_INV, // Slave Reset
|
||||
GPIO_TASMOTACLIENT_TXD, GPIO_TASMOTACLIENT_RXD, // Client Serial interface
|
||||
GPIO_TASMOTACLIENT_RST, GPIO_TASMOTACLIENT_RST_INV, // Client Reset
|
||||
GPIO_HPMA_RX, GPIO_HPMA_TX, // Honeywell HPMA115S0 Serial interface
|
||||
GPIO_GPS_RX, GPIO_GPS_TX, // GPS 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_TELEINFO_RX, // Teleinfo telemetry data receive pin
|
||||
GPIO_TELEINFO_ENABLE, // Teleinfo Enable Receive Pin
|
||||
GPIO_LMT01, // LMT01 input counting pin
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
enum ProgramSelectablePins {
|
||||
@ -199,7 +200,7 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_DDSU666_TX "|" D_SENSOR_DDSU666_RX "|"
|
||||
D_SENSOR_SM2135_CLK "|" D_SENSOR_SM2135_DAT "|"
|
||||
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_GPS_RX "|" D_SENSOR_GPS_TX "|"
|
||||
D_SENSOR_HM10_RX "|" D_SENSOR_HM10_TX "|"
|
||||
@ -225,7 +226,8 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_BL0940_RX "|"
|
||||
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_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE
|
||||
D_SENSOR_TELEINFO_RX "|" D_SENSOR_TELEINFO_ENABLE "|"
|
||||
D_SENSOR_LMT01_PULSE
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
@ -269,8 +271,8 @@ const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
AGPIO(GPIO_SPI_CLK), // SPI Clk
|
||||
AGPIO(GPIO_SPI_CS), // SPI Chip Select
|
||||
AGPIO(GPIO_SPI_DC), // SPI Data Direction
|
||||
AGPIO(GPIO_SSPI_MISO), // Software SPI Master Input Slave Output
|
||||
AGPIO(GPIO_SSPI_MOSI), // Software SPI Master Output Slave Input
|
||||
AGPIO(GPIO_SSPI_MISO), // Software SPI Master Input Client Output
|
||||
AGPIO(GPIO_SSPI_MOSI), // Software SPI Master Output Client Input
|
||||
AGPIO(GPIO_SSPI_SCLK), // Software SPI Serial Clock
|
||||
AGPIO(GPIO_SSPI_CS), // Software SPI Chip Select
|
||||
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_OUT), // Pseudo Single wire DS18B20 or DS18S20
|
||||
#endif
|
||||
#ifdef USE_LMT01
|
||||
AGPIO(GPIO_LMT01), // LMT01, count pulses on GPIO
|
||||
#endif
|
||||
|
||||
// Light
|
||||
#ifdef USE_LIGHT
|
||||
@ -468,11 +473,11 @@ const uint16_t kGpioNiceList[] PROGMEM = {
|
||||
AGPIO(GPIO_PN532_TXD), // PN532 HSU Tx
|
||||
AGPIO(GPIO_PN532_RXD), // PN532 HSU Rx
|
||||
#endif
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
AGPIO(GPIO_TASMOTASLAVE_TXD), // Tasmota Slave TX
|
||||
AGPIO(GPIO_TASMOTASLAVE_RXD), // Tasmota Slave RX
|
||||
AGPIO(GPIO_TASMOTASLAVE_RST), // Tasmota Slave Reset
|
||||
AGPIO(GPIO_TASMOTASLAVE_RST_INV), // Tasmota Slave Reset Inverted
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
AGPIO(GPIO_TASMOTACLIENT_TXD), // Tasmota Client TX
|
||||
AGPIO(GPIO_TASMOTACLIENT_RXD), // Tasmota Client RX
|
||||
AGPIO(GPIO_TASMOTACLIENT_RST), // Tasmota Client Reset
|
||||
AGPIO(GPIO_TASMOTACLIENT_RST_INV), // Tasmota Client Reset Inverted
|
||||
#endif
|
||||
#ifdef USE_RDM6300
|
||||
AGPIO(GPIO_RDM6300_RX),
|
||||
@ -622,20 +627,14 @@ typedef struct MYTMPLT {
|
||||
|
||||
/********************************************************************************************/
|
||||
// Supported hardware modules
|
||||
enum SupportedModules {
|
||||
WEMOS, ESP32_CAM_AITHINKER,
|
||||
MAXMODULE};
|
||||
enum SupportedModules { WEMOS, ESP32_CAM_AITHINKER, MAXMODULE };
|
||||
|
||||
#define USER_MODULE 255
|
||||
|
||||
const char kModuleNames[] PROGMEM =
|
||||
"ESP32-DevKit|ESP32 Cam AiThinker";
|
||||
const char kModuleNames[] PROGMEM = "ESP32-DevKit|ESP32 Cam AiThinker";
|
||||
|
||||
// Default module settings
|
||||
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
|
||||
WEMOS,
|
||||
ESP32_CAM_AITHINKER
|
||||
};
|
||||
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { WEMOS, ESP32_CAM_AITHINKER };
|
||||
|
||||
const mytmplt kModules PROGMEM =
|
||||
{ // WEMOS - Espressif ESP32-DevKitC - Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
|
||||
@ -685,12 +684,12 @@ const mytmplt kModules PROGMEM =
|
||||
/*********************************************************************************************\
|
||||
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":"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":"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":[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 // _TASMOTA_TEMPLATE_ESP32_H_
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef _TASMOTA_VERSION_H_
|
||||
#define _TASMOTA_VERSION_H_
|
||||
|
||||
const uint32_t VERSION = 0x08030105;
|
||||
const uint32_t VERSION = 0x08030106;
|
||||
|
||||
// Lowest compatible version
|
||||
const uint32_t VERSION_COMPATIBLE = 0x07010006;
|
||||
|
@ -44,7 +44,7 @@ const uint16_t HTTP_OTA_RESTART_RECONNECT_TIME = 28000; // milliseconds - Allow
|
||||
uint8_t *efm8bb1_update = nullptr;
|
||||
#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", };
|
||||
|
||||
@ -2022,8 +2022,8 @@ void ModuleSaveSettings(void)
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
const char kUnescapeCode[] = "&><\"\'";
|
||||
const char kEscapeCode[] PROGMEM = "&|>|<|"|'";
|
||||
const char kUnescapeCode[] = "&><\"\'\\";
|
||||
const char kEscapeCode[] PROGMEM = "&|>|<|"|'|\";
|
||||
|
||||
String HtmlEscape(const String unescaped) {
|
||||
char escaped[10];
|
||||
@ -2327,22 +2327,6 @@ void OtherSaveSettings(void)
|
||||
}
|
||||
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));
|
||||
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" : "");
|
||||
@ -2489,7 +2473,7 @@ void HandleInformation(void)
|
||||
#endif
|
||||
if (Settings.flag4.network_wifi) {
|
||||
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" : "");
|
||||
#if LWIP_IPV6
|
||||
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_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" D_MAC_ADDRESS "}2%s"), WiFi.softAPmacAddress().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(HTTP_MSG_RSTRT);
|
||||
ShowWebSource(SRC_WEBGUI);
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
if (TasmotaSlave_GetFlagFlashing()) {
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
if (TasmotaClient_GetFlagFlashing()) {
|
||||
restart_flag = 0;
|
||||
} else { // It was a normal firmware file, or we are ready to restart device
|
||||
restart_flag = 2;
|
||||
@ -2681,9 +2665,9 @@ void HandleUploadDone(void)
|
||||
WSContentSend_P(PSTR("</div><br>"));
|
||||
WSContentSpaceButton(BUTTON_MAIN);
|
||||
WSContentStop();
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
if (TasmotaSlave_GetFlagFlashing()) {
|
||||
TasmotaSlave_Flash();
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
if (TasmotaClient_GetFlagFlashing()) {
|
||||
TasmotaClient_Flash();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -2753,11 +2737,11 @@ void HandleUploadLoop(void)
|
||||
if (Web.upload_error != 0) { return; }
|
||||
} else
|
||||
#endif // USE_RF_FLASH
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO SLAVE hex file
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
if ((WEMOS == my_module_type) && (upload.buf[0] == ':')) { // Check if this is a ARDUINO CLIENT hex file
|
||||
Update.end(); // End esp8266 update session
|
||||
Web.upload_file_type = UPL_TASMOTASLAVE;
|
||||
Web.upload_error = TasmotaSlave_UpdateInit(); // 0
|
||||
Web.upload_file_type = UPL_TASMOTACLIENT;
|
||||
Web.upload_error = TasmotaClient_UpdateInit(); // 0
|
||||
if (Web.upload_error != 0) { return; }
|
||||
} else
|
||||
#endif
|
||||
@ -2821,9 +2805,9 @@ void HandleUploadLoop(void)
|
||||
}
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
else if (UPL_TASMOTASLAVE == Web.upload_file_type) {
|
||||
TasmotaSlave_WriteBuffer(upload.buf, upload.currentSize);
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
|
||||
TasmotaClient_WriteBuffer(upload.buf, upload.currentSize);
|
||||
}
|
||||
#endif
|
||||
else { // firmware
|
||||
@ -2887,10 +2871,10 @@ void HandleUploadLoop(void)
|
||||
Web.upload_file_type = UPL_TASMOTA;
|
||||
}
|
||||
#endif // USE_RF_FLASH
|
||||
#ifdef USE_TASMOTA_SLAVE
|
||||
else if (UPL_TASMOTASLAVE == Web.upload_file_type) {
|
||||
#ifdef USE_TASMOTA_CLIENT
|
||||
else if (UPL_TASMOTACLIENT == Web.upload_file_type) {
|
||||
// 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;
|
||||
}
|
||||
#endif
|
||||
|
@ -397,7 +397,7 @@ void ScriptEverySecond(void) {
|
||||
|
||||
if (bitRead(Settings.rule_enabled, 0)) {
|
||||
struct T_INDEX *vtp=glob_script_mem.type;
|
||||
float delta=(millis()-script_lastmillis)/1000;
|
||||
float delta=(millis()-script_lastmillis)/1000.0;
|
||||
script_lastmillis=millis();
|
||||
for (uint8_t count=0; count<glob_script_mem.numvars; count++) {
|
||||
if (vtp[count].bits.is_timer) {
|
||||
|
@ -114,6 +114,7 @@ device_parameters_t device_param[] = {
|
||||
{ KNX_SLOT3 , false, false, KNX_Empty },
|
||||
{ KNX_SLOT4 , false, false, KNX_Empty },
|
||||
{ KNX_SLOT5 , false, false, KNX_Empty },
|
||||
{ KNX_SCENE , 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 " 4",
|
||||
D_KNX_TX_SLOT " 5",
|
||||
D_KNX_TX_SCENE ,
|
||||
nullptr
|
||||
};
|
||||
|
||||
@ -184,6 +186,7 @@ const char *device_param_cb[] = {
|
||||
D_KNX_RX_SLOT " 3",
|
||||
D_KNX_RX_SLOT " 4",
|
||||
D_KNX_RX_SLOT " 5",
|
||||
D_KNX_RX_SCENE ,
|
||||
nullptr
|
||||
};
|
||||
|
||||
@ -196,12 +199,14 @@ const char *device_param_cb[] = {
|
||||
#define D_CMND_KNX_PA "_PA"
|
||||
#define D_CMND_KNX_GA "_GA"
|
||||
#define D_CMND_KNX_CB "_CB"
|
||||
#define D_CMND_KNXTXSCENE "Tx_Scene"
|
||||
|
||||
|
||||
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 = {
|
||||
&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 )
|
||||
{
|
||||
@ -518,6 +523,7 @@ void KNX_INIT(void)
|
||||
device_param[KNX_SLOT3-1].show = true;
|
||||
device_param[KNX_SLOT4-1].show = true;
|
||||
device_param[KNX_SLOT5-1].show = true;
|
||||
device_param[KNX_SCENE-1].show = true;
|
||||
#endif
|
||||
|
||||
// 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) {
|
||||
// COMMAND
|
||||
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
|
||||
float tempvar = knx.data_to_2byte_float(msg.data);
|
||||
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
|
||||
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)
|
||||
{
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||
|
@ -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_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_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 =
|
||||
"||||"
|
||||
"VA|%|A|Cm|Hz|%|LX|"
|
||||
"%|ppd|ppd|ppd|ppd|ppd|ppd|µg/m³|µg/m³|µg/m³|Cos φ|W| |"
|
||||
"VAr|kWh|kWh|V|Kg|kWh|"
|
||||
"ppm|ppm|ppb|";
|
||||
"ppm|ppm|ppb|R|G|B|" D_UNIT_KELVIN "| |LX|";
|
||||
|
||||
const char kHAssJsonSensorDevCla[] PROGMEM =
|
||||
"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: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|"
|
||||
"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|"
|
||||
// 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 =
|
||||
"{\"name\":\"%s\"," // dualr2 1
|
||||
"\"stat_t\":\"%s\"," // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",")
|
||||
"\"avty_t\":\"%s\"," // tele/dualr2/LWT
|
||||
"\"pl_avail\":\"" D_ONLINE "\"," // Online
|
||||
"\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline
|
||||
"{\"name\":\"%s\"," // dualr2 1
|
||||
"\"stat_t\":\"%s\""; // stat/dualr2/RESULT (implies "\"optimistic\":\"false\",")
|
||||
|
||||
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_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 =
|
||||
",\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2
|
||||
"\"val_tpl\":\"{{value_json.%s}}\"," // POWER2
|
||||
"\"pl_off\":\"%s\"," // OFF
|
||||
"\"pl_on\":\"%s\""; // ON
|
||||
",\"cmd_t\":\"%s\"," // cmnd/dualr2/POWER2
|
||||
"\"val_tpl\":\"{{value_json.%s}}\"," // POWER2
|
||||
"\"pl_off\":\"%s\"," // OFF
|
||||
"\"pl_on\":\"%s\""; // ON
|
||||
|
||||
const char HASS_DISCOVER_BIN_SWITCH[] PROGMEM =
|
||||
",\"val_tpl\":\"{{value_json.%s}}\"," // STATE
|
||||
"\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work
|
||||
"\"pl_on\":\"%s\"," // ON
|
||||
"\"pl_off\":\"%s\""; // OFF
|
||||
",\"val_tpl\":\"{{value_json.%s}}\"," // STATE
|
||||
"\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work
|
||||
"\"pl_on\":\"%s\"," // ON
|
||||
"\"pl_off\":\"%s\""; // OFF
|
||||
|
||||
const char HASS_DISCOVER_BIN_PIR[] PROGMEM =
|
||||
",\"val_tpl\":\"{{value_json.%s}}\"," // STATE
|
||||
"\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work
|
||||
"\"pl_on\":\"%s\"," // ON
|
||||
"\"off_dly\":1"; // Switchmode13 and Switchmode14 doesn't transmit an OFF state.
|
||||
",\"val_tpl\":\"{{value_json.%s}}\"," // STATE
|
||||
"\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work
|
||||
"\"pl_on\":\"%s\"," // ON
|
||||
"\"off_dly\":1"; // Switchmode13 and Switchmode14 doesn't transmit an OFF state.
|
||||
|
||||
const char HASS_DISCOVER_BASE_LIGHT[] PROGMEM =
|
||||
",\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer
|
||||
"\"bri_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
"\"bri_scl\":100," // 100%
|
||||
"\"on_cmd_type\":\"%s\"," // power on (first), power on (last), no power on (brightness)
|
||||
",\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer
|
||||
"\"bri_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
"\"bri_scl\":100," // 100%
|
||||
"\"on_cmd_type\":\"%s\"," // power on (first), power on (last), no power on (brightness)
|
||||
"\"bri_val_tpl\":\"{{value_json.%s}}\"";
|
||||
|
||||
const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM =
|
||||
",\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2
|
||||
"\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
",\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2
|
||||
"\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
"\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\"";
|
||||
|
||||
const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM =
|
||||
",\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White
|
||||
"\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
",\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White
|
||||
"\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
"\"whit_val_scl\":100,"
|
||||
"\"whit_val_tpl\":\"{{value_json.Channel[3]}}\"";
|
||||
|
||||
const char HASS_DISCOVER_LIGHT_CT[] PROGMEM =
|
||||
",\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT
|
||||
"\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
",\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT
|
||||
"\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT
|
||||
"\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\"";
|
||||
|
||||
const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM =
|
||||
@ -141,7 +144,7 @@ const char kHAssTriggerStringButtons[] PROGMEM =
|
||||
"|SINGLE|DOUBLE|TRIPLE|QUAD|PENTA|HOLD|";
|
||||
|
||||
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 =
|
||||
"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 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 TuyaMod = false; // Controls Tuya MCU modules
|
||||
bool PwmMod = false; // Controls PWM_DIMMER module
|
||||
bool FanMod = false; // Controls SONOFF_IFAN0X modules
|
||||
|
||||
uint8_t dimmer = 1;
|
||||
uint8_t valid_relay = 0;
|
||||
uint8_t max_lights = 1;
|
||||
uint8_t TuyaRel = 0;
|
||||
uint8_t TuyaRelInv = 0;
|
||||
uint8_t TuyaDim = 0;
|
||||
|
||||
#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
|
||||
|
||||
// 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 (!LightControl) {
|
||||
ind_light = 1;
|
||||
ind_light = true;
|
||||
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++)
|
||||
{
|
||||
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
|
||||
|
||||
// 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(state_topic, TELE, mqtt_topic, D_RSLT_STATE);
|
||||
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_DEVICE_INFO_SHORT, unique_id, ESP_getChipId());
|
||||
|
||||
#ifdef USE_LIGHT
|
||||
if (i >= Light.device) {
|
||||
if (!RelayX || PwmMod) {
|
||||
if (!RelayX || PwmMod || (TuyaDim > 0 && TuyaMod)) {
|
||||
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
|
||||
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_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("}"));
|
||||
}
|
||||
}
|
||||
@ -505,7 +530,7 @@ void HAssAnnounceButtons(void)
|
||||
{
|
||||
button_present = 1;
|
||||
} else
|
||||
#endif
|
||||
#endif // ESP8266
|
||||
{
|
||||
if (PinUsed(GPIO_KEY1, button_index)) {
|
||||
button_present = 1;
|
||||
@ -557,12 +582,21 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const
|
||||
char prefix[TOPSZ];
|
||||
char *state_topic = stemp1;
|
||||
char *availability_topic = stemp2;
|
||||
//bool LwtSensor = MQTT_LWT_DISCOVERY;
|
||||
|
||||
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);
|
||||
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());
|
||||
|
||||
|
||||
@ -629,8 +663,8 @@ void HAssAnnounceSensors(void)
|
||||
sensordata[0] = '{';
|
||||
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
|
||||
//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;
|
||||
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(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_DEVICE_INFO, unique_id, ESP_getChipId(), SettingsText(SET_DEVICENAME),
|
||||
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\","
|
||||
"\"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(),
|
||||
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);
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE));
|
||||
}
|
||||
@ -812,7 +847,6 @@ void HAssAnyKey(void)
|
||||
bool Xdrv12(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (Settings.flag.mqtt_enabled)
|
||||
{ // SetOption3 - Enable MQTT
|
||||
switch (function)
|
||||
@ -844,10 +878,13 @@ bool Xdrv12(uint8_t function)
|
||||
case FUNC_MQTT_INIT:
|
||||
hass_mode = 0; // Discovery only if Settings.flag.hass_discovery is set
|
||||
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;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_HOME_ASSISTANT
|
||||
#endif // USE_HOME_ASSISTANT
|
@ -19,6 +19,13 @@
|
||||
|
||||
#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
|
||||
|
||||
typedef uint64_t Z_IEEEAddress;
|
||||
@ -26,6 +33,7 @@ typedef uint16_t Z_ShortAddress;
|
||||
|
||||
const uint16_t BAD_SHORTADDR = 0xFFFE;
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
enum ZnpCommandType {
|
||||
Z_POLL = 0x00,
|
||||
Z_SREQ = 0x20,
|
||||
@ -45,6 +53,7 @@ enum ZnpSubsystem {
|
||||
Z_DEBUG = 0x08,
|
||||
Z_APP = 0x09
|
||||
};
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
|
||||
// Commands in the SYS subsystem
|
||||
enum SysCommand {
|
||||
|
@ -168,6 +168,8 @@ SBuffer *zigbee_buffer = nullptr;
|
||||
|
||||
#define USE_ZIGBEE_CHANNEL_MASK (1 << (USE_ZIGBEE_CHANNEL))
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
|
||||
// ZBS_* Zigbee Send
|
||||
// ZBR_* Zigbee Recv
|
||||
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)
|
||||
};
|
||||
|
||||
#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)
|
||||
if (instr >= ZGB_INSTR_12_BYTES) {
|
||||
return 3;
|
||||
@ -770,7 +796,9 @@ void ZigbeeStateMachine_Run(void) {
|
||||
}
|
||||
break;
|
||||
case ZGB_INSTR_SEND:
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
ZigbeeZNPSend((uint8_t*) cur_ptr1, cur_d8 /* len */);
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
break;
|
||||
case ZGB_INSTR_WAIT_UNTIL:
|
||||
zigbee.recv_until = true; // and reuse ZGB_INSTR_WAIT_RECV
|
||||
|
@ -552,6 +552,7 @@ int32_t Z_MgmtBindRsp(int32_t res, const class SBuffer &buf) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
/*********************************************************************************************\
|
||||
* Send specific ZNP messages
|
||||
\*********************************************************************************************/
|
||||
@ -589,6 +590,32 @@ void Z_SendAFInfoRequest(uint16_t shortaddr) {
|
||||
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
|
||||
@ -718,6 +745,8 @@ typedef struct Z_Dispatcher {
|
||||
ZB_RecvMsgFunc func;
|
||||
} Z_Dispatcher;
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
|
||||
// Ffilters based on ZNP frames
|
||||
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
|
||||
@ -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
|
||||
\*********************************************************************************************/
|
||||
|
@ -21,18 +21,32 @@
|
||||
|
||||
#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 uint8_t ZIGBEE_SOF = 0xFE;
|
||||
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>
|
||||
TasmotaSerial *ZigbeeSerial = nullptr;
|
||||
|
||||
|
||||
const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix
|
||||
D_CMND_ZIGBEEZNPSEND "|" D_CMND_ZIGBEE_PERMITJOIN "|"
|
||||
D_CMND_ZIGBEE_STATUS "|" D_CMND_ZIGBEE_RESET "|" D_CMND_ZIGBEE_SEND "|"
|
||||
D_CMND_ZIGBEE_PROBE "|" D_CMND_ZIGBEEZNPRECEIVE "|"
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
D_CMND_ZIGBEEZNPSEND "|" 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_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 "|"
|
||||
@ -40,9 +54,14 @@ const char kZbCommands[] PROGMEM = D_PRFX_ZB "|" // prefix
|
||||
;
|
||||
|
||||
void (* const ZigbeeCommand[])(void) PROGMEM = {
|
||||
&CmndZbZNPSend, &CmndZbPermitJoin,
|
||||
&CmndZbStatus, &CmndZbReset, &CmndZbSend,
|
||||
&CmndZbProbe, &CmndZbZNPReceive,
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
&CmndZbZNPSend, &CmndZbZNPReceive,
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
#ifdef USE_ZIGBEE_EZSP
|
||||
&CmndZbEZSPSend, &CmndZbEZSPReceive,
|
||||
#endif // USE_ZIGBEE_EZSP
|
||||
&CmndZbPermitJoin,
|
||||
&CmndZbStatus, &CmndZbReset, &CmndZbSend, &CmndZbProbe,
|
||||
&CmndZbForget, &CmndZbSave, &CmndZbName,
|
||||
&CmndZbBind, &CmndZbUnbind, &CmndZbPing, &CmndZbModelId,
|
||||
&CmndZbLight, &CmndZbRestore, &CmndZbBindState,
|
||||
@ -52,11 +71,12 @@ void (* const ZigbeeCommand[])(void) PROGMEM = {
|
||||
//
|
||||
// Called at event loop, checks for incoming data from the CC2530
|
||||
//
|
||||
void ZigbeeInputLoop(void)
|
||||
{
|
||||
static uint32_t zigbee_polling_window = 0;
|
||||
void ZigbeeInputLoop(void) {
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
static uint32_t zigbee_polling_window = 0; // number of milliseconds since first byte
|
||||
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:
|
||||
// 00 - SOF = 0xFE
|
||||
// 01 - Length of Data Field - 0..250
|
||||
@ -140,6 +160,127 @@ void ZigbeeInputLoop(void)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
// Do a factory reset of the CC2530
|
||||
const unsigned char ZIGBEE_FACTORY_RESET[] PROGMEM =
|
||||
{ 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) {
|
||||
if (ZigbeeSerial) {
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 1:
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
ZigbeeZNPSend(ZIGBEE_FACTORY_RESET, sizeof(ZIGBEE_FACTORY_RESET));
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
eraseZigbeeDevices();
|
||||
restart_flag = 2;
|
||||
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`
|
||||
// building the complete message (intro, length)
|
||||
@ -264,36 +442,138 @@ void CmndZbZNPSend(void)
|
||||
CmndZbZNPSendOrReceive(true);
|
||||
}
|
||||
|
||||
void ZigbeeZNPSend(const uint8_t *msg, size_t len) {
|
||||
if ((len < 2) || (len > 252)) {
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
|
||||
#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
|
||||
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;
|
||||
}
|
||||
uint8_t data_len = len - 2; // removing CMD1 and CMD2
|
||||
|
||||
if (ZigbeeSerial) {
|
||||
uint8_t fcs = data_len;
|
||||
if (send_cancel) {
|
||||
ZigbeeSerial->write(ZIGBEE_EZSP_CANCEL); // 0x1A
|
||||
}
|
||||
|
||||
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);
|
||||
bool data_frame = (0 == (msg[0] & 0x80));
|
||||
uint8_t rand = 0x42; // pseudo-randomizer initial value
|
||||
uint16_t crc = 0xFFFF; // CRC16 CCITT initialization
|
||||
|
||||
for (uint32_t i=0; i<len; i++) {
|
||||
uint8_t out_byte = msg[i];
|
||||
|
||||
// apply randomization if DATA field
|
||||
if (data_frame && (i > 0)) {
|
||||
out_byte ^= rand;
|
||||
if (rand & 1) { rand = (rand >> 1) ^ 0xB8; }
|
||||
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
|
||||
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)));
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
// 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) {
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
SBuffer buf(32+len);
|
||||
buf.add8(Z_SREQ | Z_AF); // 24
|
||||
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());
|
||||
#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("Missing \"ToDevice\" or \"ToGroup\"")); return; }
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
SBuffer buf(34);
|
||||
buf.add8(Z_SREQ | Z_ZDO);
|
||||
if (unbind) {
|
||||
@ -935,6 +1218,7 @@ void ZbBindUnbind(bool unbind) { // false = bind, true = unbind
|
||||
}
|
||||
|
||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
|
||||
ResponseCmndDone();
|
||||
}
|
||||
@ -961,6 +1245,7 @@ void CmndZbBindState(void) {
|
||||
uint16_t shortaddr = zigbee_devices.parseDeviceParam(XdrvMailbox.data);
|
||||
if (BAD_SHORTADDR == shortaddr) { ResponseCmndChar_P(PSTR("Unknown device")); return; }
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
SBuffer buf(10);
|
||||
buf.add8(Z_SREQ | Z_ZDO); // 25
|
||||
buf.add8(ZDO_MGMT_BIND_REQ); // 33
|
||||
@ -968,6 +1253,7 @@ void CmndZbBindState(void) {
|
||||
buf.add8(0); // StartIndex = 0
|
||||
|
||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
|
||||
ResponseCmndDone();
|
||||
}
|
||||
@ -1191,6 +1477,7 @@ void CmndZbPermitJoin(void) {
|
||||
duration = 0xFF; // unlimited time
|
||||
}
|
||||
|
||||
#ifdef USE_ZIGBEE_ZNP
|
||||
SBuffer buf(34);
|
||||
buf.add8(Z_SREQ | Z_ZDO); // 25
|
||||
buf.add8(ZDO_MGMT_PERMIT_JOIN_REQ); // 36
|
||||
@ -1200,6 +1487,7 @@ void CmndZbPermitJoin(void) {
|
||||
buf.add8(0x00); // TCSignificance
|
||||
|
||||
ZigbeeZNPSend(buf.getBuffer(), buf.len());
|
||||
#endif // USE_ZIGBEE_ZNP
|
||||
|
||||
ResponseCmndDone();
|
||||
}
|
||||
|
585
tasmota/xdrv_31_tasmota_client.ino
Normal file
585
tasmota/xdrv_31_tasmota_client.ino
Normal 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
|
@ -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
|
@ -322,7 +322,7 @@ String TelegramExecuteCommand(const char *svalue) {
|
||||
}
|
||||
|
||||
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) {
|
||||
case 0:
|
||||
TelegramInit();
|
||||
|
@ -23,7 +23,7 @@
|
||||
* 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
|
||||
* {"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:
|
||||
* WcStream = Control streaming, 0 = stop, 1 = start
|
||||
@ -792,7 +792,7 @@ void HandleWebcamRoot(void) {
|
||||
/*********************************************************************************************/
|
||||
|
||||
uint32_t WcSetStreamserver(uint32_t flag) {
|
||||
if (global_state.wifi_down) { return 0; }
|
||||
if (global_state.network_down) { return 0; }
|
||||
|
||||
Wc.stream_active = 0;
|
||||
|
||||
|
@ -31,7 +31,8 @@
|
||||
* GPIO26 - EMAC_RXD1(RMII)
|
||||
* 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
|
||||
|
||||
#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
|
||||
|
||||
#ifndef ETH_CLKMODE
|
||||
@ -57,36 +58,22 @@
|
||||
#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>
|
||||
|
||||
struct {
|
||||
char hostname[33];
|
||||
} Eth;
|
||||
char eth_hostname[sizeof(my_hostname)];
|
||||
|
||||
void EthernetEvent(WiFiEvent_t event) {
|
||||
switch (event) {
|
||||
case SYSTEM_EVENT_ETH_START:
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: " D_ATTEMPTING_CONNECTION));
|
||||
ETH.setHostname(Eth.hostname);
|
||||
ETH.setHostname(eth_hostname);
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_CONNECTED:
|
||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("ETH: " D_CONNECTED));
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_GOT_IP:
|
||||
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()) {
|
||||
Serial.print(", FULL_DUPLEX");
|
||||
@ -95,6 +82,9 @@ void EthernetEvent(WiFiEvent_t event) {
|
||||
Serial.print(ETH.linkSpeed());
|
||||
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;
|
||||
break;
|
||||
case SYSTEM_EVENT_ETH_DISCONNECTED:
|
||||
@ -112,13 +102,20 @@ void EthernetEvent(WiFiEvent_t event) {
|
||||
|
||||
void EthernetInit(void) {
|
||||
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);
|
||||
|
||||
int eth_power = (PinUsed(GPIO_ETH_PHY_POWER)) ? Pin(GPIO_ETH_PHY_POWER) : ETH_POWER_PIN;
|
||||
int eth_mdc = (PinUsed(GPIO_ETH_PHY_MDC)) ? Pin(GPIO_ETH_PHY_MDC) : ETH_MDC_PIN;
|
||||
int eth_mdio = (PinUsed(GPIO_ETH_PHY_MDIO)) ? Pin(GPIO_ETH_PHY_MDIO) : ETH_MDIO_PIN;
|
||||
int eth_power = (PinUsed(GPIO_ETH_PHY_POWER)) ? Pin(GPIO_ETH_PHY_POWER) : -1;
|
||||
int eth_mdc = Pin(GPIO_ETH_PHY_MDC);
|
||||
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)) {
|
||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("ETH: Bad PHY type or init error"));
|
||||
};
|
||||
@ -129,7 +126,7 @@ IPAddress EthernetLocalIP(void) {
|
||||
}
|
||||
|
||||
char* EthernetHostname(void) {
|
||||
return Eth.hostname;
|
||||
return eth_hostname;
|
||||
}
|
||||
|
||||
String EthernetMacAddress(void) {
|
||||
@ -170,7 +167,7 @@ void CmndEthAddress(void)
|
||||
|
||||
void CmndEthType(void)
|
||||
{
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
|
||||
Settings.eth_type = XdrvMailbox.payload;
|
||||
restart_flag = 2;
|
||||
}
|
||||
|
@ -127,15 +127,15 @@ void FifLEEvery250ms(void)
|
||||
} else {
|
||||
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:
|
||||
// 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 B0 FB 87 = REG[B3..B2=0xA01E,B1..B0=0xA01F] 176 = 1.76 kvarh
|
||||
// U16/S16 registers:
|
||||
// 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 03 E8 B8 FA = REG[B1..B0=0x0158] 1000 = 1.000 (power factor)
|
||||
// there are 3 data types used:
|
||||
|
@ -26,7 +26,7 @@
|
||||
* 2. Configure the module to use I2C on the correct 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.
|
||||
* 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
|
||||
* 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.
|
||||
@ -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.
|
||||
* It will map device numbers as follows:
|
||||
*
|
||||
* Device number to I2C slave address mapping
|
||||
* Device number to I2C address mapping
|
||||
*
|
||||
* 1 - 0x40
|
||||
* 2 - 0x41
|
||||
@ -59,7 +59,7 @@
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
@ -88,13 +88,13 @@
|
||||
#define INA226_REG_CALIBRATION (0x05)
|
||||
|
||||
|
||||
typedef struct Ina226SlaveInfo_tag {
|
||||
typedef struct Ina226Info_tag {
|
||||
uint8_t address;
|
||||
uint16_t calibrationValue;
|
||||
uint16_t config;
|
||||
uint8_t present : 1;
|
||||
float i_lsb;
|
||||
} Ina226SlaveInfo_t;
|
||||
} Ina226Info_t;
|
||||
|
||||
/*
|
||||
* Program memory constants
|
||||
@ -108,9 +108,9 @@ static const uint8_t PROGMEM probeAddresses[INA226_MAX_ADDRESSES] = {INA226_ADDR
|
||||
|
||||
|
||||
static char Ina226Str[] = "INA226";
|
||||
static uint8_t slavesFound = 0;
|
||||
static uint8_t Ina226sFound = 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 float voltages[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
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
@ -167,10 +167,10 @@ bool Ina226TestPresence(uint8_t device)
|
||||
|
||||
// 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);
|
||||
|
||||
if (config != slaveInfo[device].config)
|
||||
if (config != Ina226Info[device].config)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -179,10 +179,10 @@ bool Ina226TestPresence(uint8_t device)
|
||||
|
||||
void Ina226ResetActive(void)
|
||||
{
|
||||
Ina226SlaveInfo_t *p = slaveInfo;
|
||||
Ina226Info_t *p = Ina226Info;
|
||||
|
||||
for (uint32_t i = 0; i < INA226_MAX_ADDRESSES; i++) {
|
||||
p = &slaveInfo[i];
|
||||
p = &Ina226Info[i];
|
||||
// Address
|
||||
uint8_t addr = p->address;
|
||||
if (addr) {
|
||||
@ -199,9 +199,9 @@ void Ina226Init()
|
||||
{
|
||||
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, "Size of Settings: %d bytes", sizeof(Settings));
|
||||
@ -210,7 +210,7 @@ void Ina226Init()
|
||||
// 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++){
|
||||
*p = {0};
|
||||
@ -232,7 +232,7 @@ void Ina226Init()
|
||||
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
|
||||
|
||||
@ -257,8 +257,8 @@ void Ina226Init()
|
||||
if (!I2cWrite16( addr, INA226_REG_CONFIG, config))
|
||||
continue; // No device
|
||||
|
||||
// store data in slave info struct.
|
||||
p = &slaveInfo[i];
|
||||
// store data in info struct.
|
||||
p = &Ina226Info[i];
|
||||
// Address
|
||||
p->address = addr;
|
||||
// Configuration
|
||||
@ -282,7 +282,7 @@ void Ina226Init()
|
||||
|
||||
I2cSetActiveFound(addr, Ina226Str);
|
||||
|
||||
slavesFound++;
|
||||
Ina226sFound++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -292,7 +292,7 @@ void Ina226Init()
|
||||
|
||||
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);
|
||||
|
||||
float result = ((float) reg_bus_v) * 0.00125f;
|
||||
@ -307,10 +307,10 @@ float Ina226ReadBus_v(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);
|
||||
|
||||
float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb;
|
||||
float result = ((float) reg_shunt_i) * Ina226Info[device].i_lsb;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -321,10 +321,10 @@ float Ina226ReadShunt_i(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);
|
||||
|
||||
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;
|
||||
}
|
||||
@ -354,19 +354,19 @@ void Ina226EverySecond()
|
||||
{
|
||||
//AddLog_P2( LOG_LEVEL_NONE, "Ina226EverySecond");
|
||||
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 (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){
|
||||
// If there are Ina226s, and the device was present, and the device still is present, read its registers
|
||||
if (Ina226sFound && Ina226Info[device].present && Ina226TestPresence(device)){
|
||||
Ina226Read(device);
|
||||
}
|
||||
else {
|
||||
powers[device] = currents[device] = voltages[device] = 0.0f;
|
||||
// If device was present, note that it dropped off here
|
||||
//if(slaveInfo[device].present){
|
||||
//if(Ina226Info[device].present){
|
||||
//reinit_count[device]++;
|
||||
//AddLog_P2( LOG_LEVEL_DEBUG, "INA226 Device %d dropped off, count: %d", device, reinit_count[device]);
|
||||
//}
|
||||
// Device no longer present
|
||||
slaveInfo[device].present = false;
|
||||
Ina226Info[device].present = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -413,7 +413,7 @@ bool Ina226CommandSensor()
|
||||
case 1: // Rerun init
|
||||
Ina226ResetActive();
|
||||
Ina226Init();
|
||||
Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound);
|
||||
Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Ina226sFound\":%d}}"),Ina226sFound);
|
||||
break;
|
||||
|
||||
case 2: // Save and restart
|
||||
@ -497,7 +497,7 @@ void Ina226Show(bool json)
|
||||
int i, num_found;
|
||||
for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) {
|
||||
// Skip uninstalled sensors
|
||||
if (!slaveInfo[i].present)
|
||||
if (!Ina226Info[i].present)
|
||||
continue;
|
||||
|
||||
num_found++;
|
||||
|
@ -21,6 +21,8 @@
|
||||
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,
|
||||
simple beacon
|
||||
---
|
||||
@ -62,6 +64,7 @@
|
||||
#define XSNS_61 61
|
||||
|
||||
#include <vector>
|
||||
#include <mbedtls/ccm.h>
|
||||
|
||||
#define FLORA 1
|
||||
#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[] 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
|
||||
CMND_NRF_IGNORE, // ignore specific sensor type (1-6)
|
||||
CMND_NRF_PAGE, // sensor entries per web page, which will be shown alternated
|
||||
CMND_NRF_SCAN, // simplified passive BLE adv scan
|
||||
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
|
||||
@ -104,8 +108,8 @@ const char * kMINRFSlaveType[] PROGMEM = {kMINRFSlaveType1,kMINRFSlaveType2,kMIN
|
||||
const uint32_t kMINRFFloPDU[3] = {0x3eaa857d,0xef3b8730,0x71da7b46};
|
||||
const uint32_t kMINRFMJPDU[3] = {0x4760cd66,0xdbcc0cd3,0x33048df5};
|
||||
const uint32_t kMINRFL2PDU[3] = {0x3eaa057d,0xef3b0730,0x71dafb46};
|
||||
// const uint32_t kMINRFL3PDU[3] = {0x4760dd78,0xdbcc1ccd,0xffffffff}; //encrypted - 58 58
|
||||
const uint32_t kMINRFL3PDU[3] = {0x4760cb78,0xdbcc0acd,0x33048beb}; //unencrypted - 30 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 kMINRFCGGPDU[3] = {0x4760cd6e,0xdbcc0cdb,0x33048dfd};
|
||||
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];
|
||||
};
|
||||
|
||||
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{
|
||||
bleAdvPacket_t bleAdv;
|
||||
mi_beacon_t miBeacon;
|
||||
@ -223,6 +249,7 @@ struct scan_entry_t {
|
||||
|
||||
std::vector<mi_sensor_t> MIBLEsensors;
|
||||
std::vector<scan_entry_t> MINRFscanResult;
|
||||
std::vector<mi_bindKey_t> MIBLEbindKeys;
|
||||
|
||||
static union{
|
||||
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
|
||||
\*********************************************************************************************/
|
||||
@ -581,6 +663,46 @@ void MINRFreverseMAC(uint8_t _mac[]){
|
||||
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
|
||||
*
|
||||
@ -754,14 +876,19 @@ void MINRFhandleMiBeaconPacket(void){
|
||||
uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.Mac, MINRF.buffer.miBeacon.productID);
|
||||
if(_slot==0xff) return;
|
||||
DEBUG_SENSOR_LOG(PSTR("MINRF: slot %u, size vector: %u %u"),_slot,MIBLEsensors.size());
|
||||
|
||||
mi_sensor_t *_sensorVec = &MIBLEsensors.at(_slot);
|
||||
DEBUG_SENSOR_LOG(PSTR("MINRF: %u %u %u"),_slot,_sensorVec->type,MINRF.buffer.miBeacon.type);
|
||||
float _tempFloat;
|
||||
|
||||
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((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);
|
||||
switch(MINRF.buffer.miBeacon.type){
|
||||
@ -823,21 +950,6 @@ void MINRFhandleMiBeaconPacket(void){
|
||||
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
|
||||
@ -901,12 +1013,9 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds
|
||||
}
|
||||
else MINRFhandleScan();
|
||||
break;
|
||||
case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1:
|
||||
case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1: case LYWSD03:
|
||||
MINRFhandleMiBeaconPacket();
|
||||
break;
|
||||
case LYWSD03:
|
||||
MINRFhandleLYWSD03Packet();
|
||||
break;
|
||||
case CGD1:
|
||||
MINRFhandleCGD1Packet();
|
||||
break;
|
||||
@ -1026,6 +1135,12 @@ bool NRFCmd(void) {
|
||||
}
|
||||
Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.channelIgnore);
|
||||
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:
|
||||
// else for Unknown command
|
||||
serviced = false;
|
||||
@ -1191,5 +1306,3 @@ bool Xsns61(uint8_t function)
|
||||
#endif // USE_MIBLE
|
||||
#endif // USE_NRF24
|
||||
#endif // USE_SPI
|
||||
|
||||
|
||||
|
142
tasmota/xsns_74_lmt01.ino
Normal file
142
tasmota/xsns_74_lmt01.ino
Normal 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
|
@ -206,7 +206,7 @@ a_features = [[
|
||||
"USE_IAQ","USE_DISPLAY_SEVENSEG","USE_AS3935","USE_PING",
|
||||
"USE_WINDMETER","USE_OPENTHERM","USE_THERMOSTAT","USE_VEML6075",
|
||||
"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"
|
||||
@ -243,7 +243,7 @@ else:
|
||||
obj = json.load(fp)
|
||||
|
||||
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))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user