Merge branch 'development' into pre-release

This commit is contained in:
Theo Arends 2020-04-11 14:51:32 +02:00
commit b5512b6d13
95 changed files with 3540 additions and 691 deletions

View File

@ -1,132 +0,0 @@
# Device Groups
The device groups module provides a framework to allow multiple devices to be in a group with values such as power, light color/temperature/brightness, PWM values, sensor values, etc. shared with other devices in the group. For example, with multiple light modules in a device group, the light settings can be changed on one module and the settings will automatically be changed on the other light modules. Dimmer switch modules could be in a device group with light modules and the dimmer switch could control the power, brightness and colors of all the lights in the group. Multiple dimmer switches could be in a device group to form a 3-way/4-way dimmer switch.
UDP multicasts, followed by UDP unicasts if necessary, are used to send updates to all devices so updates are fast. There is no need for an MQTT server but all the devices in a group must be on the same IP network.
To include device groups support in the build, define USE_DEVICE_GROUPS in your user_config_override. This adds 3.5K to the code size. All devices in a group must be running firmware with device group support and have device groups enabled.
To enable device groups, execute the command SetOption85 1.
## Device Groups Operation
The device group name is set with the DevGroupName command. If the device group name is not set for a group, the MQTT group topic is used (with the device group number appended for device group numbers > 1). All devices in the same IP network with the same device group name are in the same group. Some modules may define additional device groups. For example, if Remote Device Mode is enabled, the PWM Dimmer module defines three devices groups.
The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change it’s brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 0xffffffff (all items) on the dimmer switch (DevGroupShare 0xffffffff,0xffffffff) and set the incoming item mask to 0xffffffff and outgoing item mask to 0 on all the lights (DevGroupShare 0xffffffff,0).
### Commands
<table>
<tr>
<td><strong>Command</strong>
</td>
<td><strong>Parameters</strong>
</td>
</tr>
<tr>
<td>DevGroupName&lt;x>
</td>
<td>0 = clear device group &lt;x> name and restart<br>
&lt;value> = set device group &lt;x> name and restart
</td>
</tr>
</tr>
<tr>
<td>DevGroupSend&lt;x>
</td>
<td>&lt;item>=&lt;value>[ ...] = send an update to device grouup &lt;x>. The device group name must have been previously set with DevGroupName&lt;x>. Multiple items/value pairs can be specified separated by a space. For example, DevGroupSend 4=90 128=1 will send an update to set the light brightness to 90 and turn relay 1 on.<br>
<br>
For items with numeric values, &lt;value> can be specified as @&lt;operator>&lt;value> to send a value after performing an operation on the current value. &lt;operator> can be + (add), - (subtract) or ^ (invert). If a value is not specified for the invert operator, 0xffffffff is used. For example, if the group's current light brightness is 40, DevGroupSend 4=@10 will send an update to increase the light brightness to 50. If all the groups relays are currently on, DevGroupSend 128=^ will turn all the relays off.<br><br>
<table>
<tr>
<td><strong>Item</strong>
</td>
<td><strong>Description</strong>
</td>
<td><strong>Value</strong>
</td>
</tr>
<tr>
<td>2
</td>
<td>Light fade
</td>
<td>0 = Off<br>1 = On
</tr>
<tr>
<td>3
</td>
<td>Light speed
</td>
<td>1..40
</tr>
<tr>
<td>4
</td>
<td>Light brightness
</td>
<td>0..255
</tr>
<tr>
<td>5
</td>
<td>Light scheme
</td>
<td>See Scheme command in <a href="https://tasmota.github.io/docs/Commands/#light">Light Commands</a>
</tr>
<tr>
<td>6
</td>
<td>Light fixed color
</td>
<td>0 = white (using CT channels), 1 = red, 2 = green, 3 = blue, 4 = orange, 5 = light green, 6 = light blue, 7 = amber, 8 = cyan, 9 = purple, 10 = yellow, 11 = pink, 12 = white (using RGB channels)
</tr>
<tr>
<td>7
</td>
<td>PWM dimmer low preset
</td>
<td>0..255
</tr>
<tr>
<td>8
</td>
<td>PWM dimmer high preset
</td>
<td>0..255
</tr>
<tr>
<td>9
</td>
<td>PWM dimmer power-on brightness
</td>
<td>0..255
</tr>
<tr>
<td>128
</td>
<td>Relay Power
</td>
<td>Bitmask with bits set for relays to be powered on. The number of relays can be specified in bits 24 - 31. If the number of relays is not specified, only relay 1 is set.
</tr>
<tr>
<td>224
</td>
<td>Light channels
</td>
<td>Comma separated list of brightness levels (0..255) for channels 1 - 5 (e.g. 255,128,0,0,0 will turn the red channel on at 100% and the green channel on at 50% on an RBG light).
</tr>
</table>
</td>
</tr>
</tr>
<tr>
<td>DevGroupShare
</td>
<td>&lt;in>,&lt;out> = set incoming and outgoing shared item mask (default = 0xffffffff,0xffffffff)<br>
1 = Power, 2 = Light brightness, 4 = Light fade/speed, 8 = Light scheme, 16 = Light color, 32 = Dimmer settings (presets)
</td>
</table>

46
ESP32README.md Normal file
View File

@ -0,0 +1,46 @@
![Tasmota logo](/tools/logo/TASMOTA_FullLogo_Vector.svg)
## ESP32 port with minimal changes
## Description:
This is my esp32 port, i try to make only minimal changes to the original source code
from Theo Arends, now again for development branch.
## Checklist:
- [x] The pull request is done against the latest dev branch
- [x] Only relevant files were touched
- [x] Only one feature/fix was added per PR.
- [x] The code change is tested and works on core Tasmota_core_stage
- [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass**
- [x] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
- [x] i checked binary "tasmota.bin" to be the same in development and development_esp32 branch
Here are the main things i have done
- in "lib_extra_dirs" i have libesp32 directory for things missing in ESP32 framework
my "ESP32-to-ESP8266-compat" has all files that are not available in ESP32
so you dont have to change the source code and i write code to get the informations from ESP32
- all librarys that are not compatibel i add to lib_ignore
- all code that is not for ESP32 i put in "#ifdef ESP8266" the define is from espessif platform
- all code for ESP32 is in "#ifdef ESP32"
- SerConfu8 type uint8_t for SerialConfig list
- changed "HTTP_HEADER" to "HTTP_HEADER1", in ESP32 its an enum
- for ip adress 0 i used IPAddress(0,0,0,0)
- Special ESP.xxx call i change to ESP_xxx (ESP_rtcUserMemoryWrite, ...) and write macros for ESP8266
- because ESP32 has only WEMOS 32 modul, i exclude all code like this:
"if (SONOFF_xxx == Settings.module)" in "#ifdef ESP8266"
- variable "sleep" i changed to "ssleep" because of standard library sleep(..) function
- all esp32 stuff is in support_esp32.ino
- in tasmota.ino i include "tasmota_compat.h"
- in tasmota_template.h i use ifdef and tasmota_templESP32.h
- defines for sensors that currently don't work, i undef in tasmota_templESP32.h
- comment fo "no warnig" in "xdrv_20_hue.ino" thats the only warning i had
Build info
Copy platformio_override_esp32.ini to platformio_override.ini an select your imagetype.
You can build tasmota and tasmota32 Version with one build.
If you need other versions change platformio_override.ini
stay at home, have fun and keep good
Jörg

View File

@ -67,3 +67,6 @@ Index | Define | Driver | Device | Address(es) | Description
43 | USE_AHT1x | xsns_63 | AHT10/15 | 0x38 | Temperature and humidity sensor
44 | USE_WEMOS_MOTOR_V1 | xdrv_34 | | 0x2D - 0x30 | WEMOS motor shield v1.0.0 (6612FNG)
45 | USE_HDC1080 | xsns_65 | HDC1080 | 0x40 | Temperature and Humidity sensor
46 | USE_IAQ | xsns_66 | IAQ | 0x5a | Air quality sensor
47 | USE_DISPLAY_SEVENSEG| xdsp_11 | HT16K33 | 0x70 - 0x77 | Seven segment LED
48 | USE_AS3935 | xsns_67 | AS3935 | 0x03 | Franklin Lightning Sensor

View File

@ -1,94 +0,0 @@
# PWM Dimmer
The PWM Dimmer module adds support for Martin Jerry/acenx/Tessan/NTONPOWER SD0x PWM dimmer switches. The brightness of the load for these dimmers is controlled by a PWM GPIO pin. They typically have power, up and down buttons, a powered-on LED, five brightness LEDs and another status LED. Examples are:[ https://www.amazon.com/dp/B07FXYSVR1](https://www.amazon.com/dp/B07FXYSVR1),[ https://www.amazon.com/dp/B07V26Q3VD](https://www.amazon.com/dp/B07V26Q3VD),[ https://www.amazon.com/dp/B07K67D43J](https://www.amazon.com/dp/B07K67D43J),[ https://www.amazon.com/dp/B07TTGFWFM](https://www.amazon.com/dp/B07TTGFWFM)
To include PWM dimmer support in the build, define USE_PWM_DIMMER in your user_config_override. This adds 4.5K to the code size. The light module is not required for PWM dimmer operation so you can #undef USE_LIGHT to reduce the firmware bin size.
To enable PWM dimmer operation, select the PWM Dimmer module.
## PWM Dimmer Operation
Pressing and releasing the power button toggles the power on/off. If the toggle turns the power on, the load is returned to the last brightness it was adjusted to. If Fade is enabled, the load is faded on/off at the rate defined by the Speed setting.
When the power is on, holding the down or up button decreases/increases the brightness. The brightness can also be changed using just the power button. When the power is on, holding the power button alternately increases or decreases the brightness. Initially, holding the power button increases the brightness. Releasing and then holding the power button again decreases the brightness.
When the power is off, pressing and releasing the down or up button turns the power on at a temporary brightness of the low/high levels set by the DimmerPreset command. Turning the power on at the low preset can also be accomplished by holding the power button while the power is off. The dimmer presets are intended to enable quickly turning on a light to a dim or bright level without changing the normal desired brightness. Turning the power on to a preset does not change the brightness the load will be set to when the switch is turned on the next time. For example, if the light is on and you adjust the brightness to 80 and then turn the light off, when you turn it back on, the brightness will return to 80. If you turn the power off again and then press the down button, the light will be turned on with a brightness of the low preset. If you then turn the light off and on again, the brightness will return to 80.
When the power is off, holding the down or up button publishes an MQTT EVENT command. The topic follows the format of the Full Topic with a prefix of Event (ex. cmnd/LightSwitch1/EVENT). The MQTT payload is Trigger#, where # is 1 if the down button is held or 2 if the up button is held. These triggers can be used in rules on remote devices (ON Event#Trigger1) or by automation software to trigger automations such as scene changes. For example, the Event topic Trigger1 payload could trigger the automation software to turn on the previous scene in a list and the Trigger2 payload could trigger the automation software to turn on the next scene in a list.
If there are LEDs defined in the template, they are turned on to indicate the current brightness. More LEDs are turned on at higher brightnesses. The LedTimeout command enables/disables an LED timeout. If LED timeout is enabled, the LEDs turn off five seconds after the last change in brightness. Note that the lowest LED and the blue power LED are always on when the power is on. The LED timeout can also be enabled/disabled by holding the power button while tapping (pressing and releasing quickly) the down button.
The LEDLink LED can be used as a nightlight/powered-off indicator. The PoweredOffLed command enables/disables turning the LEDLink LED on when the power is off. The powered-off indicator can also be enabled/disabled by holding the power button and tapping the up button.
Holding the power button, tapping the down button and then tapping or holding the down or up button sends a device group message to set RGB lights in the device group to the previous/next fixed color. The command is sent/value is adjusted once every .5 seconds for as long as the button is held. The color sequence as defined by the Light module is red, green, blue, orange, light green, light blue, amber, cyan, purple, yellow, pink, white using RGB channels, white using CT channels.
Holding the power button, tapping the up button and then tapping or holding the down or up button publishes an MQTT Event command. The command is sent/value is adjusted once every .5 seconds for as long as the button is held. The MQTT topic is as described above. The MQTT payload is Trigger#, where # is 3 if the down button is held or 4 if the up button is held.
Holding any button alone for over 10 seconds executes the WiFiConfig 2 command.
SetOption32 defines the button hold time. When the PWM Dimmer module is initially selected, SetOption32 is set to 5 (1/2 second). Button presses and holds execute the normal ButtonTopic and Rule processing. If ButtonTopic is set and SetOption61 is 0 or a the button press/hold matches a rule, the button press/hold is ignored by PWM Dimmer.
When Device Groups are enabled, the PWM Dimmer brightness presets are kept in sync across all switches in the group. The powered-off LED and LED timeout settings are specific to each switch. Changing them does not replicate the change to the other switches in the group.
### Commands
<table>
<tr>
<td><strong>Command</strong>
</td>
<td><strong>Parameters</strong>
</td>
</tr>
<tr>
<td>BriPreset
</td>
<td> &lt;low>,&lt;high> = set brightness low and high presets<br>
1..255 = set brightness preset<br>
+ = increase brightness preset<br>
- = decrease brightness preset
</td>
</tr>
<tr>
<td>SetOption86
</td>
<td>Set brightness LED timeout<br>
0 = disable timeout (default)<br>
1 = enable timeout
</td>
</tr>
<tr>
<td>SetOption87
</td>
<td>Set powered-off LED (nightlight)<br>
0 = disable powered-off LED (default)<br>
1 = enable powered-off LED
</td>
</tr>
<tr>
<td>SetOption88
</td>
<td>Set remote device mode<br>
0 = disable remote device mode(default)<br>
1 = enable remote device mode
</td>
</tr>
</table>
### Remote Device Mode
Remote device mode allows PWM Dimmer switches to control remote devices. With remote device mode enabled, each button controls a different device. Note that dimmer switches with toggle-style down/up buttons have limited functionality as remote device mode switches because you can not push the down and up buttons simultaneously.
To include remote device mode support in the build, define USE_PWM_DIMMER_REMOTE in your user_config_override. Remote device mode support requires device group support so USE_DEVICE_GROUPS is automatically defined if USE_PWM_DIMMER_REMOTE is defined. Remote device mode support adds 1.2K to the code size in addition to the code size required for device groups support.
To enable remote device mode, execute the command SetOption88 1 (the device will restart). Each remote device must be running firmware with device group support and have remote device support enabled. The remote devices do not need to be built with PWM dimmer support nor do they need to be switches.
If a remote device is a PWM dimmer, the device acts like a 3-way dimmer switch would and may or may not have a load connected to it. Its also possible to use a PWM dimmer switch without a load to act as a wall switch to control the power, brightness and color of one or more smart lights with Tasmota with device group support loaded on them.
With remote device mode is enabled, button 1 is the power button for the local device while buttons 2 and 3 are the power buttons for remote devices. Group names for buttons 2 and 3 are set by the GroupTopic2 and GroupTopic3 commands respectively. Note that the button numbers are defined by the module template and can be in any physical order on the switch (button 1 can be defined as the top button, the middle button or the bottom button). Button combinations that publish MQTT Event commands use a topic in the format cmnd/%group-topic%/EVENT.
Pressing and releasing a power button toggles the power on all devices in the group assigned to the button. When the power is on, holding the button alternately increases or decreases the brightness. When the power is off, holding the button turns the power on at a temporary brightness of the low level set by the BriPreset command.
While holding a power button, the other two buttons act like the down and up buttons for the remote device. All the functions performed by the down and up buttons in non-remote device mode are available in remote device mode. While holding button 1, button 2 performs the functions of the down button and button 3 performs the functions of the up button. While holding button 2, button 1 performs the functions of the down button and button 3 performs the functions of the up button. While holding button 3, button 1 performs the functions of the down button and button 2 performs the functions of the up button.

View File

@ -75,10 +75,14 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Add command ``Sensor10 31..254`` to control BH1750 measurement time which defaults to 69 (#8016)
- Add command ``DevGroupName`` to specify up to four Device Group Names (#8087)
- Add command ``DevGroupSend`` to send an update to a Device Group (#8093)
- Add command ``Ping`` (#7176)
- Add support for unreachable (unplugged) Zigbee devices in Philips Hue emulation and Alexa
- Add support for 64x48 SSD1306 OLED (#6740)
- Add support for Seven Segment display using HT16K33 (#8116)
- Add support for up to four MQTT GroupTopics (#8014)
- Add console command history (#7483, #8015)
- Add support for longer template names
- Add support for an iAQ sensor (#8107)
- Add support for AS3935 Lightning Sensor by device111 (#8130)
- Add console command history (#7483, #8015)
- Add quick wifi reconnect using saved AP parameters when ``SetOption56 0`` (#3189)
- Add more accuracy to GPS NTP server (#8088)

View File

@ -24,6 +24,8 @@ SOFTWARE.
#include <twi.h>
#include <FrogmoreScd30.h>
#ifdef ESP8266
#define COMMAND_SCD30_CONTINUOUS_MEASUREMENT 0x0010
#define COMMAND_SCD30_MEASUREMENT_INTERVAL 0x4600
#define COMMAND_SCD30_GET_DATA_READY 0x0202
@ -253,7 +255,7 @@ int FrogmoreScd30::get16BitRegCheckCRC(void* pInput, uint16_t *pData)
}
// gets 32 bits, (2) 16-bit chunks, and validates the CRCs
//
//
int FrogmoreScd30::get32BitRegCheckCRC(void *pInput, float *pData)
{
uint16_t tempU16High;
@ -458,7 +460,7 @@ int FrogmoreScd30::setTemperatureOffset(float offset_degC)
{
return (ERROR_SCD30_INVALID_VALUE);
}
}
int FrogmoreScd30::setTemperatureOffset(uint16_t offset_centiDegC)
@ -568,7 +570,7 @@ int FrogmoreScd30::readMeasurement(
return (error);
}
error = get32BitRegCheckCRC(&bytes[12], &tempHumidity);
error = get32BitRegCheckCRC(&bytes[12], &tempHumidity);
if (error)
{
#ifdef SCD30_DEBUG
@ -651,3 +653,4 @@ int FrogmoreScd30::stopMeasuring(void)
return (sendCommand(COMMAND_SCD30_STOP_MEASUREMENT));
}
#endif // ESP8266

View File

@ -150,9 +150,11 @@ bool TasmotaSerial::begin(long speed, int stop_bits) {
} else {
Serial.begin(speed, SERIAL_8N1);
}
#ifdef ESP8266
if (m_hardswap) {
Serial.swap();
}
#endif // ESP8266
} else {
// Use getCycleCount() loop to get as exact timing as possible
m_bit_time = ESP.getCpuFreqMHz() * 1000000 / speed;

View File

@ -2584,6 +2584,9 @@ br_cpuid(uint32_t mask_eax, uint32_t mask_ebx,
#define optimistic_yield(ignored)
#endif
#ifdef ESP32
#define memcpy_P memcpy
#endif
/* ==================================================================== */

View File

@ -68,8 +68,8 @@ public:
int16_t width;
int16_t height;
Epd();
~Epd();
// Epd();
// ~Epd();
int Init(const unsigned char* lut);
void Init(int8_t p);
void SendCommand(unsigned char command);

View File

@ -0,0 +1,19 @@
Library for ESP32 with Tasmota
This Class is for compatibility with esp8266 code
== License ==
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

View File

@ -0,0 +1,24 @@
#######################################
# Syntax Coloring Map For Test
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
A4988_ESP32Compat KEYWORD1 A4988_ESP32Compat
#######################################
# Methods and Functions (KEYWORD2)
#######################################
doMove KEYWORD2
doRotate KEYWORD2
setRPM KEYWORD2
setSPR KEYWORD2
setMIS KEYWORD2
version KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -0,0 +1,9 @@
name=ESP32-to-ESP8266-compat
version=0.0.2
author=Jörg Schüler-Maroldt
maintainer=Jörg Schüler-Maroldt <schueler-maoldt@arcor.de>
sentence=Allows Tasmota to compile for esp32
paragraph=Allows Tasmota to compile for esp32
category=ESP32
url=
architectures=*

View File

@ -0,0 +1,233 @@
/*
AddrList.h - cycle through lwIP netif's ip addresses like a c++ list
Copyright (c) 2018 david gauchard. 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
*/
/*
This class allows to explore all configured IP addresses
in lwIP netifs, with that kind of c++ loop:
for (auto a: addrList)
out.printf("IF='%s' index=%d legacy=%d IPv4=%d local=%d hostname='%s' addr= %s\n",
a.iface().c_str(),
a.ifnumber(),
a.addr().isLegacy(),
a.addr().isV4(),
a.addr().isLocal(),
a.hostname().c_str(),
a.addr().toString().c_str());
This loop:
while (WiFi.status() != WL_CONNECTED()) {
Serial.print('.');
delay(500);
}
can be replaced by:
for (bool configured = false; !configured; ) {
for (auto iface: addrList)
if ((configured = !iface.addr().isLocal())
break;
Serial.print('.');
delay(500);
}
waiting for an IPv6 global address:
for (bool configured = false; !configured; ) {
for (auto iface: addrList)
if ((configured = ( !iface.addr().isV4()
&& !iface.addr().isLocal())))
break;
Serial.print('.');
delay(500);
}
waiting for an IPv6 global address, on a specific interface:
for (bool configured = false; !configured; ) {
for (auto iface: addrList)
if ((configured = ( !iface.addr().isV4()
&& !iface.addr().isLocal()
&& iface.ifnumber() == STATION_IF)))
break;
Serial.print('.');
delay(500);
}
*/
#ifndef __ADDRLIST_H
#define __ADDRLIST_H
#include <IPAddress.h>
#include <lwip/netif.h>
#if LWIP_IPV6
#define IF_NUM_ADDRESSES (1 + LWIP_IPV6_NUM_ADDRESSES)
#else
#define IF_NUM_ADDRESSES (1)
#endif
namespace esp8266
{
namespace AddressListImplementation
{
struct netifWrapper
{
netifWrapper (netif* netif) : _netif(netif), _num(-1) {}
netifWrapper (const netifWrapper& o) : _netif(o._netif), _num(o._num) {}
netifWrapper& operator= (const netifWrapper& o)
{
_netif = o._netif;
_num = o._num;
return *this;
}
bool equal(const netifWrapper& o)
{
return _netif == o._netif && (!_netif || _num == o._num);
}
// address properties
class IPAddress4 : public IPAddress
{
public:
bool isV6() const
{
return false;
}
bool isLocal() const
{
return false;
}
};
IPAddress4 addr () const { return ipFromNetifNum(); }
bool isLegacy () const { return _num == 0; }
//bool isLocal () const { return addr().isLocal(); }
bool isV4 () const { return addr().isV4(); }
bool isV6 () const { return !addr().isV4(); }
String toString() const { return addr().toString(); }
// related to legacy address (_num=0, ipv4)
IPAddress ipv4 () const { return _netif->ip_addr; }
IPAddress netmask () const { return _netif->netmask; }
IPAddress gw () const { return _netif->gw; }
// common to all addresses of this interface
String ifname () const { return String(_netif->name[0]) + _netif->name[1]; }
const char* ifhostname () const { return _netif->hostname?: emptyString.c_str(); }
const char* ifmac () const { return (const char*)_netif->hwaddr; }
int ifnumber () const { return _netif->num; }
bool ifUp () const { return !!(_netif->flags & NETIF_FLAG_UP); }
const netif* interface () const { return _netif; }
const ip_addr_t* ipFromNetifNum () const
{
#if LWIP_IPV6
return _num ? &_netif->ip6_addr[_num - 1] : &_netif->ip_addr;
#else
return &_netif->ip_addr;
#endif
}
// lwIP interface
netif* _netif;
// address index within interface
// 0: legacy address (IPv4)
// n>0: (_num-1) is IPv6 index for netif->ip6_addr[]
int _num;
};
class AddressListIterator
{
public:
AddressListIterator (const netifWrapper& o) : netIf(o) {}
AddressListIterator (netif* netif) : netIf(netif)
{
// This constructor is called with lwIP's global netif_list, or
// nullptr. operator++() is designed to loop through _configured_
// addresses. That's why netIf's _num is initialized to -1 to allow
// returning the first usable address to AddressList::begin().
(void)operator++();
}
const netifWrapper& operator* () const { return netIf; }
const netifWrapper* operator-> () const { return &netIf; }
bool operator== (AddressListIterator& o) { return netIf.equal(*o); }
bool operator!= (AddressListIterator& o) { return !netIf.equal(*o); }
AddressListIterator operator++ (int)
{
AddressListIterator ret = *this;
(void)operator++();
return ret;
}
AddressListIterator& operator++ ()
{
while (netIf._netif)
{
if (++netIf._num == IF_NUM_ADDRESSES)
{
// all addresses from current interface were iterated,
// switching to next interface
netIf = netifWrapper(netIf._netif->next);
continue;
}
if (!ip_addr_isany(netIf.ipFromNetifNum()))
// found an initialized address
break;
}
return *this;
}
netifWrapper netIf;
};
class AddressList
{
public:
using const_iterator = const AddressListIterator;
const_iterator begin () const { return const_iterator(netif_list); }
const_iterator end () const { return const_iterator(nullptr); }
};
inline AddressList::const_iterator begin (const AddressList& a) { return a.begin(); }
inline AddressList::const_iterator end (const AddressList& a) { return a.end(); }
} // AddressListImplementation
} // esp8266
extern AddressList addrList;
#endif

View File

@ -0,0 +1,93 @@
/*
WiFi compat with ESP32
Copyright (C) 2020 Theo Arends / Jörg Schüler-Maroldt
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/>.
*/
//
#include "Arduino.h"
#include <ESP8266WiFi.h>
//
// Wifi
//
#ifdef WiFi
#undef WiFi
#endif
void WiFiClass32::setSleepMode(int iSleepMode)
{
// WIFI_MODEM_SLEEP
WiFi.setSleep(iSleepMode != WIFI_MODEM_SLEEP);
}
int WiFiClass32::getPhyMode()
{
return 0; // " BGN"
}
void WiFiClass32::wps_disable()
{
}
void WiFiClass32::setOutputPower(int n)
{
wifi_power_t p = WIFI_POWER_2dBm;
if (n > 19)
p = WIFI_POWER_19_5dBm;
else if (n > 18)
p = WIFI_POWER_18_5dBm;
else if (n >= 17)
p = WIFI_POWER_17dBm;
else if (n >= 15)
p = WIFI_POWER_15dBm;
else if (n >= 13)
p = WIFI_POWER_13dBm;
else if (n >= 11)
p = WIFI_POWER_11dBm;
else if (n >= 8)
p = WIFI_POWER_8_5dBm;
else if (n >= 7)
p = WIFI_POWER_7dBm;
else if (n >= 5)
p = WIFI_POWER_5dBm;
WiFi.setTxPower(p);
}
void WiFiClass32::forceSleepBegin()
{
}
void WiFiClass32::forceSleepWake()
{
}
bool WiFiClass32::getNetworkInfo(uint8_t i, String &ssid, uint8_t &encType, int32_t &rssi, uint8_t *&bssid, int32_t &channel, bool &hidden_scan)
{
hidden_scan = false;
return WiFi.getNetworkInfo(i, ssid, encType, rssi, bssid, channel);
}
void wifi_station_disconnect()
{
// erase ap: empty ssid, ...
WiFi.disconnect(true, true);
}
void wifi_station_dhcpc_start()
{
}
WiFiClass32 WiFi32;

View File

@ -0,0 +1,5 @@
//
// Compat with ESP32
//
#include <HTTPClient.h>

View File

@ -0,0 +1,19 @@
//
// Compat with ESP32
//
#pragma once
#include <WebServer.h>
//#define ESP8266WebServer WebServer
class ESP8266WebServer : public WebServer
{
public:
ESP8266WebServer(int port)
:WebServer(port)
{
}
};
//#define ENC_TYPE_AUTO 0

View File

@ -0,0 +1,85 @@
/*
WiFi compat with ESP32
Copyright (C) 2020 Theo Arends / Jörg Schüler-Maroldt
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/>.
*/
#pragma once
#include <WiFi.h>
// sorry, no <AddrList.h>
#undef LWIP_IPV6
#define ENC_TYPE_NONE WIFI_AUTH_OPEN
#define ENC_TYPE_WEP WIFI_AUTH_WEP
#define ENC_TYPE_CCMP WIFI_AUTH_WPA2_PSK
#define ENC_TYPE_TKIP WIFI_AUTH_WPA_WPA2_PSK
#define ENC_TYPE_AUTO WIFI_AUTH_MAX + 1
#define WIFI_LIGHT_SLEEP 1
#define WIFI_MODEM_SLEEP 2
class WiFiClass32 : public WiFiClass
{
public:
static void hostname(const char* aHostname)
{
WiFi.setHostname(aHostname);
}
static void setSleepMode(int iSleepMode);
static int getPhyMode();
static void wps_disable();
static void setOutputPower(int n);
static void forceSleepBegin();
static void forceSleepWake();
static bool getNetworkInfo(uint8_t i, String &ssid, uint8_t &encType, int32_t &rssi, uint8_t* &bssid, int32_t &channel, bool &hidden_scan);
};
void wifi_station_disconnect();
void wifi_station_dhcpc_start();
extern WiFiClass32 WiFi32;
#define WiFi WiFi32
class WiFiUDP32 : public WiFiUDP
{
public:
size_t write(const char*s)
{
return WiFiUDP::write((const uint8_t *)s, strlen(s));
}
size_t write(const uint8_t *buf, size_t n)
{
return WiFiUDP::write(buf, n);
}
static void stopAll()
{
}
static void forceSleepWake()
{
}
uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port)
{
return WiFiUDP::beginMulticast(multicast, port);
}
void beginPacketMulticast(IPAddress multicast, uint16_t port, IPAddress interfaceAddr)
{
}
};
#define WiFiUDP WiFiUDP32

View File

@ -0,0 +1,10 @@
//
// Compat with ESP32
//
#include <HTTPUpdate.h>
#define ESPhttpUpdate httpUpdate
inline HTTPUpdateResult ESPhttpUpdate_update(const String& url, const String& currentVersion = "")
{
return HTTP_UPDATE_OK;
}

View File

@ -0,0 +1,4 @@
//
// Compat with ESP32
//
#include <mDNS.h>

View File

@ -0,0 +1,6 @@
#pragma once
/**/
#include <stdint.h>
#ifndef ICACHE_FLASH_ATTR
#define ICACHE_FLASH_ATTR
#endif

View File

@ -0,0 +1,3 @@
//
// Compat with ESP32
//

View File

@ -0,0 +1,73 @@
/*
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//
#include "Arduino.h"
#include "lwip/apps/sntp.h"
#include <nvs.h>
#include <rom/rtc.h>
#include <ESP8266WiFi.h>
#include "esp8266toEsp32.h"
// ESP Stuff
struct rst_info resetInfo;
String ESP_getResetReason(void)
{
// CPU 0
return String(rtc_get_reset_reason(0));
}
String ESP_getResetInfo(void)
{
return String(PSTR("0"));
}
String ESP_getBootVersion(void)
{
return String(PSTR("Unknown"));
}
bool ESP_rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size)
{
return false;
}
bool ESP_rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size)
{
return false;
}
void ESP_reset()
{
ESP.restart();
}
uint32_t ESP_getFlashChipId()
{
return 0;
}
String String_ESP_getChipId()
{
uint64_t mac = ESP.getEfuseMac();
return String(uint32_t(mac >> 32)) + String(uint32_t(mac));
}
/*
uint64_t ESP_getChipId()
{
return ESP.getEfuseMac();
}
*/

View File

@ -0,0 +1,115 @@
/*
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This 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 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/>.
*/
#pragma once
#ifdef ESP32
// my debug Stuff
#define Serial_Debug1(p) Serial.printf p
#define Serial_DebugX(p)
//
// basics
//
// dummy defines
#define SPIFFS_END (SPI_FLASH_SEC_SIZE * 200)
#define SETTINGS_LOCATION SPIFFS_END
#include <Esp.h>
//
// ESP32
//
#define ESP_flashReadHeader(offset, data, size) ESP32_flashRead(offset, data, size)
#define ESP_flashRead(offset, data, size) ESP32_flashRead(offset, data, size)
String ESP_getResetReason(void);
String ESP_getBootVersion(void);
bool ESP_rtcUserMemoryWrite(uint32_t offset, uint32_t *data, size_t size);
bool ESP_rtcUserMemoryRead(uint32_t offset, uint32_t *data, size_t size);
void ESP_reset();
String ESP_getResetInfo(void);
uint32_t ESP_getFlashChipId();
String String_ESP_getChipId();
// Analog
inline void analogWrite(uint8_t pin, int val)
{
}
inline void analogWriteFreq(uint32_t freq)
{
}
inline void analogWriteRange(uint32_t range)
{
}
#define INPUT_PULLDOWN_16 INPUT_PULLUP
typedef double real64_t;
//
// Time and Timer
//
#define ETS_UART_INTR_DISABLE()
#define ETS_UART_INTR_ENABLE()
#define getChipId() getEfuseMac()
#define ESPhttpUpdate httpUpdate
#define getFlashChipRealSize() getFlashChipSize()
#define os_delay_us ets_delay_us
// Serial minimal type to hold the config
typedef int SerConfu8;
typedef int SerialConfig;
#define analogWrite(a, b)
//
// WS2812
//
#define NeoEsp8266BitBang800KbpsMethod NeoEsp32BitBang800KbpsMethod
//
// UDP
//
//#define PortUdp_writestr(log_data) PortUdp.write((const uint8_t *)(log_data), strlen(log_data))
#define PortUdp_write(log_data, n) PortUdp.write((const uint8_t *)(log_data), n)
//
#define wifi_forceSleepBegin()
#undef LWIP_IPV6
struct rst_info
{
int reason;
};
#define REASON_DEFAULT_RST 1
#define REASON_EXT_SYS_RST 2
#define REASON_DEEP_SLEEP_AWAKE 3
// memmove ...
#define memcpy_P memcpy
#define memmove_P memmove
#define strncpy_P strncpy
#define strcmp_P strcmp
#define memccpy_P memccpy
#define snprintf_P snprintf
#define sprintf_P sprintf
#define strncmp_P strncmp
// LWIP STuff
#define STATION_IF 0
#endif

View File

@ -0,0 +1,3 @@
#pragma once
#define timercallback void*
#define ets_printf(...)

View File

@ -0,0 +1,2 @@
#pragma once
#define GPIO_STATUS_W1TC_ADDRESS 0x24

View File

@ -0,0 +1,6 @@
#pragma once
#include "esp8266-compat.h"
#include <stdbool.h>
#include <stdint.h>
typedef uint16 uint16_t;
typedef double real64_t;

View File

@ -0,0 +1,8 @@
#pragma once
/**/
#include <lwip/ip_addr.h>
/*
#ifndef ICACHE_FLASH_ATTR
#define ICACHE_FLASH_ATTR
#endif
*/

View File

@ -0,0 +1,7 @@
#pragma once
#define sntp_get_current_timestamp() SntpGetCurrentTimestamp()
#define sntp_init() SntpInit()
#define sntp_set_timezone(tz)
#define sntp_setservername(idx, name)
#define sntp_stop()

View File

@ -0,0 +1,4 @@
//
// Compat with ESP32
//
// TODO: Port it to ESP32

View File

@ -0,0 +1,2 @@
#pragma once
/**/

View File

@ -0,0 +1,24 @@
/*
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef user_interface_h
#define user_interface_h
enum wps_cb_status {
WPS_CB_ST_SUCCESS = 0,
WPS_CB_ST_FAILED,
WPS_CB_ST_TIMEOUT,
WPS_CB_ST_WEP,
WPS_CB_ST_UNK,
};
#endif

View File

@ -0,0 +1,109 @@
;
; Example PlatformIO Project Configuration Override for ESP32 ***
; Changes done here override settings in platformio.ini ***
;
; to build Tasmota ESP32 copy to platformio_override.ini ***
;
; Please visit documentation for the options and examples
; http://docs.platformio.org/en/stable/projectconf.html
;
[platformio]
; *** Build/upload environment
;monitor_port = COM5
default_envs =
; *** Uncomment the line(s) below to select version(s)
tasmota
tasmota32
; tasmota32-minimal
; tasmota32-lite
; tasmota32-knx
; tasmota32-sensors
; tasmota32-display
; tasmota32-ir
; tasmota32-ircustom
; tasmota32-DE
; tasmota32-NL
[env32]
; uncomment this for all other tasmota32 builds
[env:tasmota32]
framework = ${common.framework}
platform = ${common32.platform}
platform_packages = ${common32.platform_packages}
board = ${common32.board}
board_build.ldscript = ${common32.board_build.ldscript}
board_build.flash_mode = ${common32.board_build.flash_mode}
board_build.f_cpu = ${common32.board_build.f_cpu}
build_unflags = ${common32.build_unflags}
build_flags = ${common32.build_flags}
monitor_speed = ${common32.monitor_speed}
upload_port = ${common32.upload_port}
upload_resetmethod = ${common32.upload_resetmethod}
upload_speed = ${common32.upload_speed}
extra_scripts = ${common32.extra_scripts}
lib_extra_dirs = ${common32.lib_extra_dirs}
lib_ignore = ${common32.lib_ignore}
; uncomment this for all other tasmota32 builds
;[env:tasmota32]
[env:tasmota32-minimal]
build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL
[env:tasmota32-lite]
build_flags = ${common.build_flags} -DFIRMWARE_LITE
[env:tasmota32-knx]
build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION
[env:tasmota32-sensors]
build_flags = ${common.build_flags} -DFIRMWARE_SENSORS
[env:tasmota32-display]
build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS
[env:tasmota32-ir]
build_flags = ${common.build_flags} ${irremoteesp8266_full.build_flags} -DFIRMWARE_IR
[env:tasmota32-ircustom]
build_flags = ${common.build_flags} ${irremoteesp8266_full.build_flags}
[env:tasmota32-DE]
build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE
[env:tasmota32-NL]
build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL
[common32]
platform = espressif32@1.12.0
platform_packages =
board = wemos_d1_mini32
board_build.ldscript = esp32_out.ld
board_build.flash_mode = ${common.board_build.flash_mode}
board_build.f_cpu = ${common.board_build.f_cpu}
build_unflags = ${common.build_unflags}
monitor_speed = ${common.monitor_speed}
upload_port = ${common.upload_port}
upload_resetmethod = ${common.upload_resetmethod}
upload_speed = 921600
extra_scripts = ${common.extra_scripts}
build_flags =
-D BUFFER_LENGTH=128
-D MQTT_MAX_PACKET_SIZE=1000
-D uint32=uint32_t
-D uint16=uint16_t
-D uint8=uint8_t
-D sint8_t=int8_t
-D sint32_t=int32_t
-D sint16_t=int16_t
-D memcpy_P=memcpy
-D memcmp_P=memcmp
; -D USE_CONFIG_OVERRIDE
lib_extra_dirs =
libesp32
lib_ignore =
ESP MQTT
TasmotaMqtt
ILI9488
RA8876
SSD3115
cc1101
FrogmoreScd30
ArduinoNTPd

View File

@ -25,8 +25,12 @@
- Add command ``SetOption41 <x>`` to force sending gratuitous ARP every <x> seconds
- Add command ``DevGroupName`` to specify up to four Device Group Names (#8087)
- Add command ``DevGroupSend`` to send an update to a Device Group (#8093)
- Add command ``Ping`` (#7176)
- Add quick wifi reconnect using saved AP parameters when ``SetOption56 0`` (#3189)
- Add more accuracy to GPS NTP server (#8088)
- Add support for an iAQ sensor (#8107)
- Add support for Seven Segment display using HT16K33 (#8116)
- Add support for AS3935 Lightning Sensor by device111 (#8130)
### 8.2.0.2 20200328

View File

@ -19,6 +19,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ESP8266
// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash
#include <core_version.h>
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
@ -109,3 +111,5 @@ void ICACHE_RAM_ATTR timer0_detachInterrupt(void) {
}
#endif // ARDUINO_ESP8266_RELEASE
#endif // ESP8266

View File

@ -37,6 +37,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ESP8266
#include <core_version.h>
#if defined(ARDUINO_ESP8266_RELEASE_2_6_1) || defined(ARDUINO_ESP8266_RELEASE_2_6_2) || defined(ARDUINO_ESP8266_RELEASE_2_6_3) || !defined(ARDUINO_ESP8266_RELEASE)
#warning **** Tasmota is using a patched PWM Arduino version as planned ****
@ -341,4 +343,6 @@ static ICACHE_RAM_ATTR void timer1Interrupt() {
};
#endif // ARDUINO_ESP8266_RELEASE
#endif // ARDUINO_ESP8266_RELEASE
#endif // ESP8266

View File

@ -19,6 +19,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ESP8266
// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash
#include <core_version.h>
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
@ -217,3 +219,5 @@ extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attrib
extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt")));
#endif // ARDUINO_ESP8266_RELEASE
#endif // ESP8266

View File

@ -19,6 +19,8 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef ESP8266
// Use PWM from core 2.4.0 as all versions below 2.5.0-beta3 produce LED flickering when settings are saved to flash
#include <core_version.h>
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
@ -232,3 +234,5 @@ extern void analogWriteFreq(uint32_t freq) __attribute__ ((weak, alias("__analog
extern void analogWriteRange(uint32_t range) __attribute__ ((weak, alias("__analogWriteRange")));
#endif // ARDUINO_ESP8266_RELEASE
#endif // ESP8266

View File

@ -63,6 +63,7 @@
#define D_JSON_ENERGY "Energy"
#define D_JSON_ERASE "Erase"
#define D_JSON_ERROR "Error"
#define D_JSON_EVENT "Event"
#define D_JSON_EVERY "Every"
#define D_JSON_EXPORT_ACTIVE "ExportActive"
#define D_JSON_EXPORT_REACTIVE "ExportReactive"
@ -535,10 +536,13 @@
#define D_PRFX_SHUTTER "Shutter"
#define D_CMND_SHUTTER_OPEN "Open"
#define D_CMND_SHUTTER_CLOSE "Close"
#define D_CMND_SHUTTER_TOGGLE "Toggle"
#define D_CMND_SHUTTER_UP "Up"
#define D_CMND_SHUTTER_DOWN "Down"
#define D_CMND_SHUTTER_TOGGLEUP "ToggleUp"
#define D_CMND_SHUTTER_TOGGLEDOWN "ToggleDown"
#define D_CMND_SHUTTER_STOPOPEN "StopOpen"
#define D_CMND_SHUTTER_STOPCLOSE "StopClose"
#define D_CMND_SHUTTER_STOPTOGGLE "StopToggle"
#define D_CMND_SHUTTER_STOPPOSITION "StopPosition"
#define D_CMND_SHUTTER_STOP "Stop"
#define D_CMND_SHUTTER_POSITION "Position"
#define D_CMND_SHUTTER_OPENTIME "OpenDuration"
@ -563,6 +567,10 @@
#define D_CMND_BRI_PRESET "BriPreset"
#endif
// Commands xdrv_38_ping.ino
#define D_CMND_PING "Ping"
#define D_JSON_PING "Ping"
// Commands xsns_02_analog.ino
#define D_CMND_ADCPARAM "AdcParam"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -674,6 +675,7 @@
#define D_UNIT_GALLONS_PER_MIN "gal/min"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOMETER_PER_HOUR "km/h"
#define D_UNIT_KILOOHM "kΩ"
#define D_UNIT_KILOWATTHOUR "kWh"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -674,6 +675,7 @@
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"
#define D_UNIT_KILOWATTHOUR "kWh"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "gal/mn"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 - GDO2"
#define D_SENSOR_HRXL_RX "HRXL - RX"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL - TX"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "А"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "кОм"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -674,6 +675,7 @@
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"
#define D_UNIT_KILOWATTHOUR "kWh"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "ink"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "A"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "kΩ"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "А"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "гал"
#define D_UNIT_GALLONS_PER_MIN "гал/хв"
#define D_UNIT_INCREMENTS "інк"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "кг"
#define D_UNIT_KILOMETER_PER_HOUR "км/г" // or "km/h"
#define D_UNIT_KILOOHM "㏀"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "安"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "千克"
#define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h"
#define D_UNIT_KILOOHM "千欧"

View File

@ -664,6 +664,7 @@
#define D_SENSOR_CC1101_GDO2 "CC1101 GDO2"
#define D_SENSOR_HRXL_RX "HRXL Rx"
#define D_SENSOR_ELECTRIQ_MOODL "MOODL Tx"
#define D_SENSOR_AS3935 "AS3935"
// Units
#define D_UNIT_AMPERE "安"
@ -673,6 +674,7 @@
#define D_UNIT_GALLONS "gal"
#define D_UNIT_GALLONS_PER_MIN "g/m"
#define D_UNIT_INCREMENTS "inc"
#define D_UNIT_KILOMETER "km"
#define D_UNIT_KILOGRAM "kg"
#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h"
#define D_UNIT_KILOOHM "千歐"

View File

@ -389,6 +389,9 @@
#define USE_SUNRISE // Add support for Sunrise and sunset tools (+16k)
#define SUNRISE_DAWN_ANGLE DAWN_NORMAL // Select desired Dawn Angle from (DAWN_NORMAL, DAWN_CIVIL, DAWN_NAUTIC, DAWN_ASTRONOMIC)
// -- Ping ----------------------------------------
// #define USE_PING // Enable Ping command (+3k code)
// -- Rules or Script ----------------------------
// Select none or only one of the below defines
#define USE_RULES // Add support for rules (+8k code)
@ -499,6 +502,8 @@
// #define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30
// #define WEMOS_MOTOR_V1_FREQ 1000 // Default frequency
// #define USE_HDC1080 // [I2cDriver45] Enable HDC1080 temperature/humidity sensor (I2C address 0x40) (+1k5 code)
// #define USE_IAQ // [I2cDriver46] Enable iAQ-core air quality sensor (I2C address 0x5a) (+0k6 code)
// #define USE_AS3935 // [I2cDriver48] Enable AS3935 Franklin Lightning Sensor (I2C address 0x03) (+5k4 code)
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0
@ -513,6 +518,8 @@
#define MTX_ADDRESS6 0x76 // [DisplayAddress6] I2C address of sixth 8x8 matrix module
#define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module
#define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module
#define USE_DISPLAY_SEVENSEG // [DisplayModel 11] [I2cDriver47] Enable sevenseg display (I2C 0x70-0x77) (<+11k code)
#define SEVENSEG_ADDRESS1 0x70 // [DisplayAddress1] I2C address of first sevenseg matrix module
// #define USE_DISPLAY_SH1106 // [DisplayModel 7] [I2cDriver6] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D)
#endif // USE_I2C
@ -661,7 +668,7 @@
/*********************************************************************************************\
* Optional firmware configurations
* Select none or just one for optional features and sensors as configured in tasmota_post.h
* Select none or just one for optional features and sensors as configured in tasmota_configurations.h
* See RELEASENOTES.md for selected features
\*********************************************************************************************/

View File

@ -211,6 +211,30 @@ typedef union {
};
} SensorCfg1;
typedef union {
uint8_t data;
struct {
uint8_t nf_autotune : 1; // Autotune the NF Noise Level
uint8_t dist_autotune : 1; // Autotune Disturber on/off
uint8_t nf_autotune_both : 1; // Autotune over both Areas: INDOORS/OUDOORS
uint8_t mqtt_only_Light_Event : 1; // mqtt only if lightning Irq
uint8_t spare4 : 1;
uint8_t spare5 : 1;
uint8_t spare6 : 1;
uint8_t spare7 : 1;
};
} As3935IntCfg;
typedef union {
uint16_t data;
struct {
uint16_t nf_autotune_time : 4; // NF Noise Autotune Time
uint16_t dist_autotune_time : 4; // Disturber Autotune Time
uint16_t nf_autotune_min : 4; // Min Stages
uint16_t spare3 : 4;
};
} As3935Param;
typedef struct {
uint32_t usage1_kWhtotal;
uint32_t usage2_kWhtotal;
@ -221,7 +245,7 @@ typedef struct {
} EnergyUsage;
typedef struct {
typedef struct PACKED {
uint8_t fnid = 0;
uint8_t dpid = 0;
} TuyaFnidDpidMap;
@ -229,7 +253,7 @@ typedef struct {
const uint32_t settings_text_size = 699; // Settings.text_pool[size] = Settings.display_model (2D2) - Settings.text_pool (017)
const uint8_t MAX_TUYA_FUNCTIONS = 16;
struct SYSCFG {
struct PACKED SYSCFG {
uint16_t cfg_holder; // 000 v6 header
uint16_t cfg_size; // 002
unsigned long save_flag; // 004
@ -472,8 +496,17 @@ struct SYSCFG {
int8_t hum_comp; // F08
uint8_t wifi_channel; // F09
uint8_t wifi_bssid[6]; // F0A
uint8_t as3935_sensor_cfg[5]; // F10
As3935IntCfg as3935_functions; // F15
As3935Param as3935_parameter; // F16
uint64_t zb_ext_panid; // F18
uint64_t zb_precfgkey_l; // F20
uint64_t zb_precfgkey_h; // F28
uint16_t zb_pan_id; // F30
uint8_t zb_channel; // F32
uint8_t zb_free_byte; // F33
uint8_t free_f10[168]; // F10
uint8_t free_f18[132]; // F34
uint16_t pulse_counter_debounce_low; // FB8
uint16_t pulse_counter_debounce_high; // FBA

View File

@ -17,166 +17,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DOMOTICZ_UPDATE_TIMER
#define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) (Optional)
#endif
#ifndef EMULATION
#define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo (single relay/light) or Hue Bridge emulation (multi relay/light) (EMUL_NONE, EMUL_WEMO or EMUL_HUE)
#endif
#ifndef MTX_ADDRESS1 // Add Display Support for up to eigth Matrices
#define MTX_ADDRESS1 0
#endif
#ifndef MTX_ADDRESS2
#define MTX_ADDRESS2 0
#endif
#ifndef MTX_ADDRESS3
#define MTX_ADDRESS3 0
#endif
#ifndef MTX_ADDRESS4
#define MTX_ADDRESS4 0
#endif
#ifndef MTX_ADDRESS5
#define MTX_ADDRESS5 0
#endif
#ifndef MTX_ADDRESS6
#define MTX_ADDRESS6 0
#endif
#ifndef MTX_ADDRESS7
#define MTX_ADDRESS7 0
#endif
#ifndef MTX_ADDRESS8
#define MTX_ADDRESS8 0
#endif
#ifndef HOME_ASSISTANT_DISCOVERY_ENABLE
#define HOME_ASSISTANT_DISCOVERY_ENABLE 0
#endif
#ifndef LATITUDE
#define LATITUDE 48.858360 // [Latitude] Your location to be used with sunrise and sunset
#endif
#ifndef LONGITUDE
#define LONGITUDE 2.294442 // [Longitude] Your location to be used with sunrise and sunset
#endif
#ifndef WORKING_PERIOD
#define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes
#endif
#ifndef COLOR_TEXT
#define COLOR_TEXT "#000" // Global text color - Black
#endif
#ifndef COLOR_BACKGROUND
#define COLOR_BACKGROUND "#fff" // Global background color - White
#endif
#ifndef COLOR_FORM
#define COLOR_FORM "#f2f2f2" // Form background color - Greyish
#endif
#ifndef COLOR_INPUT_TEXT
#define COLOR_INPUT_TEXT "#000" // Input text color - Black
#endif
#ifndef COLOR_INPUT
#define COLOR_INPUT "#fff" // Input background color - White
#endif
#ifndef COLOR_CONSOLE_TEXT
#define COLOR_CONSOLE_TEXT "#000" // Console text color - Black
#endif
#ifndef COLOR_CONSOLE
#define COLOR_CONSOLE "#fff" // Console background color - White
#endif
#ifndef COLOR_TEXT_WARNING
#define COLOR_TEXT_WARNING "#f00" // Warning text color - Red
#endif
#ifndef COLOR_TEXT_SUCCESS
#define COLOR_TEXT_SUCCESS "#008000" // Success text color - Green
#endif
#ifndef COLOR_BUTTON_TEXT
#define COLOR_BUTTON_TEXT "#fff" // Button text color - White
#endif
#ifndef COLOR_BUTTON
#define COLOR_BUTTON "#1fa3ec" // Button color - Blueish
#endif
#ifndef COLOR_BUTTON_HOVER
#define COLOR_BUTTON_HOVER "#0e70a4" // Button color when hovered over - Darker blueish
#endif
#ifndef COLOR_BUTTON_RESET
#define COLOR_BUTTON_RESET "#d43535" // Restart/Reset/Delete button color - Redish
#endif
#ifndef COLOR_BUTTON_RESET_HOVER
#define COLOR_BUTTON_RESET_HOVER "#931f1f" // Restart/Reset/Delete button color when hovered over - Darker redish
#endif
#ifndef COLOR_BUTTON_SAVE
#define COLOR_BUTTON_SAVE "#47c266" // Save button color - Greenish
#endif
#ifndef COLOR_BUTTON_SAVE_HOVER
#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" // Save button color when hovered over - Darker greenish
#endif
#ifndef COLOR_TIMER_TAB_TEXT
#define COLOR_TIMER_TAB_TEXT "#fff" // Config timer tab text color - White
#endif
#ifndef COLOR_TIMER_TAB_BACKGROUND
#define COLOR_TIMER_TAB_BACKGROUND "#999" // Config timer tab background color - Light grey
#endif
#ifndef COLOR_TITLE_TEXT
#define COLOR_TITLE_TEXT COLOR_TEXT // Title text color defaults to global text color either dark or light
#endif
#ifndef IR_RCV_MIN_UNKNOWN_SIZE
#define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6, max 255)
#endif
#ifndef ENERGY_OVERTEMP
#define ENERGY_OVERTEMP 90 // Overtemp in Celsius
#endif
#ifndef DEFAULT_DIMMER_MAX
#define DEFAULT_DIMMER_MAX 100
#endif
#ifndef DEFAULT_DIMMER_MIN
#define DEFAULT_DIMMER_MIN 0
#endif
#ifndef DEFAULT_LIGHT_DIMMER
#define DEFAULT_LIGHT_DIMMER 10
#endif
#ifndef DEFAULT_LIGHT_COMPONENT
#define DEFAULT_LIGHT_COMPONENT 255
#endif
#ifndef CORS_ENABLED_ALL
#define CORS_ENABLED_ALL "*"
#endif
enum WebColors {
COL_TEXT, COL_BACKGROUND, COL_FORM,
COL_INPUT_TEXT, COL_INPUT, COL_CONSOLE_TEXT, COL_CONSOLE,
COL_TEXT_WARNING, COL_TEXT_SUCCESS,
COL_BUTTON_TEXT, COL_BUTTON, COL_BUTTON_HOVER, COL_BUTTON_RESET, COL_BUTTON_RESET_HOVER, COL_BUTTON_SAVE, COL_BUTTON_SAVE_HOVER,
COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, COL_TITLE,
COL_LAST };
const char kWebColors[] PROGMEM =
COLOR_TEXT "|" COLOR_BACKGROUND "|" COLOR_FORM "|"
COLOR_INPUT_TEXT "|" COLOR_INPUT "|" COLOR_CONSOLE_TEXT "|" COLOR_CONSOLE "|"
COLOR_TEXT_WARNING "|" COLOR_TEXT_SUCCESS "|"
COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|"
COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT;
enum TasmotaSerialConfig {
TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1,
TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2,
TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1,
TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2,
TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1,
TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 };
const uint8_t kTasmotaSerialConfig[] PROGMEM = {
SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1,
SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2,
SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1,
SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2,
SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1,
SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2
};
/*********************************************************************************************\
* RTC memory
\*********************************************************************************************/
@ -200,14 +40,14 @@ void RtcSettingsSave(void)
{
if (GetRtcSettingsCrc() != rtc_settings_crc) {
RtcSettings.valid = RTC_MEM_VALID;
ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM));
ESP_rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM));
rtc_settings_crc = GetRtcSettingsCrc();
}
}
void RtcSettingsLoad(void)
{
ESP.rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); // 0x290
ESP_rtcUserMemoryRead(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); // 0x290
if (RtcSettings.valid != RTC_MEM_VALID) {
memset(&RtcSettings, 0, sizeof(RTCMEM));
RtcSettings.valid = RTC_MEM_VALID;
@ -247,7 +87,7 @@ void RtcRebootSave(void)
{
if (GetRtcRebootCrc() != rtc_reboot_crc) {
RtcReboot.valid = RTC_MEM_VALID;
ESP.rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT));
ESP_rtcUserMemoryWrite(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT));
rtc_reboot_crc = GetRtcRebootCrc();
}
}
@ -260,7 +100,7 @@ void RtcRebootReset(void)
void RtcRebootLoad(void)
{
ESP.rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); // 0x280
ESP_rtcUserMemoryRead(100 - sizeof(RTCRBT), (uint32_t*)&RtcReboot, sizeof(RTCRBT)); // 0x280
if (RtcReboot.valid != RTC_MEM_VALID) {
memset(&RtcReboot, 0, sizeof(RTCRBT));
RtcReboot.valid = RTC_MEM_VALID;
@ -301,6 +141,8 @@ extern "C" {
}
#include "eboot_command.h"
#ifdef ESP8266
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2)
extern "C" uint32_t _SPIFFS_end;
@ -328,6 +170,9 @@ const uint32_t SPIFFS_END = ((uint32_t)&_FS_end - 0x40200000) / SPI_FLASH_SEC_SI
// Version 4.2 config = eeprom area
const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses EEPROM area
#endif // ESP8266
// Version 5.2 allow for more flash space
const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads)
@ -341,6 +186,7 @@ uint8_t *settings_buffer = nullptr;
*/
void SetFlashModeDout(void)
{
#ifdef ESP8266
uint8_t *_buffer;
uint32_t address;
@ -358,10 +204,13 @@ void SetFlashModeDout(void)
}
}
delete[] _buffer;
#endif // ESP8266
}
bool VersionCompatible(void)
{
#ifdef ESP8266
if (Settings.flag3.compatibility_check) {
return true;
}
@ -404,6 +253,8 @@ bool VersionCompatible(void)
return false;
}
#endif // ESP8266
return true;
}
@ -479,7 +330,7 @@ void SettingsSaveAll(void)
void UpdateQuickPowerCycle(bool update)
{
if (Settings.flag3.fast_power_cycle_disable) { return; }
if (Settings.flag3.fast_power_cycle_disable) { return; } // SetOption65 - Disable fast power cycle detection for device reset
uint32_t pc_register;
uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES;
@ -638,6 +489,7 @@ void SettingsSave(uint8_t rotate)
Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade
Settings.cfg_crc32 = GetSettingsCrc32();
#ifdef ESP8266
if (ESP.flashEraseSector(settings_location)) {
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
}
@ -648,6 +500,9 @@ void SettingsSave(uint8_t rotate)
delay(1);
}
}
#else // ESP32
SettingsSaveMain(&Settings, sizeof(SYSCFG));
#endif // ESP8266
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG));
@ -672,8 +527,7 @@ void SettingsLoad(void)
uint16_t cfg_holder = 0;
for (uint32_t i = 0; i < CFG_ROTATES; i++) {
flash_location--;
ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
ESP_flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
bool valid = false;
if (Settings.version > 0x06000000) {
bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32());
@ -684,7 +538,7 @@ void SettingsLoad(void)
if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder
valid = (cfg_holder == Settings.cfg_holder);
} else {
ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH));
ESP_flashReadHeader((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH));
valid = (Settings.cfg_holder == _SettingsH.cfg_holder);
}
if (valid) {
@ -700,7 +554,7 @@ void SettingsLoad(void)
delay(1);
}
if (settings_location > 0) {
ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
ESP_flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag);
}
@ -737,6 +591,7 @@ void EspErase(uint32_t start_sector, uint32_t end_sector)
}
}
#ifdef ESP8266
void SettingsErase(uint8_t type)
{
/*
@ -791,6 +646,7 @@ void SettingsErase(uint8_t type)
EsptoolErase(_sectorStart, _sectorEnd); // Esptool - erases flash completely
#endif // FIRMWARE_MINIMAL
}
#endif // ESP8266
void SettingsSdkErase(void)
{
@ -1188,6 +1044,8 @@ void SettingsEnableAllI2cDrivers(void)
void SettingsDelta(void)
{
if (Settings.version != VERSION) { // Fix version dependent changes
#ifdef ESP8266
if (Settings.version < 0x06000000) {
Settings.cfg_size = sizeof(SYSCFG);
Settings.cfg_crc = GetSettingsCrc();
@ -1475,6 +1333,7 @@ void SettingsDelta(void)
if (Settings.version < 0x08020003) {
SettingsUpdateText(SET_TEMPLATE_NAME, Settings.user_template_name);
}
#endif // ESP8266
Settings.version = VERSION;
SettingsSave(1);

View File

@ -109,7 +109,7 @@ String GetResetReason(void)
strncpy_P(buff, PSTR(D_JSON_BLOCKED_LOOP), sizeof(buff));
return String(buff);
} else {
return ESP.getResetReason();
return ESP_getResetReason();
}
}
@ -213,7 +213,7 @@ char* ulltoa(unsigned long long value, char *str, int radix)
}
// see https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c
// char* ToHex_P(unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0'); in tasmota_post.h
// char* ToHex_P(unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0'); in tasmota_globals.h
char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween)
{
// ToHex_P(in, insz, out, outz) -> "12345667"
@ -1660,7 +1660,7 @@ void Syslog(void)
memmove(log_data + strlen(syslog_preamble), log_data, sizeof(log_data) - strlen(syslog_preamble));
log_data[sizeof(log_data) -1] = '\0';
memcpy(log_data, syslog_preamble, strlen(syslog_preamble));
PortUdp.write(log_data, strlen(log_data));
PortUdp_write(log_data, strlen(log_data));
PortUdp.endPacket();
delay(1); // Add time for UDP handling (#5512)
} else {

View File

@ -119,6 +119,7 @@ void ButtonHandler(void)
uint8_t button = NOT_PRESSED;
uint8_t button_present = 0;
#ifdef ESP8266
if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type))) {
button_present = 1;
if (Button.dual_code) {
@ -131,7 +132,9 @@ void ButtonHandler(void)
Button.dual_code = 0;
}
}
else if (pin[GPIO_KEY1 +button_index] < 99) {
else
#endif // ESP8266
if (pin[GPIO_KEY1 +button_index] < 99) {
button_present = 1;
button = (digitalRead(pin[GPIO_KEY1 +button_index]) != bitRead(Button.inverted_mask, button_index));
}
@ -153,6 +156,7 @@ void ButtonHandler(void)
if (XdrvCall(FUNC_BUTTON_PRESSED)) {
// Serviced
}
#ifdef ESP8266
else if (SONOFF_4CHPRO == my_module_type) {
if (Button.hold_timer[button_index]) { Button.hold_timer[button_index]--; }
@ -172,6 +176,7 @@ void ButtonHandler(void)
}
}
}
#endif // ESP8266
else {
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
@ -227,9 +232,12 @@ void ButtonHandler(void)
if (!restart_flag && !Button.hold_timer[button_index] && (Button.press_counter[button_index] > 0) && (Button.press_counter[button_index] < MAX_BUTTON_COMMANDS +3)) {
bool single_press = false;
if (Button.press_counter[button_index] < 3) { // Single or Double press
#ifdef ESP8266
if ((SONOFF_DUAL_R2 == my_module_type) || (SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) {
single_press = true;
} else {
} else
#endif // ESP8266
{
single_press = (Settings.flag.button_swap +1 == Button.press_counter[button_index]); // SetOption11 (0)
if ((1 == Button.present) && (2 == devices_present)) { // Single Button with two devices only
if (Settings.flag.button_swap) { // SetOption11 (0)

View File

@ -186,8 +186,11 @@ void CommandHandler(char* topicBuf, char* dataBuf, uint32_t data_len)
uint32_t real_index = SET_MQTT_GRP_TOPIC;
for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) {
if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; }
grpflg = (strstr(topicBuf, SettingsText(real_index +i)) != nullptr);
if (grpflg) { break; }
char *group_topic = SettingsText(real_index +i);
if (*group_topic && strstr(topicBuf, group_topic) != nullptr) {
grpflg = true;
break;
}
}
char stemp1[TOPSZ];
@ -423,7 +426,7 @@ void CmndStatus(void)
"\"Hardware\":\"%s\""
"%s}}"),
my_version, my_image, GetBuildDateAndTime().c_str(),
ESP.getBootVersion(), ESP.getSdkVersion(),
ESP_getBootVersion(), ESP.getSdkVersion(),
GetDeviceHardware().c_str(),
GetStatistics().c_str());
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2"));
@ -445,7 +448,7 @@ void CmndStatus(void)
D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\""
D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]"),
ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024,
ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(),
ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP_getFlashChipId(), ESP.getFlashChipMode(),
LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2, feature5, feature6);
XsnsDriverState();
ResponseAppend_P(PSTR(",\"Sensors\":"));
@ -577,10 +580,10 @@ void CmndSleep(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) {
Settings.sleep = XdrvMailbox.payload;
sleep = XdrvMailbox.payload;
ssleep = XdrvMailbox.payload;
WiFiSetSleepMode();
}
Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, sleep);
Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, XdrvMailbox.command, Settings.sleep, ssleep);
}
@ -643,7 +646,10 @@ void CmndRestart(void)
void CmndPowerOnState(void)
{
if (my_module_type != MOTOR) {
#ifdef ESP8266
if (my_module_type != MOTOR)
#endif // ESP8266
{
/* 0 = Keep relays off after power on
* 1 = Turn relays on after power on, if PulseTime set wait for PulseTime seconds, and turn relays off
* 2 = Toggle relays after power on

View File

@ -17,6 +17,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ESP8266
const uint32_t crash_magic = 0x53415400; // Stack trace magic number (TASx)
const uint32_t crash_rtc_offset = 32; // Offset in RTC memory skipping OTA used block
const uint32_t crash_dump_max_len = 31; // Dump only 31 call addresses to satisfy max JSON length of about 600 characters
@ -109,3 +111,5 @@ void CrashDump(void)
ResponseJsonEnd();
}
#endif // ESP8266

View File

@ -20,6 +20,7 @@
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_DEVICE_GROUPS
//#define DEVICE_GROUPS_DEBUG
@ -163,7 +164,7 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la
if (!ip) ip = IPAddress(239,255,255,250);
for (int attempt = 1; attempt <= 5; attempt++) {
if (PortUdp.beginPacket(ip, 1900)) {
PortUdp.write(packet, len);
PortUdp_write(packet, len);
if (PortUdp.endPacket()) return;
}
delay(10);
@ -552,7 +553,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType mes
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s packet via multicast, sequence=%u"), device_group->message_length, device_group->group_name, device_group->message[device_group->message_header_length] | device_group->message[device_group->message_header_length + 1] << 8);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(0, device_group->message, device_group->message_length, PSTR("Multicast"));
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Multicast"));
uint32_t now = millis();
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) {
@ -857,7 +858,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending initial status request for group %s"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(0, device_group->message, device_group->message_length, PSTR("Initial"));
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, device_group->message_length, PSTR("Initial"));
device_group->message[device_group->message_header_length + 2] = DGR_FLAG_STATUS_REQUEST; // The reset flag is on only for the first packet - turn it off now
device_group->next_ack_check_time = now + 200;
}
@ -941,7 +942,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending device group %s announcement"), device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
SendDeviceGroupPacket(0, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, PSTR("Announcement"));
SendDeviceGroupPacket(IPAddress(0,0,0,0), device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, PSTR("Announcement"));
device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000);
}
if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time;

177
tasmota/support_esp32.ino Normal file
View File

@ -0,0 +1,177 @@
/*
support_esp32.ino - ESP32 specific code for Tasmota
Copyright (C) 2020 Theo Arends / Jörg Schüler-Maroldt
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 ESP32
#include <nvs.h>
#include <rom/rtc.h>
void SettingsErase(uint8_t type)
{
if (1 == type) // SDK parameter area
{
}
else if (2 == type) // Tasmota parameter area (0x0F3xxx - 0x0FBFFF)
{
}
else if (3 == type) // Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF)
{
}
noInterrupts();
nvs_handle handle;
nvs_open("main", NVS_READWRITE, &handle);
nvs_erase_all(handle);
nvs_commit(handle);
nvs_close(handle);
interrupts();
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " t=%d"), type);
}
void SettingsLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen)
{
noInterrupts();
nvs_handle handle;
size_t size;
nvs_open(sNvsName, NVS_READONLY, &handle);
size = nSettingsLen;
nvs_get_blob(handle, sName, pSettings, &size);
nvs_close(handle);
interrupts();
}
void SettingsSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen)
{
nvs_handle handle;
noInterrupts();
nvs_open(sNvsName, NVS_READWRITE, &handle);
nvs_set_blob(handle, sName, pSettings, nSettingsLen);
nvs_commit(handle);
nvs_close(handle);
interrupts();
}
void ESP32_flashRead(uint32_t offset, uint32_t *data, size_t size)
{
SettingsLoad("main", "Settings", data, size);
}
void ESP32_flashReadHeader(uint32_t offset, uint32_t *data, size_t size)
{
SettingsLoad("main", "SettingsH", data, size);
}
void SettingsSaveMain(const void *pSettings, unsigned nSettingsLen)
{
SettingsSave("main", "Settings", pSettings, nSettingsLen);
}
/*
void SettingsLoadMain(void *pSettings, unsigned nSettingsLen)
{
SettingsLoad("main", "Settings", pSettings, nSettingsLen);
}
void SettingsLoadMainH(void *pSettingsH, unsigned nSettingsLenH)
{
SettingsLoad("main", "SettingsH", pSettingsH, nSettingsLenH);
}
*/
void SettingsLoadUpg(void *pSettings, unsigned nSettingsLen)
{
SettingsLoad("upg", "Settings", pSettings, nSettingsLen);
}
void SettingsLoadUpgH(void *pSettings, unsigned nSettingsLen)
{
SettingsLoad("upg", "SettingsH", pSettings, nSettingsLen);
}
//
// sntp emulation
//
static bool bNetIsTimeSync = false;
//
void SntpInit()
{
bNetIsTimeSync = true;
}
uint32_t SntpGetCurrentTimestamp(void)
{
time_t now = 0;
if (bNetIsTimeSync || ntp_force_sync)
{
//Serial_DebugX(("timesync configTime %d\n", ntp_force_sync, bNetIsTimeSync));
// init to UTC Time
configTime(0, 0, SettingsText(SET_NTPSERVER1), SettingsText(SET_NTPSERVER2), SettingsText(SET_NTPSERVER3));
bNetIsTimeSync = false;
ntp_force_sync = false;
}
time(&now);
return now;
}
//
// Crash stuff
//
void CrashDump(void)
{
}
bool CrashFlag(void)
{
return false;
}
void CrashDumpClear(void)
{
}
void CmndCrash(void)
{
/*
volatile uint32_t dummy;
dummy = *((uint32_t*) 0x00000000);
*/
}
// Do an infinite loop to trigger WDT watchdog
void CmndWDT(void)
{
/*
volatile uint32_t dummy = 0;
while (1) {
dummy++;
}
*/
}
// This will trigger the os watch after OSWATCH_RESET_TIME (=120) seconds
void CmndBlockedLoop(void)
{
/*
while (1) {
delay(1000);
}
*/
}
#endif // ESP32

View File

@ -17,7 +17,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ESP8266
#define USE_ESPTOOL
#endif // ESP8266
#ifdef USE_ESPTOOL
/*********************************************************************************************\
* EspTool Erase function based on Version 2.8

View File

@ -542,11 +542,18 @@ void GetFeatures(void)
#ifdef USE_HDC1080
feature6 |= 0x00000008; // xsns_65_hdc1080.ino
#endif
// feature6 |= 0x00000010;
// feature6 |= 0x00000020;
// feature6 |= 0x00000040;
// feature6 |= 0x00000080;
#ifdef USE_IAQ
feature6 |= 0x00000010; // xsns_66_iAQ.ino
#endif
#ifdef USE_DISPLAY_SEVENSEG
feature6 |= 0x00000020; // xdsp_11_sevenseg.ino
#endif
#ifdef USE_AS3935
feature6 |= 0x00000040; // xsns_67_as3935.ino
#endif
#ifdef USE_PING
feature6 |= 0x00000080; // xdrv_38_ping.ino
#endif
// feature6 |= 0x00000100;
// feature6 |= 0x00000200;

View File

@ -162,7 +162,7 @@ void* memmove_P(void *dest, const void *src, size_t n)
* Core overrides
\*********************************************************************************************/
// Add below line to tasmota_post.h
// Add below line to tasmota_globals.h
// extern "C" void resetPins();
void resetPins()
{

View File

@ -210,6 +210,7 @@ void SetDevicePower(power_t rpower, uint32_t source)
if (XdrvCall(FUNC_SET_DEVICE_POWER)) { // Set power state and stop if serviced
// Serviced
}
#ifdef ESP8266
else if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) {
Serial.write(0xA0);
Serial.write(0x04);
@ -221,7 +222,9 @@ void SetDevicePower(power_t rpower, uint32_t source)
else if (EXS_RELAY == my_module_type) {
SetLatchingRelay(rpower, 1);
}
else {
else
#endif // ESP8266
{
for (uint32_t i = 0; i < devices_present; i++) {
power_t state = rpower &1;
if (i < MAX_RELAYS) {
@ -279,9 +282,11 @@ void SetAllPower(uint32_t state, uint32_t source)
void SetPowerOnState(void)
{
#ifdef ESP8266
if (MOTOR == my_module_type) {
Settings.poweronstate = POWER_ALL_ON; // Needs always on else in limbo!
}
#endif // ESP8266
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) {
SetDevicePower(1, SRC_RESTART);
} else {
@ -625,7 +630,7 @@ void MqttShowState(void)
ResponseAppend_P(PSTR(",\"" D_JSON_HEAPSIZE "\":%d,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u,\"MqttCount\":%u"),
ESP.getFreeHeap()/1024, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), // SetOption60 - Enable normal sleep instead of dynamic sleep
sleep, loop_load_avg, MqttConnectCount());
ssleep, loop_load_avg, MqttConnectCount());
for (uint32_t i = 1; i <= devices_present; i++) {
#ifdef USE_LIGHT
@ -815,8 +820,10 @@ void PerformEverySecond(void)
}
}
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0
// Wifi keep alive to send Gratuitous ARP
wifiKeepAlive();
#endif // ARDUINO_ESP8266_RELEASE_2_3_0
}
/*-------------------------------------------------------------------------------------------*\
@ -901,9 +908,11 @@ void Every250mSeconds(void)
}
if (Settings.ledstate &1 && (pin[GPIO_LEDLNK] < 99 || !(blinks || restart_flag || ota_state_flag)) ) {
bool tstate = power & Settings.ledmask;
#ifdef ESP8266
if ((SONOFF_TOUCH == my_module_type) || (SONOFF_T11 == my_module_type) || (SONOFF_T12 == my_module_type) || (SONOFF_T13 == my_module_type)) {
tstate = (!power) ? 1 : 0; // As requested invert signal for Touch devices to find them in the dark
}
#endif // ESP8266
SetLedPower(tstate);
}
@ -1211,13 +1220,14 @@ void SerialInput(void)
delay(0);
serial_in_byte = Serial.read();
#ifdef ESP8266
/*-------------------------------------------------------------------------------------------*\
* Sonoff dual and ch4 19200 baud serial interface
\*-------------------------------------------------------------------------------------------*/
if ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)) {
serial_in_byte = ButtonSerial(serial_in_byte);
}
#endif // ESP8266
/*-------------------------------------------------------------------------------------------*/
if (XdrvCall(FUNC_SERIAL)) {
@ -1318,7 +1328,15 @@ void GpioInit(void)
if (!ValidModule(Settings.module)) {
uint32_t module = MODULE;
if (!ValidModule(MODULE)) { module = SONOFF_BASIC; }
if (!ValidModule(MODULE)) {
#ifdef ESP8266
module = SONOFF_BASIC;
#endif // ESP8266
#ifdef ESP32
module = WEMOS;
#endif // ESP32
}
Settings.module = module;
Settings.last_module = module;
}
@ -1415,7 +1433,9 @@ void GpioInit(void)
if (mpin) pin[mpin] = i;
}
#ifdef ESP8266
if ((2 == pin[GPIO_TXD]) || (H801 == my_module_type)) { Serial.set_tx(2); }
#endif // ESP8266
analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h)
analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c)
@ -1460,6 +1480,7 @@ void GpioInit(void)
if (XdrvCall(FUNC_MODULE_INIT)) {
// Serviced
}
#ifdef ESP8266
else if (YTF_IR_BRIDGE == my_module_type) {
ClaimSerial(); // Stop serial loopback mode
// devices_present = 1;
@ -1477,6 +1498,7 @@ void GpioInit(void)
SetSerial(19200, TS_SERIAL_8N1);
}
#endif // USE_SONOFF_SC
#endif // ESP8266
for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
if (pin[GPIO_PWM1 +i] < 99) {
@ -1495,10 +1517,12 @@ void GpioInit(void)
if (pin[GPIO_REL1 +i] < 99) {
pinMode(pin[GPIO_REL1 +i], OUTPUT);
devices_present++;
#ifdef ESP8266
if (EXS_RELAY == my_module_type) {
digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0);
if (i &1) { devices_present--; }
}
#endif // ESP8266
}
}

View File

@ -156,10 +156,10 @@ void WiFiSetSleepMode(void)
// Sleep explanation: https://github.com/esp8266/Arduino/blob/3f0c601cfe81439ce17e9bd5d28994a7ed144482/libraries/ESP8266WiFi/src/ESP8266WiFiGeneric.cpp#L255
#if defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
#else // Enabled in 2.3.0, 2.4.0 and stage
if (sleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times
if (ssleep && Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
WiFi.setSleepMode(WIFI_LIGHT_SLEEP); // Allow light sleep during idle times
} else {
WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default)
WiFi.setSleepMode(WIFI_MODEM_SLEEP); // Disable sleep (Esp8288/Arduino core and sdk default)
}
#endif
WifiSetOutputPower();
@ -709,9 +709,10 @@ void EspRestart(void)
WifiShutdown(true);
CrashDumpClear(); // Clear the stack dump in RTC
// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0
ESP.reset();
ESP_reset();
}
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0
//
// Gratuitous ARP, backported from https://github.com/esp8266/Arduino/pull/6889
//
@ -759,3 +760,4 @@ void wifiKeepAlive(void) {
SetNextTimeInterval(wifiTimer, wifiTimerSec * 1000);
}
}
#endif // ARDUINO_ESP8266_RELEASE_2_3_0

View File

@ -30,7 +30,6 @@
* Default sensor states
\*********************************************************************************************/
#define CODE_IMAGE 0
#define CODE_IMAGE_STR "tasmota"
#define USE_LIGHT // Enable light control
@ -42,8 +41,14 @@
* Power Type
\*********************************************************************************************/
#ifdef ESP8266
typedef unsigned long power_t; // Power (Relay) type
const uint32_t POWER_MASK = 0xffffffffUL; // Power (Relay) full mask
#endif // ESP8266
#ifdef ESP32
typedef uint64_t power_t; // Power (Relay) type
const uint64_t POWER_MASK = 0xffffffffffffffffull; // Power (Relay) full mask
#endif // ESP32
/*********************************************************************************************\
* Constants
@ -155,19 +160,6 @@ const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to
#define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer)
#define MAX_RULE_VARS 16 // Max number of rule variables (33 bytes / variable)
/*
// Removed from esp8266 core since 20171105
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
*/
#define tmin(a,b) ((a)<(b)?(a):(b))
#define tmax(a,b) ((a)>(b)?(a):(b))
#define STR_HELPER(x) #x
#ifndef STR
#define STR(x) STR_HELPER(x)
#endif
//enum ws2812NeopixelbusFeature { NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_3LED, NEO_RGBW, NEO_GRBW }; // Doesn't work
#define NEO_RGB 0 // Neopixel RGB leds
#define NEO_GRB 1 // Neopixel GRB leds
@ -303,7 +295,8 @@ enum SettingsTextIndex { SET_OTAURL,
SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8,
SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16,
SET_MQTT_GRP_TOPIC2, SET_MQTT_GRP_TOPIC3, SET_MQTT_GRP_TOPIC4,
SET_TEMPLATE_NAME, SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4,
SET_TEMPLATE_NAME,
SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4,
SET_MAX };
enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYPE_UPDATE_COMMAND };
@ -336,4 +329,21 @@ const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Seri
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
enum TasmotaSerialConfig {
TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1,
TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2,
TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1,
TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2,
TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1,
TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 };
const SerConfu8 kTasmotaSerialConfig[] PROGMEM = {
SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1,
SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2,
SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1,
SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2,
SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1,
SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2
};
#endif // _TASMOTA_H_

View File

@ -32,13 +32,14 @@
// Location specific includes
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
#include "tasmota_compat.h"
#include "tasmota_version.h" // Tasmota version information
#include "tasmota.h" // Enumeration used in my_user_config.h
#include "my_user_config.h" // Fixed user configurable options
#ifdef USE_MQTT_TLS
#include <t_bearssl.h> // we need to include before "tasmota_post.h" to take precedence over the BearSSL version in Arduino
#include <t_bearssl.h> // We need to include before "tasmota_globals.h" to take precedence over the BearSSL version in Arduino
#endif // USE_MQTT_TLS
#include "tasmota_post.h" // Configuration overrides for all previous includes
#include "tasmota_globals.h" // Function prototypes and global configuration
#include "i18n.h" // Language support configured by my_user_config.h
#include "tasmota_template.h" // Hardware configuration
@ -123,7 +124,7 @@ uint8_t mqtt_cmnd_blocked = 0; // Ignore flag for publish command
uint8_t mqtt_cmnd_blocked_reset = 0; // Count down to reset if needed
uint8_t state_250mS = 0; // State 250msecond per second flag
uint8_t latching_relay_pulse = 0; // Latching relay pulse timer
uint8_t sleep; // Current copy of Settings.sleep
uint8_t ssleep; // Current copy of Settings.sleep
uint8_t blinkspeed = 1; // LED blink rate
uint8_t pin[GPIO_MAX]; // Possible pin configurations
uint8_t active_device = 1; // Active device in ExecuteCommandPower
@ -226,7 +227,7 @@ void setup(void)
syslog_level = Settings.syslog_level;
stop_flash_rotate = Settings.flag.stop_flash_rotate; // SetOption12 - Switch between dynamic or fixed slot flash save location
save_data_counter = Settings.save_data;
sleep = Settings.sleep;
ssleep = Settings.sleep;
#ifndef USE_EMULATION
Settings.flag2.emulation = 0;
#else
@ -259,8 +260,13 @@ void setup(void)
Settings.my_adc0 = ADC0_NONE; // Reset user defined ADC0 disabling sensors
}
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;
#endif // ESP8266
#ifdef ESP32
Settings.module = WEMOS; // Reset module to Wemos
#endif // ESP32
}
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count);
}
@ -374,10 +380,10 @@ void loop(void)
if (Settings.flag3.sleep_normal) { // SetOption60 - Enable normal sleep instead of dynamic sleep
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
delay(sleep); // https://github.com/esp8266/Arduino/issues/2021
delay(ssleep); // https://github.com/esp8266/Arduino/issues/2021
} else {
if (my_activity < (uint32_t)sleep) {
delay((uint32_t)sleep - my_activity); // Provide time for background tasks like wifi
if (my_activity < (uint32_t)ssleep) {
delay((uint32_t)ssleep - my_activity); // Provide time for background tasks like wifi
} else {
if (global_state.wifi_down) {
delay(my_activity /2); // If wifi down and my_activity > setoption36 then force loop delay to 1/3 of my_activity period
@ -386,7 +392,7 @@ void loop(void)
}
if (!my_activity) { my_activity++; } // We cannot divide by 0
uint32_t loop_delay = sleep;
uint32_t loop_delay = ssleep;
if (!loop_delay) { loop_delay++; } // We cannot divide by 0
uint32_t loops_per_second = 1000 / loop_delay; // We need to keep track of this many loops per second
uint32_t this_cycle_ratio = 100 * my_activity / loop_delay;

31
tasmota/tasmota_compat.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
#ifdef ESP32
#include <esp8266toEsp32.h>
#define PACKED __attribute((__packed__))
// Modul
#undef MODULE
#define MODULE WEMOS // [Module] Select default model
#endif
#ifdef ESP8266
// ESP8266
#define PACKED
#define ESP_rtcUserMemoryWrite(offset, data, size) ESP.rtcUserMemoryWrite(offset, data, size)
#define ESP_rtcUserMemoryRead(offset, data, size) ESP.rtcUserMemoryRead(offset, data, size)
#define ESP_getResetReason() ESP.getResetReason()
#define ESP_reset() ESP.reset()
#define ESP_getBootVersion() ESP.getBootVersion()
#define ESP_getFlashChipId() ESP.getFlashChipId()
//
// we need different ESP_flashRead for ESP32
//
#define ESP_flashReadHeader(offset, data, size) ESP.flashRead(offset, data, size)
#define ESP_flashRead(offset, data, size) ESP.flashRead(offset, data, size)
//
// UDP
#define PortUdp_write(p,n) PortUdp.write(p, n)
//
// Serial minimal type to hold the config
#define SerConfu8 uint8_t
#endif // ESP32

View File

@ -1,5 +1,5 @@
/*
tasmota_post.h - Post header file for Tasmota
tasmota_configurations.h - Configurations for Tasmota
Copyright (C) 2020 Theo Arends
@ -17,73 +17,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TASMOTA_POST_H_
#define _TASMOTA_POST_H_
/*********************************************************************************************\
* Function prototypes
\*********************************************************************************************/
// Needed for core 2.3.0 compilation (#6721)
#ifdef __cplusplus
extern "C" {
#endif
#include "user_interface.h"
#ifdef __cplusplus
}
#endif
//#ifdef USE_KNX // Enabling this will fail compilation. It has no impact if not used. (20180417)
#include <esp-knx-ip.h>
void KNX_CB_Action(message_t const &msg, void *arg);
//#endif // USE_KNX
void DomoticzTempHumPressureSensor(float temp, float hum, float baro = -1);
char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0');
extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end);
extern "C" void resetPins();
/*********************************************************************************************\
* Default global defines
\*********************************************************************************************/
#ifndef ENERGY_OVERTEMP
#define ENERGY_OVERTEMP 90 // Overtemp in Celsius
#endif
#ifdef USE_EMULATION_HUE
#define USE_EMULATION
#endif
#ifdef USE_EMULATION_WEMO
#define USE_EMULATION
#endif
#ifdef USE_DEVICE_GROUPS
#define USE_EMULATION
#endif
#ifdef USE_MQTT_TLS
const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog
#else
const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog
#endif
#if defined(USE_MQTT_TLS) && defined(ARDUINO_ESP8266_RELEASE_2_3_0)
#error "TLS is no more supported on Core 2.3.0, use 2.4.2 or higher."
#endif
#ifndef MODULE
#define MODULE SONOFF_BASIC // [Module] Select default model
#endif
#ifdef USE_PWM_DIMMER_REMOTE
#ifdef USE_PWM_DIMMER
#ifndef USE_DEVICE_GROUPS
#define USE_DEVICE_GROUPS
#endif // USE_DEVICE_GROUPS
#else // USE_PWM_DIMMER
#undef USE_PWM_DIMMER_REMOTE
#endif // USE_PWM_DIMMER
#endif // USE_PWM_DIMMER_REMOTE
#ifndef _TASMOTA_CONFIGURATIONS_H_
#define _TASMOTA_CONFIGURATIONS_H_
/*********************************************************************************************\
* [tasmota-sensors.bin]
@ -92,8 +27,6 @@ extern "C" void resetPins();
#ifdef FIRMWARE_SENSORS
#undef CODE_IMAGE
#define CODE_IMAGE 2
#undef CODE_IMAGE_STR
#define CODE_IMAGE_STR "sensors"
@ -189,6 +122,8 @@ extern "C" void resetPins();
#define WEMOS_MOTOR_V1_ADDR 0x30 // Default I2C address 0x30
#define WEMOS_MOTOR_V1_FREQ 1000 // Default frequency
//#define USE_HDC1080 // Enable HDC1080 temperature/humidity sensor
#define USE_IAQ // [I2cDriver46] Enable iAQ-core air quality sensor (I2C address 0x5a) (+0k6 code)
#define USE_AS3935 // [I2cDriver48] Enable AS3935 Franklin Lightning Sensor (I2C address 0x03) (+5k4 code)
#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code)
#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code)
@ -257,8 +192,6 @@ extern "C" void resetPins();
#ifdef FIRMWARE_KNX_NO_EMULATION
#undef CODE_IMAGE
#define CODE_IMAGE 3
#undef CODE_IMAGE_STR
#define CODE_IMAGE_STR "knx"
@ -282,8 +215,6 @@ extern "C" void resetPins();
#ifdef FIRMWARE_DISPLAYS
#undef CODE_IMAGE
#define CODE_IMAGE 5
#undef CODE_IMAGE_STR
#define CODE_IMAGE_STR "display"
@ -332,6 +263,7 @@ extern "C" void resetPins();
#define USE_DISPLAY_LCD // [DisplayModel 1] Enable Lcd display (I2C addresses 0x27 and 0x3F) (+6k code)
#define USE_DISPLAY_SSD1306 // [DisplayModel 2] Enable SSD1306 Oled 128x64 display (I2C addresses 0x3C and 0x3D) (+16k code)
#define USE_DISPLAY_MATRIX // [DisplayModel 3] Enable 8x8 Matrix display (I2C adresseses see below) (+11k code)
#define USE_DISPLAY_SEVENSEG // [DisplayModel 11] [I2cDriver47] Enable sevenseg display (I2C addresses 0x70 - 0x77) (<+11k code)
#define USE_DISPLAY_SH1106 // [DisplayModel 7] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D)
#define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC)
@ -355,8 +287,6 @@ extern "C" void resetPins();
#ifdef FIRMWARE_IR
#undef CODE_IMAGE
#define CODE_IMAGE 6
#undef CODE_IMAGE_STR
#define CODE_IMAGE_STR "ir"
@ -462,8 +392,6 @@ extern "C" void resetPins();
#ifdef FIRMWARE_LITE
#undef CODE_IMAGE
#define CODE_IMAGE 4
#undef CODE_IMAGE_STR
#define CODE_IMAGE_STR "lite"
@ -579,8 +507,6 @@ extern "C" void resetPins();
#ifdef FIRMWARE_MINIMAL
#undef CODE_IMAGE
#define CODE_IMAGE 1
#undef CODE_IMAGE_STR
#define CODE_IMAGE_STR "minimal"
@ -692,95 +618,4 @@ extern "C" void resetPins();
#undef USE_DEBUG_DRIVER // Disable debug code
#endif // FIRMWARE_MINIMAL
/*********************************************************************************************\
* Mandatory defines satisfying possible disabled defines
\*********************************************************************************************/
// 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)
#ifndef USE_SONOFF_RF
#undef USE_RF_FLASH // Disable RF firmware flash when SOnoff Rf is disabled
#endif
#ifndef SWITCH_MODE
#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state)
#endif
#ifndef STARTING_OFFSET // NOVA SDS parameter used in settings
#define STARTING_OFFSET 30
#endif
#ifndef MQTT_FINGERPRINT1
// Set an all-zeros default fingerprint to activate auto-learning on first connection (AWS IoT)
#define MQTT_FINGERPRINT1 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
#endif
#ifndef MQTT_FINGERPRINT2
#define MQTT_FINGERPRINT2 "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07"
#endif
#ifndef WS2812_LEDS
#define WS2812_LEDS 30 // [Pixels] Number of LEDs
#endif
#ifndef MQTT_MAX_PACKET_SIZE
#define MQTT_MAX_PACKET_SIZE 1200 // Bytes
#endif
#ifndef MQTT_KEEPALIVE
#define MQTT_KEEPALIVE 30 // Seconds
#endif
#ifndef MQTT_TIMEOUT
#define MQTT_TIMEOUT 10000 // milli seconds
#endif
#ifndef MQTT_CLEAN_SESSION
#define MQTT_CLEAN_SESSION 1 // 0 = No clean session, 1 = Clean session (default)
#endif
#ifndef MESSZ
//#define MESSZ 1040 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1200)
#define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string
#endif
//#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
#ifndef ARDUINO_ESP8266_RELEASE
#define ARDUINO_ESP8266_RELEASE "STAGE"
#endif
#ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // Disable not supported features in core 2.3.0
#undef USE_MQTT_TLS_CA_CERT
#endif
#ifdef USE_DEVICE_GROUPS
#define SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, ...) _SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, __VA_ARGS__, 0)
#define SendLocalDeviceGroupMessage(REQUEST_TYPE, ...) _SendDeviceGroupMessage(0, REQUEST_TYPE, __VA_ARGS__, 0)
#define DEVICE_GROUP_MESSAGE "M-TASMOTA_DGR/"
const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE;
uint8_t device_group_count = 1;
#endif // USE_DEVICE_GROUPS
#ifdef DEBUG_TASMOTA_CORE
#define DEBUG_CORE_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_CORE_LOG(...)
#endif
#ifdef DEBUG_TASMOTA_DRIVER
#define DEBUG_DRIVER_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_DRIVER_LOG(...)
#endif
#ifdef DEBUG_TASMOTA_SENSOR
#define DEBUG_SENSOR_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_SENSOR_LOG(...)
#endif
#ifdef DEBUG_TASMOTA_TRACE
#define DEBUG_TRACE_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_TRACE_LOG(...)
#endif
#endif // _TASMOTA_POST_H_
#endif // _TASMOTA_CONFIGURATIONS_H_

335
tasmota/tasmota_globals.h Normal file
View File

@ -0,0 +1,335 @@
/*
tasmota_globals.h - Function prototypes and global configurations for Tasmota
Copyright (C) 2020 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TASMOTA_GLOBALS_H_
#define _TASMOTA_GLOBALS_H_
/*********************************************************************************************\
* Function prototypes
\*********************************************************************************************/
// Needed for core 2.3.0 compilation (#6721)
#ifdef __cplusplus
extern "C" {
#endif
#include "user_interface.h"
#ifdef __cplusplus
}
#endif
//#ifdef USE_KNX // Enabling this will fail compilation. It has no impact if not used. (20180417)
#include <esp-knx-ip.h>
void KNX_CB_Action(message_t const &msg, void *arg);
//#endif // USE_KNX
void DomoticzTempHumPressureSensor(float temp, float hum, float baro = -1);
char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0');
extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end);
extern "C" void resetPins();
/*********************************************************************************************\
* Preconfigured configurations
\*********************************************************************************************/
#include "tasmota_configurations.h" // Preconfigured configurations
/*********************************************************************************************\
* Mandatory defines satisfying disabled defines
\*********************************************************************************************/
#ifndef MODULE
#define MODULE SONOFF_BASIC // [Module] Select default model
#endif
#ifdef USE_EMULATION_HUE
#define USE_EMULATION
#endif
#ifdef USE_EMULATION_WEMO
#define USE_EMULATION
#endif
#ifdef USE_DEVICE_GROUPS
#define USE_EMULATION
#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)
#ifndef USE_SONOFF_RF
#undef USE_RF_FLASH // Disable RF firmware flash when Sonoff Rf is disabled
#endif
#ifndef SWITCH_MODE
#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state)
#endif
#ifndef MQTT_FINGERPRINT1
// Set an all-zeros default fingerprint to activate auto-learning on first connection (AWS IoT)
#define MQTT_FINGERPRINT1 "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"
#endif
#ifndef MQTT_FINGERPRINT2
#define MQTT_FINGERPRINT2 "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07"
#endif
#ifndef WS2812_LEDS
#define WS2812_LEDS 30 // [Pixels] Number of LEDs
#endif
#ifdef USE_MQTT_TLS
const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog
#else
const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog
#endif
#if defined(USE_MQTT_TLS) && defined(ARDUINO_ESP8266_RELEASE_2_3_0)
#error "TLS is no more supported on Core 2.3.0, use 2.4.2 or higher."
#endif
#ifndef MQTT_MAX_PACKET_SIZE
#define MQTT_MAX_PACKET_SIZE 1200 // Bytes
#endif
#ifndef MQTT_KEEPALIVE
#define MQTT_KEEPALIVE 30 // Seconds
#endif
#ifndef MQTT_TIMEOUT
#define MQTT_TIMEOUT 10000 // milli seconds
#endif
#ifndef MQTT_CLEAN_SESSION
#define MQTT_CLEAN_SESSION 1 // 0 = No clean session, 1 = Clean session (default)
#endif
#ifndef MESSZ
//#define MESSZ 1040 // Max number of characters in JSON message string (Hass discovery and nice MQTT_MAX_PACKET_SIZE = 1200)
#define MESSZ (MQTT_MAX_PACKET_SIZE -TOPSZ -7) // Max number of characters in JSON message string
#endif
#ifndef ARDUINO_ESP8266_RELEASE
#define ARDUINO_ESP8266_RELEASE "STAGE"
#endif
#ifdef USE_PWM_DIMMER_REMOTE
#ifdef USE_PWM_DIMMER
#ifndef USE_DEVICE_GROUPS
#define USE_DEVICE_GROUPS
#endif // USE_DEVICE_GROUPS
#else // USE_PWM_DIMMER
#undef USE_PWM_DIMMER_REMOTE
#endif // USE_PWM_DIMMER
#endif // USE_PWM_DIMMER_REMOTE
#ifndef DOMOTICZ_UPDATE_TIMER
#define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) (Optional)
#endif
#ifndef EMULATION
#define EMULATION EMUL_NONE // [Emulation] Select Belkin WeMo (single relay/light) or Hue Bridge emulation (multi relay/light) (EMUL_NONE, EMUL_WEMO or EMUL_HUE)
#endif
#ifndef MTX_ADDRESS1 // Add Display Support for up to eigth Matrices
#define MTX_ADDRESS1 0
#endif
#ifndef MTX_ADDRESS2
#define MTX_ADDRESS2 0
#endif
#ifndef MTX_ADDRESS3
#define MTX_ADDRESS3 0
#endif
#ifndef MTX_ADDRESS4
#define MTX_ADDRESS4 0
#endif
#ifndef MTX_ADDRESS5
#define MTX_ADDRESS5 0
#endif
#ifndef MTX_ADDRESS6
#define MTX_ADDRESS6 0
#endif
#ifndef MTX_ADDRESS7
#define MTX_ADDRESS7 0
#endif
#ifndef MTX_ADDRESS8
#define MTX_ADDRESS8 0
#endif
#ifndef HOME_ASSISTANT_DISCOVERY_ENABLE
#define HOME_ASSISTANT_DISCOVERY_ENABLE 0
#endif
#ifndef LATITUDE
#define LATITUDE 48.858360 // [Latitude] Your location to be used with sunrise and sunset
#endif
#ifndef LONGITUDE
#define LONGITUDE 2.294442 // [Longitude] Your location to be used with sunrise and sunset
#endif
#ifndef IR_RCV_MIN_UNKNOWN_SIZE
#define IR_RCV_MIN_UNKNOWN_SIZE 6 // Set the smallest sized "UNKNOWN" message packets we actually care about (default 6, max 255)
#endif
#ifndef ENERGY_OVERTEMP
#define ENERGY_OVERTEMP 90 // Overtemp in Celsius
#endif
#ifndef DEFAULT_DIMMER_MAX
#define DEFAULT_DIMMER_MAX 100
#endif
#ifndef DEFAULT_DIMMER_MIN
#define DEFAULT_DIMMER_MIN 0
#endif
#ifndef DEFAULT_LIGHT_DIMMER
#define DEFAULT_LIGHT_DIMMER 10
#endif
#ifndef DEFAULT_LIGHT_COMPONENT
#define DEFAULT_LIGHT_COMPONENT 255
#endif
#ifndef CORS_ENABLED_ALL
#define CORS_ENABLED_ALL "*"
#endif
#ifndef WORKING_PERIOD
#define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes
#endif
#ifndef STARTING_OFFSET
#define STARTING_OFFSET 30 // NOVA SDS parameter used in settings
#endif
/*********************************************************************************************\
* UserConfig related parameters
\*********************************************************************************************/
#ifndef COLOR_TEXT
#define COLOR_TEXT "#000" // Global text color - Black
#endif
#ifndef COLOR_BACKGROUND
#define COLOR_BACKGROUND "#fff" // Global background color - White
#endif
#ifndef COLOR_FORM
#define COLOR_FORM "#f2f2f2" // Form background color - Greyish
#endif
#ifndef COLOR_INPUT_TEXT
#define COLOR_INPUT_TEXT "#000" // Input text color - Black
#endif
#ifndef COLOR_INPUT
#define COLOR_INPUT "#fff" // Input background color - White
#endif
#ifndef COLOR_CONSOLE_TEXT
#define COLOR_CONSOLE_TEXT "#000" // Console text color - Black
#endif
#ifndef COLOR_CONSOLE
#define COLOR_CONSOLE "#fff" // Console background color - White
#endif
#ifndef COLOR_TEXT_WARNING
#define COLOR_TEXT_WARNING "#f00" // Warning text color - Red
#endif
#ifndef COLOR_TEXT_SUCCESS
#define COLOR_TEXT_SUCCESS "#008000" // Success text color - Green
#endif
#ifndef COLOR_BUTTON_TEXT
#define COLOR_BUTTON_TEXT "#fff" // Button text color - White
#endif
#ifndef COLOR_BUTTON
#define COLOR_BUTTON "#1fa3ec" // Button color - Blueish
#endif
#ifndef COLOR_BUTTON_HOVER
#define COLOR_BUTTON_HOVER "#0e70a4" // Button color when hovered over - Darker blueish
#endif
#ifndef COLOR_BUTTON_RESET
#define COLOR_BUTTON_RESET "#d43535" // Restart/Reset/Delete button color - Redish
#endif
#ifndef COLOR_BUTTON_RESET_HOVER
#define COLOR_BUTTON_RESET_HOVER "#931f1f" // Restart/Reset/Delete button color when hovered over - Darker redish
#endif
#ifndef COLOR_BUTTON_SAVE
#define COLOR_BUTTON_SAVE "#47c266" // Save button color - Greenish
#endif
#ifndef COLOR_BUTTON_SAVE_HOVER
#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" // Save button color when hovered over - Darker greenish
#endif
#ifndef COLOR_TIMER_TAB_TEXT
#define COLOR_TIMER_TAB_TEXT "#fff" // Config timer tab text color - White
#endif
#ifndef COLOR_TIMER_TAB_BACKGROUND
#define COLOR_TIMER_TAB_BACKGROUND "#999" // Config timer tab background color - Light grey
#endif
#ifndef COLOR_TITLE_TEXT
#define COLOR_TITLE_TEXT COLOR_TEXT // Title text color defaults to global text color either dark or light
#endif
enum WebColors {
COL_TEXT, COL_BACKGROUND, COL_FORM,
COL_INPUT_TEXT, COL_INPUT, COL_CONSOLE_TEXT, COL_CONSOLE,
COL_TEXT_WARNING, COL_TEXT_SUCCESS,
COL_BUTTON_TEXT, COL_BUTTON, COL_BUTTON_HOVER, COL_BUTTON_RESET, COL_BUTTON_RESET_HOVER, COL_BUTTON_SAVE, COL_BUTTON_SAVE_HOVER,
COL_TIMER_TAB_TEXT, COL_TIMER_TAB_BACKGROUND, COL_TITLE,
COL_LAST };
const char kWebColors[] PROGMEM =
COLOR_TEXT "|" COLOR_BACKGROUND "|" COLOR_FORM "|"
COLOR_INPUT_TEXT "|" COLOR_INPUT "|" COLOR_CONSOLE_TEXT "|" COLOR_CONSOLE "|"
COLOR_TEXT_WARNING "|" COLOR_TEXT_SUCCESS "|"
COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|"
COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT;
/*********************************************************************************************\
* Macros
\*********************************************************************************************/
/*
// Removed from esp8266 core since 20171105
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
*/
#define tmin(a,b) ((a)<(b)?(a):(b))
#define tmax(a,b) ((a)>(b)?(a):(b))
#define STR_HELPER(x) #x
#ifndef STR
#define STR(x) STR_HELPER(x)
#endif
#ifdef USE_DEVICE_GROUPS
#define SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, ...) _SendDeviceGroupMessage(DEVICE_INDEX, REQUEST_TYPE, __VA_ARGS__, 0)
#define SendLocalDeviceGroupMessage(REQUEST_TYPE, ...) _SendDeviceGroupMessage(0, REQUEST_TYPE, __VA_ARGS__, 0)
#define DEVICE_GROUP_MESSAGE "M-TASMOTA_DGR/"
const char kDeviceGroupMessage[] PROGMEM = DEVICE_GROUP_MESSAGE;
uint8_t device_group_count = 1;
#endif // USE_DEVICE_GROUPS
#ifdef DEBUG_TASMOTA_CORE
#define DEBUG_CORE_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_CORE_LOG(...)
#endif
#ifdef DEBUG_TASMOTA_DRIVER
#define DEBUG_DRIVER_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_DRIVER_LOG(...)
#endif
#ifdef DEBUG_TASMOTA_SENSOR
#define DEBUG_SENSOR_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_SENSOR_LOG(...)
#endif
#ifdef DEBUG_TASMOTA_TRACE
#define DEBUG_TRACE_LOG(...) AddLog_Debug(__VA_ARGS__)
#else
#define DEBUG_TRACE_LOG(...)
#endif
/*********************************************************************************************/
#endif // _TASMOTA_GLOBALS_H_

View File

@ -226,6 +226,7 @@ enum UserSelectablePins {
GPIO_CC1101_GDO2, // CC1101 pin for RX
GPIO_HRXL_RX, // Data from MaxBotix HRXL sonar range sensor
GPIO_ELECTRIQ_MOODL_TX, // ElectriQ iQ-wifiMOODL Serial TX
GPIO_AS3935,
GPIO_SENSOR_END };
// Programmer selectable GPIO functionality
@ -312,7 +313,8 @@ const char kSensorNames[] PROGMEM =
D_SENSOR_LE01MR_RX "|" D_SENSOR_LE01MR_TX "|"
D_SENSOR_CC1101_GDO0 "|" D_SENSOR_CC1101_GDO2 "|"
D_SENSOR_HRXL_RX "|"
D_SENSOR_ELECTRIQ_MOODL
D_SENSOR_ELECTRIQ_MOODL "|"
D_SENSOR_AS3935
;
const char kSensorNamesFixed[] PROGMEM =
@ -656,6 +658,9 @@ const uint8_t kGpioNiceList[] PROGMEM = {
#ifdef USE_HRXL
GPIO_HRXL_RX,
#endif
#ifdef USE_AS3935
GPIO_AS3935,
#endif
};
/********************************************************************************************/
@ -692,11 +697,26 @@ const char kAdc0Names[] PROGMEM =
/********************************************************************************************/
#ifdef ESP8266
#define MAX_GPIO_PIN 17 // Number of supported GPIO
#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11)
const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0";
#else // ESP32
// esp32 has more pins
#define USER_MODULE 255
#define MAX_GPIO_PIN 44 // Number of supported GPIO
#define MIN_FLASH_PINS 4 // Number of flash chip pins unusable for configuration (GPIO6, 7, 8 and 11)
const char PINS_WEMOS[] PROGMEM = "00010203040506070809101112131415161718192021222324252627282930313233343536373839";
#endif // ESP8266
/********************************************************************************************/
typedef struct MYIO {
uint8_t io[MAX_GPIO_PIN];
} myio;
@ -730,6 +750,8 @@ typedef struct MYTMPLT {
/********************************************************************************************/
#ifdef ESP8266
// Supported hardware modules
enum SupportedModules {
SONOFF_BASIC, SONOFF_RF, SONOFF_SV, SONOFF_TH, SONOFF_DUAL, SONOFF_POW, SONOFF_4CH, SONOFF_S2X, SLAMPHER, SONOFF_TOUCH,
@ -2221,4 +2243,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
}
};
#endif // ESP8266
#ifdef ESP32
#include "tasmota_template_ESP32.h"
#endif // ESP32
#endif // _TASMOTA_TEMPLATE_H_

View File

@ -0,0 +1,155 @@
/*
tasmota_template_ESP32.h - template settings for Tasmota
Copyright (C) 2020 Theo Arends
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _TASMOTA_TEMPLATE_ESP32_H_
#define _TASMOTA_TEMPLATE_ESP32_H_
#ifdef ESP32
// mqtt
#undef MQTT_LIBRARY_TYPE
#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT
// Hardware has no ESP32
#undef USE_TUYA_DIMMER
#undef USE_PWM_DIMMER
#undef USE_EXS_DIMMER
#undef USE_ARMTRONIX_DIMMERS
#undef USE_SONOFF_RF
#undef USE_SONOFF_SC
#undef USE_SONOFF_IFAN
#undef USE_SONOFF_L1
#undef USE_SONOFF_D1
#undef USE_RF_FLASH
// not ported
#undef USE_DISCOVERY
#undef USE_ADC_VCC // Needs to be ported
#undef USE_DEEPSLEEP
#undef USE_MY92X1
#undef USE_TUYA_MCU
#undef USE_I2C
#undef USE_PS_16_DZ
/********************************************************************************************/
// Supported hardware modules
enum SupportedModules {
WEMOS,
ESP32_CAM,
MAXMODULE
};
const char kModuleNames[] PROGMEM =
"WeMos D1 ESP32|ESP32 CAM|"
;
// Default module settings
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
WEMOS,
ESP32_CAM
};
const mytmplt kModules[MAXMODULE] PROGMEM = {
{ // "WeMos D1 ESP32", // Any ESP32 device like WeMos and NodeMCU hardware (ESP32)
GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
0, //6
0, //7
0, //8
0, //9
0, //10
0, //11
GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7
GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
0, //20
0, //21 IO GPIO21, VSPIHD, EMAC_TX_EN
GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE
0, //24
GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
0, //28
0, //29
0, //30
0, //31
GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
0, //37 NO PULLUP
0, //38 NO PULLUP
GPIO_USER //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
},
{ //"ESP32 CAM",
GPIO_USER, //0 (I)O GPIO0, ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK
GPIO_USER, //1 IO TXD0 GPIO1, U0TXD, CLK_OUT3, EMAC_RXD2
GPIO_USER, //2 IO GPIO2, ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, HS2_DATA0, SD_DATA0
GPIO_USER, //3 IO RXD0 GPIO3, U0RXD, CLK_OUT2
GPIO_USER, //4 IO GPIO4, ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, HS2_DATA1, SD_DATA1, EMAC_TX_ER
GPIO_USER, //5 IO GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK
0, //6
0, //7
0, //8
0, //9
0, //10
0, //11
GPIO_USER, //12 (I)O GPIO12, ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI, HSPIQ, HS2_DATA2, SD_DATA2, EMAC_TXD3 (If driven High, flash voltage (VDD_SDIO) is 1.8V not default 3.3V. Has internal pull-down, so unconnected = Low = 3.3V. May prevent flashing and/or booting if 3.3V flash is connected and pulled high. See ESP32 datasheet for more details.)
GPIO_USER, //13 IO GPIO13, ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, HS2_DATA3, SD_DATA3, EMAC_RX_ER
GPIO_USER, //14 IO GPIO14, ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, HS2_CLK, SD_CLK, EMAC_TXD2
GPIO_USER, //15 (I)O GPIO15, ADC2_CH3, TOUCH3, MTDO, HSPICS0, RTC_GPIO13, HS2_CMD, SD_CMD, EMAC_RXD3 (If driven Low, silences boot messages from normal boot. Has internal pull-up, so unconnected = High = normal output.)
GPIO_USER, //16 IO GPIO16, HS1_DATA4, U2RXD, EMAC_CLK_OUT
GPIO_USER, //17 IO GPIO17, HS1_DATA5, U2TXD, EMAC_CLK_OUT_180
GPIO_USER, //18 IO GPIO18, VSPICLK, HS1_DATA7
GPIO_USER, //19 IO GPIO19, VSPIQ, U0CTS, EMAC_TXD0
0, //20
0, //21 IO GPIO21, VSPIHD, EMAC_TX_EN
GPIO_USER, //22 IO LED GPIO22, VSPIWP, U0RTS, EMAC_TXD1
GPIO_USER, //23 IO GPIO23, VSPID, HS1_STROBE
0, //24
GPIO_USER, //25 IO GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0
GPIO_USER, //26 IO GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1
GPIO_USER, //27 IO GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17, EMAC_RX_DV
0, //28
0, //29
0, //30
0, //31
GPIO_USER, //32 IO GPIO32, XTAL_32K_P (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9
GPIO_USER, //33 IO GPIO33, XTAL_32K_N (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8
GPIO_USER, //34 I NO PULLUP GPIO34, ADC1_CH6, RTC_GPIO4
GPIO_USER, //35 I NO PULLUP GPIO35, ADC1_CH7, RTC_GPIO5
GPIO_USER, //36 I NO PULLUP GPIO36, SENSOR_VP, ADC_H, ADC1_CH0, RTC_GPIO0
0, //37 NO PULLUP
0, //38 NO PULLUP
GPIO_USER //39 I NO PULLUP GPIO39, SENSOR_VN, ADC1_CH3, ADC_H, RTC_GPIO3
}
};
#endif // ESP32
#endif // _TASMOTA_TEMPLATE_ESP32_H_

View File

@ -48,7 +48,7 @@ enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1, UPL_TASMOTASLAVE };
static const char * HEADER_KEYS[] = { "User-Agent", };
const char HTTP_HEADER[] PROGMEM =
const char HTTP_HEADER1[] PROGMEM =
"<!DOCTYPE html><html lang=\"" D_HTML_LANGUAGE "\" class=\"\">"
"<head>"
"<meta charset='utf-8'>"
@ -848,7 +848,7 @@ void WSContentStart_P(const char* title, bool auth)
if (title != nullptr) {
char ctitle[strlen_P(title) +1];
strcpy_P(ctitle, title); // Get title from flash to RAM
WSContentSend_P(HTTP_HEADER, SettingsText(SET_FRIENDLYNAME1), ctitle);
WSContentSend_P(HTTP_HEADER1, SettingsText(SET_FRIENDLYNAME1), ctitle);
}
}
@ -1266,7 +1266,7 @@ bool HandleRootStatusRefresh(void)
#ifdef USE_SHUTTER
int32_t ShutterWebButton;
if (ShutterWebButton = IsShutterWebButton(device)) {
snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_TOGGLEUP) : PSTR(D_CMND_SHUTTER_TOGGLEDOWN));
snprintf_P(svalue, sizeof(svalue), PSTR("ShutterPosition%d %s"), abs(ShutterWebButton), (ShutterWebButton>0) ? PSTR(D_CMND_SHUTTER_STOPOPEN) : PSTR(D_CMND_SHUTTER_STOPCLOSE));
ExecuteWebCommand(svalue, SRC_WEBGUI);
} else {
#endif // USE_SHUTTER
@ -2175,7 +2175,7 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1}2&nbsp;")); // Empty line
WSContentSend_P(PSTR("}1" D_ESP_CHIP_ID "}2%d"), ESP.getChipId());
WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP.getFlashChipId());
WSContentSend_P(PSTR("}1" D_FLASH_CHIP_ID "}20x%06X"), ESP_getFlashChipId());
WSContentSend_P(PSTR("}1" D_FLASH_CHIP_SIZE "}2%dkB"), ESP.getFlashChipRealSize() / 1024);
WSContentSend_P(PSTR("}1" D_PROGRAM_FLASH_SIZE "}2%dkB"), ESP.getFlashChipSize() / 1024);
WSContentSend_P(PSTR("}1" D_PROGRAM_SIZE "}2%dkB"), ESP.getSketchSize() / 1024);

View File

@ -950,17 +950,21 @@ public:
// only if non-multi channel
// We apply dimmer in priority to RGB
uint8_t bri = _state->DimmerToBri(Settings.light_dimmer);
// The default values are #FFFFFFFFFF, in this case we avoid setting all channels
// at the same time, see #6534 and #8120
if ((DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) &&
(DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) {
_state->setBriCT(bri);
_state->setBriRGB(bri);
_state->setColorMode(LCM_RGB);
}
if (Settings.light_color[0] + Settings.light_color[1] + Settings.light_color[2] > 0) {
// The default values are #FFFFFFFFFF, in this case we avoid setting all channels
// at the same time, see #6534
if ( (DEFAULT_LIGHT_COMPONENT == Settings.light_color[0]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[1]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[2]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[3]) &&
(DEFAULT_LIGHT_COMPONENT == Settings.light_color[4]) &&
(DEFAULT_LIGHT_DIMMER == Settings.light_dimmer) ) {
_state->setColorMode(LCM_RGB);
}
_state->setBriRGB(bri);
} else {
_state->setBriCT(bri);
@ -1216,6 +1220,7 @@ bool LightModuleInit(void)
if (XlgtCall(FUNC_MODULE_INIT)) {
// serviced
}
#ifdef ESP8266
else if (SONOFF_BN == my_module_type) { // PWM Single color led (White)
light_type = LT_PWM1;
}
@ -1234,6 +1239,7 @@ bool LightModuleInit(void)
}
light_type = LT_PWM2;
}
#endif // ESP8266
if (light_type > LT_BASIC) {
devices_present++;
@ -1701,12 +1707,12 @@ void LightAnimate(void)
// or set a maximum of PWM_MAX_SLEEP if light is on or Fade is running
if (Light.power || Light.fade_running) {
if (Settings.sleep > PWM_MAX_SLEEP) {
sleep = PWM_MAX_SLEEP; // set a maxumum value of 50 milliseconds to ensure that animations are smooth
ssleep = PWM_MAX_SLEEP; // set a maxumum value of 50 milliseconds to ensure that animations are smooth
} else {
sleep = Settings.sleep; // or keep the current sleep if it's lower than 50
ssleep = Settings.sleep; // or keep the current sleep if it's lower than 50
}
} else {
sleep = Settings.sleep;
ssleep = Settings.sleep;
}
if (!Light.power) { // All channels powered off
@ -1891,11 +1897,12 @@ void LightAnimate(void)
bool isChannelGammaCorrected(uint32_t channel) {
if (!Settings.light_correction) { return false; } // Gamma correction not activated
if (channel >= Light.subtype) { return false; } // Out of range
#ifdef ESP8266
if (PHILIPS == my_module_type) {
if ((LST_COLDWARM == Light.subtype) && (1 == channel)) { return false; } // PMW reserved for CT
if ((LST_RGBCW == Light.subtype) && (4 == channel)) { return false; } // PMW reserved for CT
}
#endif // ESP8266
return true;
}
@ -2070,6 +2077,7 @@ void calcGammaBulbs(uint16_t cur_col_10[5]) {
uint16_t white_bri10 = cur_col_10[cw0] + cur_col_10[cw1]; // cumulated brightness
uint16_t white_bri10_1023 = (white_bri10 > 1023) ? 1023 : white_bri10; // max 1023
#ifdef ESP8266
if (PHILIPS == my_module_type) { // channel 1 is the color tone, mapped to cold channel (0..255)
// Xiaomi Philips bulbs follow a different scheme:
cur_col_10[cw1] = light_state.getCT10bits();
@ -2079,7 +2087,9 @@ void calcGammaBulbs(uint16_t cur_col_10[5]) {
} else {
cur_col_10[cw0] = white_bri10_1023; // no gamma, extend to 10 bits
}
} else if (Settings.light_correction) {
} else
#endif // ESP8266
if (Settings.light_correction) {
// if sum of both channels is > 255, then channels are probably uncorrelated
if (white_bri10 <= 1031) { // take a margin of 8 above 1023 to account for rounding errors
// we calculate the gamma corrected sum of CW + WW
@ -2631,7 +2641,9 @@ void CmndDimmerRange(void)
Settings.dimmer_hw_min = parm[1];
Settings.dimmer_hw_max = parm[0];
}
#ifdef ESP8266
if (PWM_DIMMER != my_module_type) restart_flag = 2;
#endif // ESP8266
}
Response_P(PSTR("{\"" D_CMND_DIMMER_RANGE "\":{\"Min\":%d,\"Max\":%d}}"), Settings.dimmer_hw_min, Settings.dimmer_hw_max);
}

View File

@ -565,6 +565,7 @@ bool Xdrv06(uint8_t function)
{
bool result = false;
#ifdef ESP8266
if (SONOFF_BRIDGE == my_module_type) {
switch (function) {
case FUNC_SERIAL:
@ -582,6 +583,7 @@ bool Xdrv06(uint8_t function)
break;
}
}
#endif // ESP8266
return result;
}

View File

@ -556,8 +556,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
if (msg.data_len == 1) {
// COMMAND
tempchar[0] = msg.data[0];
tempchar[1] = '\0';
sprintf(tempchar,"%d",msg.data[0]);
} else {
// VALUE
float tempvar = knx.data_to_2byte_float(msg.data);

View File

@ -213,7 +213,11 @@ void HAssAnnounceRelayLight(void)
TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId());
#ifdef USE_LIGHT
if (is_light || PWM_DIMMER == my_module_type)
if (is_light
#ifdef ESP8266
|| PWM_DIMMER == my_module_type
#endif
)
{
char *brightness_command_topic = stemp1;
@ -423,10 +427,13 @@ void HAssAnnounceButtons(void)
uint8_t toggle = 1;
uint8_t hold = 0;
#ifdef ESP8266
if (!button_index && ((SONOFF_DUAL == my_module_type) || (CH4 == my_module_type)))
{
button_present = 1;
} else {
} else
#endif
{
if (pin[GPIO_KEY1 + button_index] < 99) {
button_present = 1;
}
@ -481,8 +488,8 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const
char subname[20];
mqtt_data[0] = '\0'; // Clear retained message
// Clear or Set topic
// Clear or Set topic
NoAlNumToUnderscore(subname, MultiSubName); //Replace all non alphaumeric characters to '_' to avoid topic name issues
snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%s"), ESP.getChipId(), sensorname, subname);
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);
@ -517,7 +524,7 @@ void HAssAnnounceSensor(const char *sensorname, const char *subsensortype, const
case 3:
snprintf_P(param1, sizeof(param1), PSTR("%s"), PressureUnit().c_str());
break;
// case 4: // Speed. Default to km/h if not set to have a graph representation under HAss
// case 4: // Speed. Default to km/h if not set to have a graph representation under HAss
// case 5:
// case 6:
// case 7:
@ -596,8 +603,8 @@ void HAssAnnounceSensors(void)
for (auto subsensor : subsensors) {
snprintf_P(NewSensorName, sizeof(NewSensorName), PSTR("%s %s"), NestedName, subsensor.key);
HAssAnnounceSensor(sensorname, NestedName, NewSensorName, 0, 0, 1, subsensor.key);
}
} else if (subsensor.value.is<JsonArray&>()) {
}
} else if (subsensor.value.is<JsonArray&>()) {
// If there is more than a value on sensor data, 'n' entitites will be created
JsonArray& subsensors = subsensor.value.as<JsonArray&>();
uint8_t subqty = subsensors.size();

View File

@ -838,7 +838,7 @@ void DisplayText(void)
if (!fill) {
*dp = 0;
} else {
linebuf[abs(fill)] = 0;
linebuf[abs(int(fill))] = 0;
}
if (fill<0) {
// right align

View File

@ -37,16 +37,18 @@ enum ShutterModes { SHT_OFF_OPEN__OFF_CLOSE, SHT_OFF_ON__OPEN_CLOSE, SHT_PULSE_O
enum ShutterButtonStates { SHT_NOT_PRESSED, SHT_PRESSED_MULTI, SHT_PRESSED_HOLD, SHT_PRESSED_IMMEDIATE, SHT_PRESSED_EXT_HOLD, SHT_PRESSED_MULTI_SIMULTANEOUS, SHT_PRESSED_HOLD_SIMULTANEOUS, SHT_PRESSED_EXT_HOLD_SIMULTANEOUS,};
const char kShutterCommands[] PROGMEM = D_PRFX_SHUTTER "|"
D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|"
D_CMND_SHUTTER_OPEN "|" D_CMND_SHUTTER_CLOSE "|" D_CMND_SHUTTER_TOGGLE "|" D_CMND_SHUTTER_STOP "|" D_CMND_SHUTTER_POSITION "|"
D_CMND_SHUTTER_OPENTIME "|" D_CMND_SHUTTER_CLOSETIME "|" D_CMND_SHUTTER_RELAY "|"
D_CMND_SHUTTER_SETHALFWAY "|" D_CMND_SHUTTER_SETCLOSE "|" D_CMND_SHUTTER_INVERT "|" D_CMND_SHUTTER_CLIBRATION "|"
D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS;
D_CMND_SHUTTER_MOTORDELAY "|" D_CMND_SHUTTER_FREQUENCY "|" D_CMND_SHUTTER_BUTTON "|" D_CMND_SHUTTER_LOCK "|" D_CMND_SHUTTER_ENABLEENDSTOPTIME "|" D_CMND_SHUTTER_INVERTWEBBUTTONS "|"
D_CMND_SHUTTER_STOPOPEN "|" D_CMND_SHUTTER_STOPCLOSE "|" D_CMND_SHUTTER_STOPTOGGLE "|" D_CMND_SHUTTER_STOPPOSITION;
void (* const ShutterCommand[])(void) PROGMEM = {
&CmndShutterOpen, &CmndShutterClose, &CmndShutterStop, &CmndShutterPosition,
&CmndShutterOpen, &CmndShutterClose, &CmndShutterToggle, &CmndShutterStop, &CmndShutterPosition,
&CmndShutterOpenTime, &CmndShutterCloseTime, &CmndShutterRelay,
&CmndShutterSetHalfway, &CmndShutterSetClose, &CmndShutterInvert, &CmndShutterCalibration , &CmndShutterMotorDelay,
&CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons};
&CmndShutterFrequency, &CmndShutterButton, &CmndShutterLock, &CmndShutterEnableEndStopTime, &CmndShutterInvertWebButtons,
&CmndShutterStopOpen, &CmndShutterStopClose, &CmndShutterStopToggle, &CmndShutterStopPosition};
const char JSON_SHUTTER_POS[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Position\":%d,\"Direction\":%d,\"Target\":%d}";
const char JSON_SHUTTER_BUTTON[] PROGMEM = "\"" D_PRFX_SHUTTER "%d\":{\"Button%d\":%d}";
@ -677,7 +679,13 @@ void ShutterButtonHandler(void)
CmndShutterStop();
} else {
XdrvMailbox.payload = position = (position-1)<<1;
CmndShutterPosition();
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SHT: shutter %d -> %d"), shutter_index+1, position);
if (102 == position) {
XdrvMailbox.payload = XdrvMailbox.index;
CmndShutterToggle();
} else {
CmndShutterPosition();
}
if (Settings.shutter_button[button_index] & ((0x01<<26)<<pos_press_index)) {
// MQTT broadcast to grouptopic
char scommand[CMDSZ];
@ -701,7 +709,6 @@ void ShutterButtonHandler(void)
ResponseJsonEnd();
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_PRFX_SHUTTER));
XdrvRulesProcess();
}
}
@ -718,7 +725,7 @@ void ShutterSetPosition(uint32_t device, uint32_t position)
void CmndShutterOpen(void)
{
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.index);
if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) {
XdrvMailbox.index = XdrvMailbox.payload;
}
@ -727,9 +734,21 @@ void CmndShutterOpen(void)
CmndShutterPosition();
}
void CmndShutterStopOpen(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
uint32_t index = XdrvMailbox.index-1;
if (Shutter.direction[index]) {
CmndShutterStop();
} else {
CmndShutterOpen();
}
}
}
void CmndShutterClose(void)
{
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload open: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.i);
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload close: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.index);
if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) {
XdrvMailbox.index = XdrvMailbox.payload;
}
@ -739,6 +758,45 @@ void CmndShutterClose(void)
CmndShutterPosition();
}
void CmndShutterStopClose(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
uint32_t index = XdrvMailbox.index-1;
if (Shutter.direction[index]) {
CmndShutterStop();
} else {
CmndShutterClose();
}
}
}
void CmndShutterToggle(void)
{
//AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Payload toggle: %d, i %d"), XdrvMailbox.payload, XdrvMailbox.index);
if ((1 == XdrvMailbox.index) && (XdrvMailbox.payload != -99)) {
XdrvMailbox.index = XdrvMailbox.payload;
}
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
uint32_t index = XdrvMailbox.index-1;
XdrvMailbox.payload = (50 < ShutterRealToPercentPosition(Shutter.real_position[index], index)) ? 0 : 100;
XdrvMailbox.data_len = 0;
last_source = SRC_WEBGUI;
CmndShutterPosition();
}
}
void CmndShutterStopToggle(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
uint32_t index = XdrvMailbox.index-1;
if (Shutter.direction[index]) {
CmndShutterStop();
} else {
CmndShutterToggle();
}
}
}
void CmndShutterStop(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
@ -779,15 +837,15 @@ void CmndShutterPosition(void)
// special handling fo UP,DOWN,TOGGLE,STOP command comming with payload -99
if ((XdrvMailbox.data_len > 1) && (XdrvMailbox.payload <= 0)) {
//UpperCase(XdrvMailbox.data, XdrvMailbox.data);
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP))) {
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_UP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_OPEN) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN))) {
CmndShutterOpen();
return;
}
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN))) {
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_DOWN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_CLOSE) || ((Shutter.direction[index]==0) && !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE))) {
CmndShutterClose();
return;
}
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEUP) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_TOGGLEDOWN)))) {
if (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOP) || ((Shutter.direction[index]) && (!strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPOPEN) || !strcasecmp(XdrvMailbox.data,D_CMND_SHUTTER_STOPCLOSE)))) {
XdrvMailbox.payload = -99;
CmndShutterStop();
return;
@ -861,6 +919,18 @@ void CmndShutterPosition(void)
}
}
void CmndShutterStopPosition(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
uint32_t index = XdrvMailbox.index-1;
if (Shutter.direction[index]) {
XdrvMailbox.payload = -99;
CmndShutterStop();
} else {
CmndShutterPosition();
}
}
}
void CmndShutterOpenTime(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= shutters_present)) {
@ -928,10 +998,10 @@ void CmndShutterButton(void)
// (setting>>28)&(0x01) : mqtt broadcast tripple press
// (setting>>27)&(0x01) : mqtt broadcast double press
// (setting>>26)&(0x01) : mqtt broadcast single press
// (setting>>20)&(0x3f) : shutter_position hold; 0 disabled, 1..101 == 0..100%
// (setting>>14)&(0x3f) : shutter_position tripple press 0 disabled, 1..101 == 0..100%
// (setting>> 8)&(0x3f) : shutter_position double press 0 disabled, 1..101 == 0..100%
// (setting>> 2)&(0x3f) : shutter_position single press 0 disabled, 1..101 == 0..100%
// (setting>>20)&(0x3f) : shutter_position hold; 0 disabled, 1..101 == 0..100%, 102 == toggle
// (setting>>14)&(0x3f) : shutter_position tripple press 0 disabled, 1..101 == 0..100%, 102 == toggle
// (setting>> 8)&(0x3f) : shutter_position double press 0 disabled, 1..101 == 0..100%, 102 == toggle
// (setting>> 2)&(0x3f) : shutter_position single press 0 disabled, 1..101 == 0..100%, 102 == toggle
// (setting>> 0)&(0x03) : shutter_index
if (XdrvMailbox.data_len > 0) {
uint32_t i = 0;
@ -945,10 +1015,16 @@ void CmndShutterButton(void)
// Loop through the data string, splitting on ' ' seperators.
for (char *str = strtok_r(data_copy, " ", &str_ptr); str && i < (1+4+4+1); str = strtok_r(nullptr, " ", &str_ptr), i++) {
int field;
if (str[0] == '-') {
field = -1;
} else {
field = atoi(str);
switch (str[0]) {
case '-':
field = -1;
break;
case 't':
field = 102;
break;
default:
field = atoi(str);
break;
}
switch (i) {
case 0:
@ -971,18 +1047,22 @@ void CmndShutterButton(void)
setting |= (((100>>1)+1)<<2) | (((0>>1)+1)<<8) | (((50>>1)+1)<<14);
isShortCommand = true;
break;
} else if (!strcmp_P(str, PSTR("toggle"))) {
setting |= (((102>>1)+1)<<2) | (((50>>1)+1)<<8);
isShortCommand = true;
break;
}
case 2:
if (isShortCommand) {
if ((field==1) && (setting & (0x3F<<(2+6*3))))
// if short command up or down then also enable MQTT broadcast
// if short command up or down (hold press position set) then also enable MQTT broadcast
setting |= (0x3<<29);
done = true;
break;
}
case 3:
case 4:
if ((field >= -1) && (field<=100))
if ((field >= -1) && (field<=102))
setting |= (((field>>1)+1)<<(i*6 + (2-6)));
break;
case 5:
@ -1023,8 +1103,12 @@ void CmndShutterButton(void)
for (uint32_t j=0 ; j < 4 ; j++) {
int8_t pos = (((setting>> (2+6*j))&(0x3f))-1)<<1;
if (pos>=0)
setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos);
if (0 <= pos)
if (102 == pos) {
setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" t"));
} else {
setting_chr_ptr += snprintf_P(setting_chr_ptr, 5, PSTR(" %d"), pos);
}
else
setting_chr_ptr += sprintf_P(setting_chr_ptr, PSTR(" -"));
}

169
tasmota/xdrv_38_ping.ino Normal file
View File

@ -0,0 +1,169 @@
/*
xdrv_38_ping.ino - support for ICMP Ping
Copyright (C) 2020 Theo Arends and Stephan Hadinger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_PING
#define XDRV_38 38
#include <ping.h>
#include <vector>
const char kPingCommands[] PROGMEM = "|" // no prefix
D_CMND_PING
;
void (* const PingCommand[])(void) PROGMEM = {
&CmndPing,
};
// inspired by https://github.com/dancol90/ESP8266Ping
typedef struct Ping_t {
ping_option opt; // extend the ping_option structure with internal values
uint16_t total_count; // total count if packets sent
uint16_t timeout_count; // time-outs (no responses)
uint32_t min_time; // minimum time in ms for a successful response
uint32_t max_time; // maximum time in ms for a successful response
uint32_t sum_time; // cumulated time in ms for all successful responses (used to compute the average)
bool done; // indicates the ping campaign is finished
} Ping_t;
std::vector<Ping_t*> pings = {};
extern "C" {
// callbacks for ping
// called after a ping response is received or time-out
void ICACHE_RAM_ATTR ping_recv_cb(Ping_t *ping, struct ping_resp *p_resp) {
// If successful
if (p_resp->ping_err >= 0) {
uint32_t resp_time = p_resp->resp_time;
ping->sum_time += resp_time;
if (resp_time < ping->min_time) { ping->min_time = resp_time; }
if (resp_time > ping->max_time) { ping->max_time = resp_time; }
}
}
// called after the ping campaign is finished
void ICACHE_RAM_ATTR ping_sent_cb(Ping_t *ping, struct ping_resp *p_resp) {
// copy counters to build the MQTT response
ping->total_count = p_resp->total_count;
ping->timeout_count = p_resp->timeout_count;
ping->done = true;
}
}
// Check if any ping requests is completed, and publish the results
void PingResponsePoll(void) {
for (auto it = pings.begin(); it != pings.end(); it++) {
Ping_t *ping = *it;
if (ping->done) {
uint32_t success = ping->total_count - ping->timeout_count;
uint32_t ip = ping->opt.ip;
// Serial.printf(
// "DEBUG ping_sent_cb: ping reply\n"
// "\tsuccess_count = %d \n"
// "\ttimeout_count = %d \n"
// "\tmin_time = %d \n"
// "\tmax_time = %d \n"
// "\tavg_time = %d \n",
// success, ping->timeout_count,
// ping->min_time, ping->max_time,
// success ? ping->sum_time / success : 0
// );
Response_P(PSTR("{\"" D_JSON_PING "\":{\"%d.%d.%d.%d\":{"
"\"Reachable\":%s"
",\"Success\":%d"
",\"Timeout\":%d"
",\"MinTime\":%d"
",\"MaxTime\":%d"
",\"AvgTime\":%d"
"}}}"),
ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, ip >> 24,
success ? "true" : "false",
success, ping->timeout_count,
ping->min_time, ping->max_time,
success ? ping->sum_time / success : 0
);
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_PING));
XdrvRulesProcess();
pings.erase(it--); // remove from list
delete ping; // free memory allocated
}
}
}
void CmndPing(void) {
uint32_t count = XdrvMailbox.index;
IPAddress ip;
RemoveSpace(XdrvMailbox.data);
if (count > 60) { count = 60; }
if (WiFi.hostByName(XdrvMailbox.data, ip)) {
Ping_t *ping = new Ping_t();
memset(ping, 0, sizeof(Ping_t ));
ping->min_time = UINT32_MAX;
ping_option &opt = ping->opt;
opt.count = count;
opt.coarse_time = 1; // wait 1 second between messages
opt.ip = ip;
// callbacks
opt.recv_function = (ping_recv_function) ping_recv_cb; // at each response or time-out
opt.sent_function = (ping_sent_function) ping_sent_cb; // when all packets have been sent and reveived
if (ping_start(&opt)) {
pings.push_back(ping);
ResponseCmndDone();
} else {
ResponseCmndChar_P(PSTR("Unable to send Ping"));
delete ping;
}
} else {
ResponseCmndChar_P(PSTR("Unable to resolve IP address"));
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdrv38(uint8_t function)
{
bool result = false;
switch (function) {
case FUNC_EVERY_250_MSECOND:
PingResponsePoll();
break;
case FUNC_COMMAND:
result = DecodeCommand(kPingCommands, PingCommand);
break;
}
return result;
}
#endif // USE_PING

View File

@ -0,0 +1,306 @@
/*
xdsp_11_sevenseg.ino - Display seven segment support for Tasmota
Copyright (C) 2020 Theo Arends and Adafruit
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_I2C
#ifdef USE_DISPLAY
#ifdef USE_DISPLAY_SEVENSEG
#define XDSP_11 11
#define XI2C_47 47 // See I2CDEVICES.md
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h> // Seven segment LED
Adafruit_7segment sevenseg = Adafruit_7segment();
uint8_t sevenseg_state = 0;
/*********************************************************************************************/
void SevensegWrite(void)
{
sevenseg.writeDisplay();
}
void SevensegClear(void)
{
sevenseg.clear();
SevensegWrite();
}
/*********************************************************************************************/
void SevensegInitMode(void)
{
sevenseg.setBrightness(Settings.display_dimmer);
sevenseg.blinkRate(0); // 0 - 3
SevensegClear();
}
void SevensegInit(uint8_t mode)
{
switch(mode) {
case DISPLAY_INIT_MODE:
case DISPLAY_INIT_PARTIAL:
case DISPLAY_INIT_FULL:
SevensegInitMode();
break;
}
}
void SevensegInitDriver(void)
{
if (!Settings.display_model) {
if (I2cSetDevice(SEVENSEG_ADDRESS1)) {
Settings.display_model = XDSP_11;
}
}
if (XDSP_11 == Settings.display_model) {
sevenseg_state = 1;
sevenseg.begin(SEVENSEG_ADDRESS1);
Settings.display_width = 4;
Settings.display_height = 1;
SevensegInitMode();
}
}
void SevensegOnOff(void)
{
if (!disp_power) { SevensegClear(); }
}
void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8_t flag)
{
uint16_t number = 0;
boolean hasnumber= false;
uint8_t dots= 0;
boolean t=false;
boolean T=false;
boolean d=false;
boolean hex=false;
boolean done=false;
boolean s=false;
for (int i=0; (str[i]!='\0') && (!done); i++) {
// [prefix(es) chars]digits
// Some combinations won't make sense.
// Reference: https://learn.adafruit.com/adafruit-led-backpack/1-2-inch-7-segment-backpack-arduino-wiring-and-setup
// Some sample valid combinations:
// 787 -> 787
// x47 -> 2F
// st:241 -> 04:01
// sT241 -> 4 01
switch (str[i]) {
case 'x': // print given dec value as hex
hex = true;
break;
case ':': // print colon
dots |= 0x02;
break;
case '^': // print top_left_dot
dots |= 0x08;
break;
case 'v': // print bottom_left_dot
dots |= 0x04;
break;
case '.': // print ampm
dots |= 0x10;
break;
case 'T': // print as time 12 format
t = true;
break;
case 't': // print as time 24 format
T = true;
break;
case 's': // duration in seconds
s = true;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
hasnumber= true;
number = atoi(str+i);
done = true;
break;
default: // unknown format, ignore
break;
}
}
if (s) {
// number is duration in seconds
hex = false;
int hour = number/60/60;
int minute = (number/60)%60;
if (hour) {
// HH:MM
number = hour*100 + minute;
} else {
// MM:SS
number = minute*100 + number%60;
}
}
if (hasnumber) {
if (hex) {
sevenseg.print(number, HEX);
} else {
sevenseg.print(number, DEC);
}
}
if (dots) {
sevenseg.writeDigitRaw(2, dots);
}
sevenseg.writeDisplay();
}
/*********************************************************************************************/
#ifdef USE_DISPLAY_MODES1TO5
void SevensegTime(boolean time_24)
{
uint hours = RtcTime.hour;
uint minutes = RtcTime.minute;
uint second = RtcTime.second;
uint16_t displayValue = hours * 100 + minutes;
uint16_t dots = 0;
// Do 24 hour to 12 hour format conversion when required.
if (!time_24) {
// Handle when hours are past 12 by subtracting 12 hours (1200 value).
if (hours > 12) {
displayValue -= 1200;
}
// Handle hour 0 (midnight) being shown as 12.
else if (hours == 0) {
displayValue += 1200;
}
}
// Now print the time value to the display.
sevenseg.print(displayValue, DEC);
// Add zero padding when in 24 hour mode and it's midnight.
// In this case the print function above won't have leading 0's
// which can look confusing. Go in and explicitly add these zeros.
if (time_24) {
if (hours == 0) {
// Pad hour 0.
sevenseg.writeDigitNum(1, 0);
// Also pad when the 10's minute is 0 and should be padded.
if (minutes < 10) {
sevenseg.writeDigitNum(3, 0);
}
}
if (hours < 10) {
// Always have 4 digits time
sevenseg.writeDigitNum(0, 0);
}
} else {
// Identify and display AM/PM
if (hours >= 12) {
dots |= 0x10;
}
}
sevenseg.writeDigitRaw(2, dots |= ((second%2) << 1));
sevenseg.writeDisplay();
}
#endif // USE_DISPLAY_MODES1TO5
void SevensegRefresh(void) // Every second
{
if (disp_power) {
if (Settings.display_mode) { // Mode 0 is User text
switch (Settings.display_mode) {
case 1: // Time 12
SevensegTime(false);
break;
case 2: // Time 24
SevensegTime(true);
break;
case 4: // Mqtt
case 3: // Local
case 5: { // Mqtt
break;
}
}
}
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xdsp11(uint8_t function)
{
if (!I2cEnabled(XI2C_47)) { return false; }
bool result = false;
if (FUNC_DISPLAY_INIT_DRIVER == function) {
SevensegInitDriver();
}
else if (XDSP_11 == Settings.display_model) {
switch (function) {
case FUNC_DISPLAY_MODEL:
result = true;
break;
case FUNC_DISPLAY_INIT:
SevensegInit(dsp_init);
break;
case FUNC_DISPLAY_CLEAR:
SevensegClear();
break;
case FUNC_DISPLAY_EVERY_SECOND:
SevensegRefresh();
break;
case FUNC_DISPLAY_ONOFF:
case FUNC_DISPLAY_POWER:
SevensegOnOff();
break;
case FUNC_DISPLAY_DRAW_STRING:
SevensegDrawStringAt(dsp_x, dsp_y, dsp_str, dsp_color, dsp_flag);
break;
}
}
return result;
}
#endif // USE_DISPLAY_SEVENSEG
#endif // USE_DISPLAY
#endif // USE_I2C

View File

@ -665,7 +665,7 @@ bool Xsns37(uint8_t function)
RfSnsAnalyzeRawSignal();
}
}
sleep = 0;
ssleep = 0;
break;
case FUNC_EVERY_SECOND:
RfSnsEverySecond();

137
tasmota/xsns_66_iAQ.ino Normal file
View File

@ -0,0 +1,137 @@
/*
xsns_66_iAQ.ino - Support for iAQ-Core - Indoor Air Quality Sensor Module
Copyright (C) 2020 Christian Baars 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_I2C
#ifdef USE_IAQ
#define XSNS_66 66
#define XI2C_46 46 // See I2CDEVICES.md
#define I2_ADR_IAQ 0x5a // collides with MLX90614 and maybe others
#define IAQ_STATUS_OK 0x00
#define IAQ_STATUS_BUSY 0x01
#define IAQ_STATUS_WARM 0x10
#define IAQ_STATUS_ERR 0x80
#define IAQ_STATUS_I2C_ERR 0xFF
struct {
int32_t resistance;
uint16_t pred;
uint16_t Tvoc;
uint8_t status;
bool ready;
} iAQ;
void IAQ_Init(void)
{
if (!I2cSetDevice(I2_ADR_IAQ)) { return; }
I2cSetActiveFound(I2_ADR_IAQ, "IAQ");
iAQ.ready = true;
}
void IAQ_Read(void)
{
uint8_t buf[9];
buf[2] = IAQ_STATUS_I2C_ERR; // populate entry with error code
Wire.requestFrom((uint8_t)I2_ADR_IAQ,sizeof(buf));
for( uint32_t i=0; i<9; i++ ) {
buf[i]= Wire.read();
}
// AddLog_P2(LOG_LEVEL_DEBUG, "iAQ: buffer %x %x %x %x %x %x %x %x %x ", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8]);
iAQ.pred = (buf[0]<<8) + buf[1];
iAQ.status = buf[2];
iAQ.resistance = ((uint32_t)buf[3]<<24) + ((uint32_t)buf[4]<<16) + ((uint32_t)buf[5]<<8) + (uint32_t)buf[6];
iAQ.Tvoc = (buf[7]<<8) + buf[8];
}
/*********************************************************************************************\
* Presentation
\*********************************************************************************************/
#ifdef USE_WEBSERVER
const char HTTP_SNS_IAQ[] PROGMEM =
"{s}iAQ-Core " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}" // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
"{s}iAQ-Core " D_TVOC "{m}%d " D_UNIT_PARTS_PER_BILLION "{e}";
const char HTTP_SNS_IAQ_ERROR[] PROGMEM =
"{s}iAQ-Core {m} %s {e}";
#endif
void IAQ_Show(uint8_t json)
{
IAQ_Read();
if (json) {
if (iAQ.status!=IAQ_STATUS_OK){
AddLog_P2(LOG_LEVEL_INFO, PSTR("iAQ: " D_ERROR " %x" ),iAQ.status);
return;
}
else {
ResponseAppend_P(PSTR(",\"IAQ\":{\"" D_JSON_ECO2 "\":%u,\"" D_JSON_TVOC "\":%u,\"" D_JSON_RESISTANCE "\":%u}"), iAQ.pred, iAQ.Tvoc, iAQ.resistance);
#ifdef USE_DOMOTICZ
if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, iAQ.pred);
#endif // USE_DOMOTICZ
}
#ifdef USE_WEBSERVER
} else {
switch(iAQ.status){
case IAQ_STATUS_OK:
WSContentSend_PD(HTTP_SNS_IAQ, iAQ.pred, iAQ.Tvoc);
break;
case IAQ_STATUS_WARM:
WSContentSend_PD(HTTP_SNS_IAQ_ERROR, D_START);
break;
default:
WSContentSend_PD(HTTP_SNS_IAQ_ERROR, D_ERROR);
}
#endif
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns66(byte function)
{
if (!I2cEnabled(XI2C_46)) { return false; }
bool result = false;
if (FUNC_INIT == function) {
IAQ_Init();
}
else if (iAQ.ready) {
switch (function) {
case FUNC_JSON_APPEND:
IAQ_Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
IAQ_Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_IAQ
#endif // USE_I2C

828
tasmota/xsns_67_as3935.ino Normal file
View File

@ -0,0 +1,828 @@
/*
xsns_67_as3935.ino - AS3935 Franklin Lightning Sensor support for Tasmota
Copyright (C) 2020 Martin Wagner
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_I2C
#ifdef USE_AS3935
/*********************************************************************************************\
* AS3935 Lightning Sensor
*
* I2C Address: 0x03
\*********************************************************************************************/
#define XSNS_67 67
#define XI2C_48 48 // See I2CDEVICES.md
#define D_NAME_AS3935 "AS3935"
#define AS3935_ADDR 0x03
// Reg mask shift
#define IRQ_TBL 0x03, 0x0F, 0
#define ENERGY_RAW_1 0x04, 0xFF, 0
#define ENERGY_RAW_2 0x05, 0xFF, 0
#define ENERGY_RAW_3 0x06, 0x1F, 0
#define LGHT_DIST 0x07, 0x3F, 0
#define DISP_TRCO 0x08, 0x20, 5
#define DISP_LCO 0x08, 0x80, 7
#define TUNE_CAPS 0x08, 0x0F, 0
#define AFE_GB 0x00, 0x3E, 0
#define WDTH 0x01, 0x0F, 0
#define NF_LEVEL 0x01, 0x70, 4
#define SPIKE_REJECT 0x02, 0x0F, 0
#define MIN_NUM_LIGH 0x02, 0x30, 4
#define DISTURBER 0x03, 0x20, 5
#define LCO_FDIV 0x03, 0xC0, 6
#define INDOORS 0x24
#define OUTDOORS 0x1C
// Translation
// http
#define D_AS3935_GAIN "gain:"
#define D_AS3935_ENERGY "energy:"
#define D_AS3935_DISTANCE "distance:"
#define D_AS3935_DISTURBER "disturber:"
#define D_AS3935_VRMS "µVrms:"
// http Message
#define D_AS3935_APRX "aprx.:"
#define D_AS3935_AWAY "away"
#define D_AS3935_LIGHT "lightning"
#define D_AS3935_OUT "lightning out of range"
#define D_AS3935_NOT "distance not determined"
#define D_AS3935_ABOVE "lightning overhead"
#define D_AS3935_NOISE "noise detected"
#define D_AS3935_DISTDET "disturber detected"
#define D_AS3935_INTNOEV "Interrupt with no Event!"
#define D_AS3935_NOMESS "listening..."
// CMD Status
#define D_AS3935_ON "On"
#define D_AS3935_OFF "Off"
#define D_AS3935_INDOORS "Indoors"
#define D_AS3935_OUTDOORS "Outdoors"
#define D_AS3935_CAL_FAIL "calibration failed"
#define D_AS3935_CAL_OK "calibration set to:"
// Global
const char HTTP_SNS_UNIT_KILOMETER[] PROGMEM = D_UNIT_KILOMETER;
// Http
const char HTTP_SNS_AS3935_ENERGY[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_ENERGY " {m}%d{e}";
const char HTTP_SNS_AS3935_DISTANZ[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_DISTANCE " {m}%u " D_UNIT_KILOMETER "{e}";
const char HTTP_SNS_AS3935_VRMS[] PROGMEM = "{s}" D_NAME_AS3935 " " D_AS3935_VRMS "{m}%#4u (%d){e}";
const char HTTP_SNS_AS3935_OUTDOORS[] PROGMEM = "{s}%s " D_AS3935_GAIN " {m}" D_AS3935_OUTDOORS " {e}";
const char HTTP_SNS_AS3935_INDOORS[] PROGMEM = "{s}%s " D_AS3935_GAIN " {m}" D_AS3935_INDOORS " {e}";
const char* const HTTP_SNS_AS3935_GAIN[] PROGMEM = {HTTP_SNS_AS3935_INDOORS, HTTP_SNS_AS3935_OUTDOORS};
const char HTTP_SNS_AS3935_DIST_ON[] PROGMEM = "{s}%s " D_AS3935_DISTURBER " {m}" D_AS3935_ON " {e}";
const char HTTP_SNS_AS3935_DIST_OFF[] PROGMEM = "{s}%s " D_AS3935_DISTURBER " {m}" D_AS3935_OFF " {e}";
const char* const HTTP_SNS_AS3935_DISTURBER[] PROGMEM = {HTTP_SNS_AS3935_DIST_OFF, HTTP_SNS_AS3935_DIST_ON};
// http Messages
const char HTTP_SNS_AS3935_EMPTY[] PROGMEM = "{s}%s: " D_AS3935_NOMESS "{e}";
const char HTTP_SNS_AS3935_OUT[] PROGMEM = "{s}%s: " D_AS3935_OUT "{e}";
const char HTTP_SNS_AS3935_NOT[] PROGMEM = "{s}%s: " D_AS3935_NOT "{e}";
const char HTTP_SNS_AS3935_ABOVE[] PROGMEM = "{s}%s: " D_AS3935_ABOVE "{e}";
const char HTTP_SNS_AS3935_NOISE[] PROGMEM = "{s}%s: " D_AS3935_NOISE "{e}";
const char HTTP_SNS_AS3935_DISTURB[] PROGMEM = "{s}%s: " D_AS3935_DISTDET "{e}";
const char HTTP_SNS_AS3935_INTNOEV[] PROGMEM = "{s}%s: " D_AS3935_INTNOEV "{e}";
const char HTTP_SNS_AS3935_MSG[] PROGMEM = "{s}%s: " D_AS3935_LIGHT " " D_AS3935_APRX " %d " D_UNIT_KILOMETER " " D_AS3935_AWAY "{e}";
const char* const HTTP_SNS_AS3935_TABLE_1[] PROGMEM = { HTTP_SNS_AS3935_EMPTY, HTTP_SNS_AS3935_MSG, HTTP_SNS_AS3935_OUT, HTTP_SNS_AS3935_NOT, HTTP_SNS_AS3935_ABOVE, HTTP_SNS_AS3935_NOISE, HTTP_SNS_AS3935_DISTURB, HTTP_SNS_AS3935_INTNOEV };
// Json
const char JSON_SNS_AS3935_EVENTS[] PROGMEM = ",\"%s\":{\"" D_JSON_EVENT "\":%d,\"" D_JSON_DISTANCE "\":%d,\"" D_JSON_ENERGY "\":%u}";
// Json Command
const char* const S_JSON_AS3935_COMMAND_ONOFF[] PROGMEM = {"\"" D_AS3935_OFF "\"","\"" D_AS3935_ON"\""};
const char* const S_JSON_AS3935_COMMAND_GAIN[] PROGMEM = {"\"" D_AS3935_INDOORS "\"", "\"" D_AS3935_OUTDOORS "\""};
const char* const S_JSON_AS3935_COMMAND_CAL[] PROGMEM = {"" D_AS3935_CAL_FAIL "","" D_AS3935_CAL_OK ""};
const char S_JSON_AS3935_COMMAND_STRING[] PROGMEM = "{\"" D_NAME_AS3935 "\":{\"%s\":%s}}";
const char S_JSON_AS3935_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_AS3935 "\":{\"%s\":%d}}";
const char S_JSON_AS3935_COMMAND_SETTINGS[] PROGMEM = "{\"" D_NAME_AS3935 "\":{\"Gain\":%s,\"NFfloor\":%d,\"uVrms\":%d,\"Tunecaps\":%d,\"MinNumLight\":%d,\"Rejektion\":%d,\"Wdthreshold\":%d,\"MinNFstage\":%d,\"NFAutoTime\":%d,\"DisturberAutoTime\":%d,\"Disturber\":%s,\"NFauto\":%s,\"Disturberauto\":%s,\"NFautomax\":%s,\"Mqttlightevent\":%s}}";
const char kAS3935_Commands[] PROGMEM = "setnf|setminstage|setml|default|setgain|settunecaps|setrej|setwdth|disttime|nftime|disturber|autonf|autodisturber|autonfmax|mqttevent|settings|calibrate";
enum AS3935_Commands { // commands for Console
CMND_AS3935_SET_NF, // Noise Floor Level, value from 0-7 (3 Bit)
CMND_AS3935_SET_MINNF, // Set Min Noise Floor Level when Autotune is active Value von 0-15
CMND_AS3935_SET_MINLIGHT, // Minimum number of lightning 0=1/1=5/2=9/3=16 Lightnings
CMND_AS3935_SET_DEF, // set default for Sensor and Settings
CMND_AS3935_SET_GAIN, // Set Inddoor/Outdoor
CMND_AS3935_SET_TUNE, // Internal Tuning Capacitors (from 0 to 120pF in steps of 8pf)
CMND_AS3935_SET_REJ, // Set Spike Rejection
CMND_AS3935_SET_WDTH, // Watchdog threshold
CMND_AS3935_DISTTIME, // Threshhold Time for Auto Disturber
CMND_AS3935_NFTIME, // Threshhold Time for NF-Autotune
CMND_AS3935_SET_DISTURBER, // Set Disturber on/off
CMND_AS3935_NF_AUTOTUNE, // Autotune the NF Noise
CMND_AS3935_DIST_AUTOTUNE, // Autotune Disturber on/off
CMND_AS3935_NF_ATUNE_BOTH, // Autotune over both Areas: INDOORS/OUDOORS
CMND_AS3935_MQTT_LIGHT_EVT, // mqtt only if lightning Irq
CMND_AS3935_SETTINGS, // Json output of all settings
CMND_AS3935_CALIBRATE // caps autocalibrate
};
struct AS3935STRUCT
{
bool autodist_activ = false;
volatile bool detected = false;
volatile bool dispLCO = 0;
uint8_t icount = 0;
uint8_t irq = 0;
uint8_t mqtt_irq = 0;
uint8_t http_irq = 0;
uint8_t http_count_start = 0;
int16_t http_distance = 0;
int16_t distance = 0;
uint16_t http_timer = 0;
uint16_t http_count = 0;
uint16_t nftimer = 0;
uint16_t disttimer = 0;
uint32_t intensity = 0;
uint32_t http_intensity = 0;
volatile uint32_t pulse = 0;
} as3935_sensor;
uint8_t as3935_active = 0;
void ICACHE_RAM_ATTR AS3935Isr() {
as3935_sensor.detected = true;
}
uint8_t AS3935ReadRegister(uint8_t reg, uint8_t mask, uint8_t shift) {
uint8_t data = I2cRead8(AS3935_ADDR, reg);
if (reg == 0x08) Settings.as3935_sensor_cfg[4] = data;
if (reg < 0x04) Settings.as3935_sensor_cfg[reg] = data;
return ((data & mask) >> shift);
}
void AS3935WriteRegister(uint8_t reg, uint8_t mask, uint8_t shift, uint8_t data) {
uint8_t currentReg = I2cRead8(AS3935_ADDR, reg);
currentReg &= (~mask);
data <<= shift;
data &= mask;
data |= currentReg;
I2cWrite8(AS3935_ADDR, reg, data);
if (reg == 0x08) Settings.as3935_sensor_cfg[4] = I2cRead8(AS3935_ADDR, reg);
if (reg < 0x04) Settings.as3935_sensor_cfg[reg] = I2cRead8(AS3935_ADDR, reg);
}
/********************************************************************************************/
// Autotune Caps
void ICACHE_RAM_ATTR AS3935CountFreq() {
if (as3935_sensor.dispLCO)
as3935_sensor.pulse++;
}
bool AS3935AutoTuneCaps(uint8_t irqpin) {
int32_t maxtune = 17500; // there max 3.5 % tol
uint8_t besttune;
AS3935WriteRegister(LCO_FDIV, 0); // Fdiv 16
delay(2);
for (uint8_t tune = 0; tune < 16; tune++) {
AS3935WriteRegister(TUNE_CAPS, tune);
delay(2);
AS3935WriteRegister(DISP_LCO,1);
delay(1);
as3935_sensor.dispLCO = true;
as3935_sensor.pulse = 0;
attachInterrupt(digitalPinToInterrupt(irqpin), AS3935CountFreq, RISING);
delay(200); // 100ms callback not work accurat for fequ. measure
as3935_sensor.dispLCO = false;
detachInterrupt(irqpin);
AS3935WriteRegister(DISP_LCO,0);
int32_t currentfreq = 500000 - ((as3935_sensor.pulse * 5) * 16);
if(currentfreq < 0) currentfreq = -currentfreq;
if(maxtune > currentfreq) {
maxtune = currentfreq;
besttune = tune;
}
}
if (maxtune >= 17500) // max. 3.5%
return false;
AS3935SetTuneCaps(besttune);
return true;
}
/********************************************************************************************/
// functions
void AS3935CalibrateRCO() {
I2cWrite8(AS3935_ADDR, 0x3D, 0x96);
AS3935WriteRegister(DISP_TRCO, 1);
delay(2);
AS3935WriteRegister(DISP_TRCO, 0);
}
uint8_t AS3935TransMinLights(uint8_t min_lights) {
if (5 > min_lights) {
return 0;
} else if (9 > min_lights) {
return 1;
} else if (16 > min_lights) {
return 2;
} else {
return 3;
}
}
uint8_t AS3935TranslMinLightsInt(uint8_t min_lights) {
switch (min_lights) {
case 0: return 1;
case 1: return 5;
case 2: return 9;
case 3: return 16;
}
}
uint8_t AS3935TranslIrq(uint8_t irq, uint8_t distance) {
switch(irq) {
case 0: return 7; // Interrupt with no IRQ
case 1: return 5; // Noise level too high
case 4: return 6; // Disturber detected
case 8:
if (distance == -1) return 2; // Lightning out of Distance
else if (distance == 0) return 3; // Distance cannot be determined
else if (distance == 1) return 4; // Storm is Overhead
else return 1; // Lightning with Distance detected
}
}
void AS3935CalcVrmsLevel(uint16_t &vrms, uint8_t &stage)
{
uint8_t room = AS3935GetGain();
uint8_t nflev = AS3935GetNoiseFloor();
if (room == 0x24)
{
switch (nflev){
case 0x00:
vrms = 28;
break;
case 0x01:
vrms = 45;
break;
case 0x02:
vrms = 62;
break;
case 0x03:
vrms = 78;
break;
case 0x04:
vrms = 95;
break;
case 0x05:
vrms = 112;
break;
case 0x06:
vrms = 130;
break;
case 0x07:
vrms = 146;
break;
}
stage = nflev;
}
else
{
switch (nflev)
{
case 0x00:
vrms = 390;
break;
case 0x01:
vrms = 630;
break;
case 0x02:
vrms = 860;
break;
case 0x03:
vrms = 1100;
break;
case 0x04:
vrms = 1140;
break;
case 0x05:
vrms = 1570;
break;
case 0x06:
vrms = 1800;
break;
case 0x07:
vrms = 2000;
break;
}
stage = nflev + 8;
}
}
/********************************************************************************************/
uint8_t AS3935GetIRQ() {
delay(2);
return AS3935ReadRegister(IRQ_TBL);
}
uint8_t AS3935GetDistance() {
return AS3935ReadRegister(LGHT_DIST);
}
int16_t AS3935CalcDistance() {
uint8_t dist = AS3935GetDistance();
switch (dist) {
case 0x3F: return -1; // Out of Range
case 0x01: return 1; // Storm is Overhead
case 0x00: return 0; // Distance cannot be determined
default:
if (40 < dist){
return 40;// limited because higher is not accurate
}
return dist;
}
}
uint32_t AS3935GetIntensity() {
uint32_t nrgy_raw = (AS3935ReadRegister(ENERGY_RAW_3) << 8);
nrgy_raw |= AS3935ReadRegister(ENERGY_RAW_2);
nrgy_raw <<= 8;
nrgy_raw |= AS3935ReadRegister(ENERGY_RAW_1);
return nrgy_raw;
}
uint8_t AS3935GetTuneCaps() {
return AS3935ReadRegister(TUNE_CAPS);
}
void AS3935SetTuneCaps(uint8_t tune) {
AS3935WriteRegister(TUNE_CAPS, tune);
delay(2);
AS3935CalibrateRCO();
}
uint8_t AS3935GetDisturber() {
return AS3935ReadRegister(DISTURBER);
}
uint8_t AS3935SetDisturber(uint8_t stat) {
AS3935WriteRegister(DISTURBER, stat);
}
uint8_t AS3935GetMinLights() {
return AS3935ReadRegister(MIN_NUM_LIGH);
}
uint8_t AS3935SetMinLights(uint8_t stat) {
AS3935WriteRegister(MIN_NUM_LIGH, stat);
}
uint8_t AS3935GetNoiseFloor() {
return AS3935ReadRegister(NF_LEVEL);
}
uint8_t AS3935SetNoiseFloor(uint8_t noise) {
AS3935WriteRegister(NF_LEVEL , noise);
}
uint8_t AS3935GetGain() {
if (AS3935ReadRegister(AFE_GB) == OUTDOORS)
return OUTDOORS;
return INDOORS;
}
uint8_t AS3935SetGain(uint8_t room) {
AS3935WriteRegister(AFE_GB, room);
}
uint8_t AS3935GetGainInt() {
if (AS3935ReadRegister(AFE_GB) == OUTDOORS)
return 1;
return 0;
}
uint8_t AS3935GetSpikeRejection() {
return AS3935ReadRegister(SPIKE_REJECT);
}
void AS3935SetSpikeRejection(uint8_t rej) {
AS3935WriteRegister(SPIKE_REJECT, rej);
}
uint8_t AS3935GetWdth() {
return AS3935ReadRegister(WDTH);
}
void AS3935SetWdth(uint8_t wdth) {
AS3935WriteRegister(WDTH, wdth);
}
bool AS3935AutoTune(){
detachInterrupt(pin[GPIO_AS3935]);
bool result = AS3935AutoTuneCaps(pin[GPIO_AS3935]);
attachInterrupt(digitalPinToInterrupt(pin[GPIO_AS3935]), AS3935Isr, RISING);
return result;
}
/********************************************************************************************/
// Noise Floor autofunctions
bool AS3935LowerNoiseFloor() {
uint8_t noise = AS3935GetNoiseFloor();
uint16_t vrms;
uint8_t stage;
AS3935CalcVrmsLevel(vrms, stage);
if (Settings.as3935_functions.nf_autotune_both) {
if (stage == 8 && stage > Settings.as3935_parameter.nf_autotune_min) {
AS3935SetGain(INDOORS);
AS3935SetNoiseFloor(7);
return true;
}
}
if (0 < noise && stage > Settings.as3935_parameter.nf_autotune_min) {
noise--;
AS3935SetNoiseFloor(noise);
return true;
}
return false;
}
bool AS3935RaiseNoiseFloor() {
uint8_t noise = AS3935GetNoiseFloor();
uint8_t room = AS3935GetGain();
if (Settings.as3935_functions.nf_autotune_both) {
if (7 == noise && room == INDOORS) {
AS3935SetGain(OUTDOORS);
AS3935SetNoiseFloor(0);
return true;
}
}
if (7 > noise) {
noise++;
AS3935SetNoiseFloor(noise);
return true;
}
return false;
}
/********************************************************************************************/
// init functions
bool AS3935SetDefault() {
I2cWrite8(AS3935_ADDR, 0x3C, 0x96); // Set default
delay(2);
Settings.as3935_sensor_cfg[0] = I2cRead8(AS3935_ADDR, 0x00);
Settings.as3935_sensor_cfg[1] = I2cRead8(AS3935_ADDR, 0x01);
Settings.as3935_sensor_cfg[2] = I2cRead8(AS3935_ADDR, 0x02);
Settings.as3935_sensor_cfg[3] = I2cRead8(AS3935_ADDR, 0x03);
Settings.as3935_sensor_cfg[4] = I2cRead8(AS3935_ADDR, 0x08);
Settings.as3935_parameter.nf_autotune_min = 0x00;
Settings.as3935_parameter.nf_autotune_time = 4;
Settings.as3935_parameter.dist_autotune_time = 1;
return true;
}
void AS3935InitSettings() {
if(Settings.as3935_functions.nf_autotune){
AS3935SetGain(INDOORS);
AS3935SetNoiseFloor(0);
}
I2cWrite8(AS3935_ADDR, 0x00, Settings.as3935_sensor_cfg[0]);
I2cWrite8(AS3935_ADDR, 0x01, Settings.as3935_sensor_cfg[1]);
I2cWrite8(AS3935_ADDR, 0x02, Settings.as3935_sensor_cfg[2]);
I2cWrite8(AS3935_ADDR, 0x03, Settings.as3935_sensor_cfg[3]);
I2cWrite8(AS3935_ADDR, 0x08, Settings.as3935_sensor_cfg[4]);
delay(2);
}
void AS3935Setup(void) {
if (Settings.as3935_sensor_cfg[0] == 0x00) {
AS3935SetDefault();
} else {
AS3935InitSettings();
}
AS3935CalibrateRCO();
}
bool AS3935init() {
uint8_t ret = I2cRead8(AS3935_ADDR, 0x00);
if(INDOORS == ret || OUTDOORS == ret) // 0x24
return true;
return false;
}
void AS3935Detect(void) {
if (I2cActive(AS3935_ADDR)) return;
if (AS3935init())
{
I2cSetActiveFound(AS3935_ADDR, D_NAME_AS3935);
pinMode(pin[GPIO_AS3935], INPUT);
attachInterrupt(digitalPinToInterrupt(pin[GPIO_AS3935]), AS3935Isr, RISING);
AS3935Setup();
as3935_active = 1;
}
}
void AS3935EverySecond() {
if (as3935_sensor.detected) {
as3935_sensor.irq = AS3935GetIRQ(); // 1 =Noise, 4 = Disturber, 8 = storm
switch (as3935_sensor.irq) {
case 1:
if (Settings.as3935_functions.nf_autotune) {
if (AS3935RaiseNoiseFloor()) as3935_sensor.nftimer = 0;
}
break;
case 4:
if (Settings.as3935_functions.dist_autotune) {
AS3935SetDisturber(1);
as3935_sensor.autodist_activ = true;
}
break;
case 8:
as3935_sensor.intensity = AS3935GetIntensity();
as3935_sensor.distance = AS3935CalcDistance();
as3935_sensor.http_intensity = as3935_sensor.intensity;
as3935_sensor.http_distance = as3935_sensor.distance;
break;
}
// http show
as3935_sensor.http_irq = AS3935TranslIrq(as3935_sensor.irq, as3935_sensor.distance);
// mqtt publish
as3935_sensor.mqtt_irq = as3935_sensor.http_irq;
switch (as3935_sensor.mqtt_irq) {
case 5:
case 6:
if (!Settings.as3935_functions.mqtt_only_Light_Event) {
MqttPublishSensor();
as3935_sensor.http_timer = 10;
}
break;
default:
as3935_sensor.http_timer = 60;
MqttPublishSensor();
}
// clear mqtt events for Teleperiod
as3935_sensor.intensity = 0;
as3935_sensor.distance = 0;
as3935_sensor.mqtt_irq = 0;
// start http times
as3935_sensor.http_count_start = 1;
as3935_sensor.icount++; // Int counter
as3935_sensor.detected = false;
}
if (as3935_sensor.http_count_start) as3935_sensor.http_count++;
// clear Http
if (as3935_sensor.http_count == as3935_sensor.http_timer) {
as3935_sensor.http_count = 0;
as3935_sensor.http_count_start = 0;
as3935_sensor.http_intensity = 0;
as3935_sensor.http_distance = 0;
as3935_sensor.http_irq = 0;
}
// Noise Floor Autotune function
if (Settings.as3935_functions.nf_autotune) {
as3935_sensor.nftimer++;
if (as3935_sensor.nftimer > Settings.as3935_parameter.nf_autotune_time * 60) {
AS3935LowerNoiseFloor();
as3935_sensor.nftimer = 0;
}
}
// Disturber auto function
if (Settings.as3935_functions.dist_autotune) {
if (as3935_sensor.autodist_activ) as3935_sensor.disttimer++;
if (as3935_sensor.disttimer >= Settings.as3935_parameter.dist_autotune_time * 60) {
AS3935SetDisturber(0);
as3935_sensor.disttimer = 0;
as3935_sensor.autodist_activ = false;
}
}
}
bool AS3935Cmd(void) {
char command[CMDSZ];
uint8_t name_len = strlen(D_NAME_AS3935);
if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_AS3935), name_len)) {
uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kAS3935_Commands);
switch (command_code) {
case CMND_AS3935_SET_NF:
if (XdrvMailbox.data_len) {
if (15 >= XdrvMailbox.payload) {
AS3935SetNoiseFloor(XdrvMailbox.payload);
}
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetNoiseFloor());
break;
case CMND_AS3935_SET_MINNF:
if (XdrvMailbox.data_len) {
if (15 >= XdrvMailbox.payload) {
Settings.as3935_parameter.nf_autotune_min = XdrvMailbox.payload;
}
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.nf_autotune_min);
break;
case CMND_AS3935_SET_MINLIGHT:
if (XdrvMailbox.data_len) {
AS3935SetMinLights(AS3935TransMinLights(XdrvMailbox.payload));
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935TranslMinLightsInt(AS3935GetMinLights()));
break;
case CMND_AS3935_SET_DEF:
if (!XdrvMailbox.data_len) {
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935SetDefault());
}
break;
case CMND_AS3935_SET_GAIN:
if (XdrvMailbox.data_len > 6) {
uint8_t data_len = strlen(D_AS3935_OUTDOORS);
if (!strncasecmp_P(XdrvMailbox.data, PSTR(D_AS3935_OUTDOORS), data_len)) {
AS3935SetGain(OUTDOORS);
} else {
AS3935SetGain(INDOORS);
}
}
Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_GAIN[AS3935GetGainInt()]);
break;
case CMND_AS3935_SET_TUNE:
if (XdrvMailbox.data_len) {
if (15 >= XdrvMailbox.payload) {
AS3935SetTuneCaps(XdrvMailbox.payload);
}
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetTuneCaps());
break;
case CMND_AS3935_SET_REJ:
if (XdrvMailbox.data_len) {
if (15 >= XdrvMailbox.payload) {
AS3935SetSpikeRejection(XdrvMailbox.payload);
}
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetSpikeRejection());
break;
case CMND_AS3935_SET_WDTH:
if (XdrvMailbox.data_len) {
if (15 >= XdrvMailbox.payload) {
AS3935SetWdth(XdrvMailbox.payload);
}
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, AS3935GetWdth());
break;
case CMND_AS3935_DISTTIME:
if (XdrvMailbox.data_len) {
if (15 >= XdrvMailbox.payload) {
Settings.as3935_parameter.dist_autotune_time = XdrvMailbox.payload;
}
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.dist_autotune_time);
break;
case CMND_AS3935_NFTIME:
if (XdrvMailbox.data_len) {
if (15 >= XdrvMailbox.payload) {
Settings.as3935_parameter.nf_autotune_time = XdrvMailbox.payload;
}
}
Response_P(S_JSON_AS3935_COMMAND_NVALUE, command, Settings.as3935_parameter.nf_autotune_time);
break;
case CMND_AS3935_SET_DISTURBER:
if (XdrvMailbox.data_len) {
if (2 > XdrvMailbox.payload) {
AS3935SetDisturber(XdrvMailbox.payload);
if (!XdrvMailbox.payload) Settings.as3935_functions.dist_autotune = 0;
}
}
Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[AS3935GetDisturber()]);
break;
case CMND_AS3935_NF_AUTOTUNE:
if (XdrvMailbox.data_len) {
if (2 > XdrvMailbox.payload) {
Settings.as3935_functions.nf_autotune = XdrvMailbox.payload;
}
}
Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.nf_autotune]);
break;
case CMND_AS3935_DIST_AUTOTUNE:
if (XdrvMailbox.data_len) {
if (2 > XdrvMailbox.payload) {
Settings.as3935_functions.dist_autotune = XdrvMailbox.payload;
}
}
Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.dist_autotune]);
break;
case CMND_AS3935_NF_ATUNE_BOTH:
if (XdrvMailbox.data_len) {
if (2 > XdrvMailbox.payload) {
Settings.as3935_functions.nf_autotune_both = XdrvMailbox.payload;
}
}
Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.nf_autotune_both]);
break;
case CMND_AS3935_MQTT_LIGHT_EVT:
if (XdrvMailbox.data_len) {
if (2 > XdrvMailbox.payload) {
Settings.as3935_functions.mqtt_only_Light_Event = XdrvMailbox.payload;
}
}
Response_P(S_JSON_AS3935_COMMAND_STRING, command, S_JSON_AS3935_COMMAND_ONOFF[Settings.as3935_functions.mqtt_only_Light_Event]);
break;
case CMND_AS3935_SETTINGS: {
if (!XdrvMailbox.data_len) {
uint8_t gain = AS3935GetGainInt();
uint16_t vrms;
uint8_t stage;
AS3935CalcVrmsLevel(vrms, stage);
uint8_t nf_floor = AS3935GetNoiseFloor();
uint8_t min_nf = Settings.as3935_parameter.nf_autotune_min;
uint8_t tunecaps = AS3935GetTuneCaps();
uint8_t minnumlight = AS3935TranslMinLightsInt(AS3935GetMinLights());
uint8_t disturber = AS3935GetDisturber();
uint8_t reinj = AS3935GetSpikeRejection();
uint8_t wdth = AS3935GetWdth();
uint8_t nfauto = Settings.as3935_functions.nf_autotune;
uint8_t distauto = Settings.as3935_functions.dist_autotune;
uint8_t nfautomax = Settings.as3935_functions.nf_autotune_both;
uint8_t jsonlight = Settings.as3935_functions.mqtt_only_Light_Event;
uint8_t nf_time = Settings.as3935_parameter.nf_autotune_time;
uint8_t dist_time =Settings.as3935_parameter.dist_autotune_time;
Response_P(S_JSON_AS3935_COMMAND_SETTINGS, S_JSON_AS3935_COMMAND_GAIN[gain], nf_floor, vrms, tunecaps, minnumlight, reinj, wdth, min_nf, nf_time, dist_time, S_JSON_AS3935_COMMAND_ONOFF[disturber], S_JSON_AS3935_COMMAND_ONOFF[nfauto], S_JSON_AS3935_COMMAND_ONOFF[distauto], S_JSON_AS3935_COMMAND_ONOFF[nfautomax], S_JSON_AS3935_COMMAND_ONOFF[jsonlight]);
}
}
break;
case CMND_AS3935_CALIBRATE: {
bool calreslt;
if (!XdrvMailbox.data_len) calreslt = AS3935AutoTune();
Response_P(S_JSON_AS3935_COMMAND_NVALUE, S_JSON_AS3935_COMMAND_CAL[calreslt], AS3935GetTuneCaps());
}
break;
default:
return false;
}
return true;
} else {
return false;
}
}
void AH3935Show(bool json)
{
if (json) {
ResponseAppend_P(JSON_SNS_AS3935_EVENTS, D_SENSOR_AS3935, as3935_sensor.mqtt_irq, as3935_sensor.distance, as3935_sensor.intensity );
#ifdef USE_WEBSERVER
} else {
uint8_t gain = AS3935GetGainInt();
uint8_t disturber = AS3935GetDisturber();
uint16_t vrms;
uint8_t stage;
AS3935CalcVrmsLevel(vrms, stage);
WSContentSend_PD(HTTP_SNS_AS3935_TABLE_1[as3935_sensor.http_irq], D_NAME_AS3935, as3935_sensor.http_distance);
WSContentSend_PD(HTTP_SNS_AS3935_DISTANZ, as3935_sensor.http_distance);
WSContentSend_PD(HTTP_SNS_AS3935_ENERGY, as3935_sensor.http_intensity);
WSContentSend_PD(HTTP_SNS_AS3935_GAIN[gain], D_NAME_AS3935);
WSContentSend_PD(HTTP_SNS_AS3935_DISTURBER[disturber], D_NAME_AS3935);
WSContentSend_PD(HTTP_SNS_AS3935_VRMS, vrms, stage);
#endif // USE_WEBSERVER
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns67(uint8_t function)
{
if (!I2cEnabled(XI2C_48)) { return false; }
bool result = false;
if (FUNC_INIT == function) {
AS3935Detect();
}
else if (as3935_active) {
switch (function) {
case FUNC_EVERY_SECOND:
AS3935EverySecond();
break;
case FUNC_COMMAND:
result = AS3935Cmd();
break;
case FUNC_JSON_APPEND:
AH3935Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
AH3935Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_AS3935
#endif // USE_I2C

View File

@ -93,7 +93,7 @@ a_setoption = [[
"IR Unknown threshold",
"CSE7766 invalid power margin",
"Ignore hold time (s)",
"(not used) Number of Tuya MCU relays",
"Gratuitous ARP repeat time",
"Over temperature threshold (celsius)",
"(not used) Tuya MCU max dimmer value",
"(not used) Tuya MCU voltage Id",
@ -144,7 +144,9 @@ a_setoption = [[
"PWM Dimmer Turn red LED on when powered off",
"PWM Dimmer Buttons control remote devices",
"Distinct MQTT topics per device for Zigbee",
"","","","",
"Disable non-json MQTT response",
"Enable light fading at start/power on",
"","",
"","","","",
"","","","",
"","","","",
@ -199,7 +201,7 @@ a_features = [[
"USE_AHT1x","USE_WEMOS_MOTOR_V1","USE_DEVICE_GROUPS","USE_PWM_DIMMER"
],[
"USE_KEELOQ","USE_HRXL","USE_SONOFF_D1","USE_HDC1080",
"","","","",
"USE_IAQ","USE_DISPLAY_SEVENSEG","USE_AS3935","USE_PING",
"","","","",
"","","","",
"","","","",
@ -239,7 +241,7 @@ else:
obj = json.load(fp)
def StartDecode():
print ("\n*** decode-status.py v20200314 by Theo Arends and Jacek Ziolkowski ***")
print ("\n*** decode-status.py v20200411 by Theo Arends and Jacek Ziolkowski ***")
# print("Decoding\n{}".format(obj))