mirror of
https://github.com/esphome/esphome.git
synced 2025-11-03 08:31:47 +00:00
Compare commits
152 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53c231a7eb | ||
|
|
d44ce82aa1 | ||
|
|
a055de48e4 | ||
|
|
37b8d665fe | ||
|
|
dd7c8dabb1 | ||
|
|
e41a9875e3 | ||
|
|
c5c42c4338 | ||
|
|
531428b8b0 | ||
|
|
ea8068e001 | ||
|
|
7842a55c81 | ||
|
|
51d39862b1 | ||
|
|
bfea6ca79b | ||
|
|
6297395018 | ||
|
|
a5b49dbfa6 | ||
|
|
7c0d777173 | ||
|
|
74878276fc | ||
|
|
226e3b1dad | ||
|
|
7752794fc5 | ||
|
|
b3094d6a53 | ||
|
|
e3640e710f | ||
|
|
2ef64b55c5 | ||
|
|
7f6672bb37 | ||
|
|
68a3b31628 | ||
|
|
1b35855e68 | ||
|
|
1e1837000d | ||
|
|
e2d5257632 | ||
|
|
387c75793b | ||
|
|
4f3a74d08a | ||
|
|
fdbc59a159 | ||
|
|
0db37bb55c | ||
|
|
2ff2750628 | ||
|
|
eae5c17b87 | ||
|
|
a59cde91ad | ||
|
|
1f243ae37e | ||
|
|
603f82977e | ||
|
|
2d70422a6f | ||
|
|
e2c8b21195 | ||
|
|
7adaeacd0b | ||
|
|
3aaa92fdff | ||
|
|
5efd076c08 | ||
|
|
5f535e9756 | ||
|
|
70faeb2fa8 | ||
|
|
469c0db981 | ||
|
|
440e428aa4 | ||
|
|
dde70c95a4 | ||
|
|
09d1846261 | ||
|
|
34d26a517d | ||
|
|
d24b88271c | ||
|
|
f22115792a | ||
|
|
82a30558e1 | ||
|
|
847fe5adca | ||
|
|
775b51c6a1 | ||
|
|
e0ad5a9009 | ||
|
|
1bf01a9081 | ||
|
|
6ae59bb43d | ||
|
|
929600d7f7 | ||
|
|
163d0c55ab | ||
|
|
327ccb241e | ||
|
|
6b3c7b0854 | ||
|
|
681dcb51da | ||
|
|
576d5021fd | ||
|
|
6cd76f00ac | ||
|
|
6f63a62a8d | ||
|
|
8867a0fcfb | ||
|
|
42b4a166ec | ||
|
|
c27fd0f01a | ||
|
|
dcb4a0a81e | ||
|
|
17da9fddc3 | ||
|
|
31aa3c55ca | ||
|
|
eca3685ea0 | ||
|
|
bd216c5c63 | ||
|
|
31ff76427c | ||
|
|
2229aa6ccc | ||
|
|
872b468415 | ||
|
|
9f022a7433 | ||
|
|
85a958e300 | ||
|
|
0ee56195ae | ||
|
|
48f52db1d9 | ||
|
|
d2c7afeef0 | ||
|
|
644aec791e | ||
|
|
b70a0325c5 | ||
|
|
268387f829 | ||
|
|
b975caef1e | ||
|
|
54fe1c7d55 | ||
|
|
89c1274d56 | ||
|
|
f9ca3f1c27 | ||
|
|
26dbc30279 | ||
|
|
4bee316425 | ||
|
|
1ca241615d | ||
|
|
b8aa84002a | ||
|
|
10cc0b1d5b | ||
|
|
11d9c203c1 | ||
|
|
c9ab454c3c | ||
|
|
4a55692885 | ||
|
|
88c129e705 | ||
|
|
80b48f01fb | ||
|
|
642bc91a76 | ||
|
|
d69926ee56 | ||
|
|
4758403d44 | ||
|
|
4b0ec5c28a | ||
|
|
4b2a9e5e49 | ||
|
|
1449c51d49 | ||
|
|
a451705e0b | ||
|
|
2e6db39173 | ||
|
|
373f75253c | ||
|
|
724842084e | ||
|
|
8f3635b167 | ||
|
|
11605a36f7 | ||
|
|
533f81d625 | ||
|
|
aacb9e44e8 | ||
|
|
c6e3f1bca6 | ||
|
|
a933d4aeb6 | ||
|
|
caa5b20791 | ||
|
|
e2ad9ed746 | ||
|
|
32c0e7c2ae | ||
|
|
6c564c7b7f | ||
|
|
c81e3a3be4 | ||
|
|
6b1b9ef7ec | ||
|
|
c26a8b8718 | ||
|
|
4a89a475bd | ||
|
|
8cf15c7f5c | ||
|
|
adc76ca1b8 | ||
|
|
8f8892440c | ||
|
|
570843150d | ||
|
|
f3fc9e4142 | ||
|
|
075fcb77a8 | ||
|
|
e5899ff717 | ||
|
|
2fb3970027 | ||
|
|
1a4efa1b8c | ||
|
|
72f656ffef | ||
|
|
b60239d5e5 | ||
|
|
d02e280c3c | ||
|
|
6535b0966e | ||
|
|
82dbacbee5 | ||
|
|
2432901974 | ||
|
|
ebb5d58c14 | ||
|
|
605e365405 | ||
|
|
5ab995d8ca | ||
|
|
4248741b11 | ||
|
|
4b8ecc7634 | ||
|
|
25d04c759c | ||
|
|
b4ec84030e | ||
|
|
29e8761373 | ||
|
|
a04299c59e | ||
|
|
d7bf3c51d9 | ||
|
|
ac0b095941 | ||
|
|
cda9bad233 | ||
|
|
41db8a1264 | ||
|
|
e7e785fd60 | ||
|
|
300d3a1f46 | ||
|
|
356554c08d | ||
|
|
ced28ad006 |
@@ -3,7 +3,7 @@
|
||||
variables:
|
||||
DOCKER_DRIVER: overlay2
|
||||
DOCKER_HOST: tcp://docker:2375/
|
||||
BASE_VERSION: '2.0.0'
|
||||
BASE_VERSION: '2.0.1'
|
||||
TZ: UTC
|
||||
|
||||
stages:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
sudo: false
|
||||
language: python
|
||||
python: '3.5'
|
||||
python: '3.6'
|
||||
install: script/setup
|
||||
cache:
|
||||
directories:
|
||||
@@ -15,8 +15,8 @@ matrix:
|
||||
- script/ci-custom.py
|
||||
- flake8 esphome
|
||||
- pylint esphome
|
||||
- python: "3.5"
|
||||
env: TARGET=Test3.5
|
||||
- python: "3.6"
|
||||
env: TARGET=Test3.6
|
||||
script:
|
||||
- esphome tests/test1.yaml compile
|
||||
- esphome tests/test2.yaml compile
|
||||
|
||||
@@ -3,3 +3,4 @@ include README.md
|
||||
include esphome/dashboard/templates/*.html
|
||||
recursive-include esphome/dashboard/static *.ico *.js *.css *.woff* LICENSE
|
||||
recursive-include esphome *.cpp *.h *.tcc
|
||||
recursive-include esphome LICENSE.txt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG BUILD_FROM=esphome/esphome-base-amd64:2.0.0
|
||||
ARG BUILD_FROM=esphome/esphome-base-amd64:2.0.1
|
||||
FROM ${BUILD_FROM}
|
||||
|
||||
COPY . .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM esphome/esphome-base-amd64:2.0.0
|
||||
FROM esphome/esphome-base-amd64:2.0.1
|
||||
|
||||
RUN \
|
||||
apt-get update \
|
||||
@@ -14,5 +14,7 @@ RUN \
|
||||
COPY requirements_test.txt /requirements_test.txt
|
||||
RUN pip3 install --no-cache-dir wheel && pip3 install --no-cache-dir -r /requirements_test.txt
|
||||
|
||||
RUN ln -s /usr/bin/pip3 /usr/bin/pip && ln -f -s /usr/bin/python3 /usr/bin/python
|
||||
|
||||
VOLUME ["/esphome"]
|
||||
WORKDIR /esphome
|
||||
|
||||
@@ -14,7 +14,7 @@ from esphome.const import CONF_BAUD_RATE, CONF_BROKER, CONF_LOGGER, CONF_OTA, \
|
||||
CONF_PASSWORD, CONF_PORT, CONF_ESPHOME, CONF_PLATFORMIO_OPTIONS
|
||||
from esphome.core import CORE, EsphomeError, coroutine, coroutine_with_priority
|
||||
from esphome.helpers import color, indent
|
||||
from esphome.py_compat import IS_PY2, safe_input
|
||||
from esphome.py_compat import IS_PY2, safe_input, IS_PY3
|
||||
from esphome.util import run_external_command, run_external_process, safe_print, list_yaml_files
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -165,16 +165,27 @@ def compile_program(args, config):
|
||||
|
||||
def upload_using_esptool(config, port):
|
||||
path = CORE.firmware_bin
|
||||
cmd = ['esptool.py', '--before', 'default_reset', '--after', 'hard_reset',
|
||||
'--baud', str(config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get('upload_speed', 460800)),
|
||||
'--chip', 'esp8266', '--port', port, 'write_flash', '0x0', path]
|
||||
first_baudrate = config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get('upload_speed', 460800)
|
||||
|
||||
if os.environ.get('ESPHOME_USE_SUBPROCESS') is None:
|
||||
import esptool
|
||||
# pylint: disable=protected-access
|
||||
return run_external_command(esptool._main, *cmd)
|
||||
def run_esptool(baud_rate):
|
||||
cmd = ['esptool.py', '--before', 'default_reset', '--after', 'hard_reset',
|
||||
'--baud', str(baud_rate),
|
||||
'--chip', 'esp8266', '--port', port, 'write_flash', '0x0', path]
|
||||
|
||||
return run_external_process(*cmd)
|
||||
if os.environ.get('ESPHOME_USE_SUBPROCESS') is None:
|
||||
import esptool
|
||||
# pylint: disable=protected-access
|
||||
return run_external_command(esptool._main, *cmd)
|
||||
|
||||
return run_external_process(*cmd)
|
||||
|
||||
rc = run_esptool(first_baudrate)
|
||||
if rc == 0 or first_baudrate == 115200:
|
||||
return rc
|
||||
# Try with 115200 baud rate, with some serial chips the faster baud rates do not work well
|
||||
_LOGGER.info("Upload with baud rate %s failed. Trying again with baud rate 115200.",
|
||||
first_baudrate)
|
||||
return run_esptool(115200)
|
||||
|
||||
|
||||
def upload_program(config, args, host):
|
||||
@@ -364,14 +375,15 @@ def command_update_all(args):
|
||||
def print_bar(middle_text):
|
||||
middle_text = " {} ".format(middle_text)
|
||||
width = len(click.unstyle(middle_text))
|
||||
half_line = "=" * ((twidth - width) / 2)
|
||||
half_line = "=" * ((twidth - width) // 2)
|
||||
click.echo("%s%s%s" % (half_line, middle_text, half_line))
|
||||
|
||||
for f in files:
|
||||
print("Updating {}".format(color('cyan', f)))
|
||||
print('-' * twidth)
|
||||
print()
|
||||
rc = run_external_process('esphome', '--dashboard', f, 'run', '--no-logs')
|
||||
rc = run_external_process('esphome', '--dashboard', f, 'run', '--no-logs', '--upload-port',
|
||||
'OTA')
|
||||
if rc == 0:
|
||||
print_bar("[{}] {}".format(color('bold_green', 'SUCCESS'), f))
|
||||
success[f] = True
|
||||
@@ -509,6 +521,15 @@ def run_esphome(argv):
|
||||
_LOGGER.error("Missing configuration parameter, see esphome --help.")
|
||||
return 1
|
||||
|
||||
if IS_PY2:
|
||||
_LOGGER.warning("You're using ESPHome with python 2. Support for python 2 is deprecated "
|
||||
"and will be removed in 1.15.0. Please reinstall ESPHome with python 3.6 "
|
||||
"or higher.")
|
||||
elif IS_PY3 and sys.version_info < (3, 6, 0):
|
||||
_LOGGER.warning("You're using ESPHome with python 3.5. Support for python 3.5 is "
|
||||
"deprecated and will be removed in 1.15.0. Please reinstall ESPHome with "
|
||||
"python 3.6 or higher.")
|
||||
|
||||
if args.command in PRE_CONFIG_ACTIONS:
|
||||
try:
|
||||
return PRE_CONFIG_ACTIONS[args.command](args)
|
||||
|
||||
@@ -70,14 +70,14 @@ def to_code(config):
|
||||
cg.add_global(api_ns.using)
|
||||
|
||||
|
||||
KEY_VALUE_SCHEMA = cv.Schema({cv.string: cv.templatable(cv.string)})
|
||||
KEY_VALUE_SCHEMA = cv.Schema({cv.string: cv.templatable(cv.string_strict)})
|
||||
|
||||
HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(APIServer),
|
||||
cv.Required(CONF_SERVICE): cv.templatable(cv.string),
|
||||
cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA,
|
||||
cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA,
|
||||
cv.Optional(CONF_VARIABLES, default={}): KEY_VALUE_SCHEMA,
|
||||
cv.Optional(CONF_VARIABLES, default={}): cv.Schema({cv.string: cv.returning_lambda}),
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -216,6 +216,9 @@ message BinarySensorStateResponse {
|
||||
|
||||
fixed32 key = 1;
|
||||
bool state = 2;
|
||||
// If the binary sensor does not have a valid state yet.
|
||||
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
|
||||
bool missing_state = 3;
|
||||
}
|
||||
|
||||
// ==================== COVER ====================
|
||||
@@ -406,6 +409,7 @@ message ListEntitiesSensorResponse {
|
||||
string icon = 5;
|
||||
string unit_of_measurement = 6;
|
||||
int32 accuracy_decimals = 7;
|
||||
bool force_update = 8;
|
||||
}
|
||||
message SensorStateResponse {
|
||||
option (id) = 25;
|
||||
@@ -415,6 +419,9 @@ message SensorStateResponse {
|
||||
|
||||
fixed32 key = 1;
|
||||
float state = 2;
|
||||
// If the sensor does not have a valid state yet.
|
||||
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
|
||||
bool missing_state = 3;
|
||||
}
|
||||
|
||||
// ==================== SWITCH ====================
|
||||
@@ -471,6 +478,9 @@ message TextSensorStateResponse {
|
||||
|
||||
fixed32 key = 1;
|
||||
string state = 2;
|
||||
// If the text sensor does not have a valid state yet.
|
||||
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
|
||||
bool missing_state = 3;
|
||||
}
|
||||
|
||||
// ==================== SUBSCRIBE LOGS ====================
|
||||
|
||||
@@ -163,6 +163,7 @@ bool APIConnection::send_binary_sensor_state(binary_sensor::BinarySensor *binary
|
||||
BinarySensorStateResponse resp;
|
||||
resp.key = binary_sensor->get_object_id_hash();
|
||||
resp.state = state;
|
||||
resp.missing_state = !binary_sensor->has_state();
|
||||
return this->send_binary_sensor_state_response(resp);
|
||||
}
|
||||
bool APIConnection::send_binary_sensor_info(binary_sensor::BinarySensor *binary_sensor) {
|
||||
@@ -185,11 +186,12 @@ bool APIConnection::send_cover_state(cover::Cover *cover) {
|
||||
auto traits = cover->get_traits();
|
||||
CoverStateResponse resp{};
|
||||
resp.key = cover->get_object_id_hash();
|
||||
resp.legacy_state = (cover->position == cover::COVER_OPEN) ? LEGACY_COVER_STATE_OPEN : LEGACY_COVER_STATE_CLOSED;
|
||||
resp.legacy_state =
|
||||
(cover->position == cover::COVER_OPEN) ? enums::LEGACY_COVER_STATE_OPEN : enums::LEGACY_COVER_STATE_CLOSED;
|
||||
resp.position = cover->position;
|
||||
if (traits.get_supports_tilt())
|
||||
resp.tilt = cover->tilt;
|
||||
resp.current_operation = static_cast<EnumCoverOperation>(cover->current_operation);
|
||||
resp.current_operation = static_cast<enums::CoverOperation>(cover->current_operation);
|
||||
return this->send_cover_state_response(resp);
|
||||
}
|
||||
bool APIConnection::send_cover_info(cover::Cover *cover) {
|
||||
@@ -213,13 +215,13 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
|
||||
auto call = cover->make_call();
|
||||
if (msg.has_legacy_command) {
|
||||
switch (msg.legacy_command) {
|
||||
case LEGACY_COVER_COMMAND_OPEN:
|
||||
case enums::LEGACY_COVER_COMMAND_OPEN:
|
||||
call.set_command_open();
|
||||
break;
|
||||
case LEGACY_COVER_COMMAND_CLOSE:
|
||||
case enums::LEGACY_COVER_COMMAND_CLOSE:
|
||||
call.set_command_close();
|
||||
break;
|
||||
case LEGACY_COVER_COMMAND_STOP:
|
||||
case enums::LEGACY_COVER_COMMAND_STOP:
|
||||
call.set_command_stop();
|
||||
break;
|
||||
}
|
||||
@@ -246,7 +248,7 @@ bool APIConnection::send_fan_state(fan::FanState *fan) {
|
||||
if (traits.supports_oscillation())
|
||||
resp.oscillating = fan->oscillating;
|
||||
if (traits.supports_speed())
|
||||
resp.speed = static_cast<EnumFanSpeed>(fan->speed);
|
||||
resp.speed = static_cast<enums::FanSpeed>(fan->speed);
|
||||
return this->send_fan_state_response(resp);
|
||||
}
|
||||
bool APIConnection::send_fan_info(fan::FanState *fan) {
|
||||
@@ -361,6 +363,7 @@ bool APIConnection::send_sensor_state(sensor::Sensor *sensor, float state) {
|
||||
SensorStateResponse resp{};
|
||||
resp.key = sensor->get_object_id_hash();
|
||||
resp.state = state;
|
||||
resp.missing_state = !sensor->has_state();
|
||||
return this->send_sensor_state_response(resp);
|
||||
}
|
||||
bool APIConnection::send_sensor_info(sensor::Sensor *sensor) {
|
||||
@@ -374,6 +377,7 @@ bool APIConnection::send_sensor_info(sensor::Sensor *sensor) {
|
||||
msg.icon = sensor->get_icon();
|
||||
msg.unit_of_measurement = sensor->get_unit_of_measurement();
|
||||
msg.accuracy_decimals = sensor->get_accuracy_decimals();
|
||||
msg.force_update = sensor->get_force_update();
|
||||
return this->send_list_entities_sensor_response(msg);
|
||||
}
|
||||
#endif
|
||||
@@ -418,6 +422,7 @@ bool APIConnection::send_text_sensor_state(text_sensor::TextSensor *text_sensor,
|
||||
TextSensorStateResponse resp{};
|
||||
resp.key = text_sensor->get_object_id_hash();
|
||||
resp.state = std::move(state);
|
||||
resp.missing_state = !text_sensor->has_state();
|
||||
return this->send_text_sensor_state_response(resp);
|
||||
}
|
||||
bool APIConnection::send_text_sensor_info(text_sensor::TextSensor *text_sensor) {
|
||||
@@ -441,8 +446,8 @@ bool APIConnection::send_climate_state(climate::Climate *climate) {
|
||||
auto traits = climate->get_traits();
|
||||
ClimateStateResponse resp{};
|
||||
resp.key = climate->get_object_id_hash();
|
||||
resp.mode = static_cast<EnumClimateMode>(climate->mode);
|
||||
resp.action = static_cast<EnumClimateAction>(climate->action);
|
||||
resp.mode = static_cast<enums::ClimateMode>(climate->mode);
|
||||
resp.action = static_cast<enums::ClimateAction>(climate->action);
|
||||
if (traits.get_supports_current_temperature())
|
||||
resp.current_temperature = climate->current_temperature;
|
||||
if (traits.get_supports_two_point_target_temperature()) {
|
||||
@@ -467,7 +472,7 @@ bool APIConnection::send_climate_info(climate::Climate *climate) {
|
||||
for (auto mode : {climate::CLIMATE_MODE_AUTO, climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL,
|
||||
climate::CLIMATE_MODE_HEAT}) {
|
||||
if (traits.supports_mode(mode))
|
||||
msg.supported_modes.push_back(static_cast<EnumClimateMode>(mode));
|
||||
msg.supported_modes.push_back(static_cast<enums::ClimateMode>(mode));
|
||||
}
|
||||
msg.visual_min_temperature = traits.get_visual_min_temperature();
|
||||
msg.visual_max_temperature = traits.get_visual_max_temperature();
|
||||
|
||||
@@ -4,115 +4,115 @@
|
||||
namespace esphome {
|
||||
namespace api {
|
||||
|
||||
template<> const char *proto_enum_to_string<EnumLegacyCoverState>(EnumLegacyCoverState value) {
|
||||
template<> const char *proto_enum_to_string<enums::LegacyCoverState>(enums::LegacyCoverState value) {
|
||||
switch (value) {
|
||||
case LEGACY_COVER_STATE_OPEN:
|
||||
case enums::LEGACY_COVER_STATE_OPEN:
|
||||
return "LEGACY_COVER_STATE_OPEN";
|
||||
case LEGACY_COVER_STATE_CLOSED:
|
||||
case enums::LEGACY_COVER_STATE_CLOSED:
|
||||
return "LEGACY_COVER_STATE_CLOSED";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<EnumCoverOperation>(EnumCoverOperation value) {
|
||||
template<> const char *proto_enum_to_string<enums::CoverOperation>(enums::CoverOperation value) {
|
||||
switch (value) {
|
||||
case COVER_OPERATION_IDLE:
|
||||
case enums::COVER_OPERATION_IDLE:
|
||||
return "COVER_OPERATION_IDLE";
|
||||
case COVER_OPERATION_IS_OPENING:
|
||||
case enums::COVER_OPERATION_IS_OPENING:
|
||||
return "COVER_OPERATION_IS_OPENING";
|
||||
case COVER_OPERATION_IS_CLOSING:
|
||||
case enums::COVER_OPERATION_IS_CLOSING:
|
||||
return "COVER_OPERATION_IS_CLOSING";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<EnumLegacyCoverCommand>(EnumLegacyCoverCommand value) {
|
||||
template<> const char *proto_enum_to_string<enums::LegacyCoverCommand>(enums::LegacyCoverCommand value) {
|
||||
switch (value) {
|
||||
case LEGACY_COVER_COMMAND_OPEN:
|
||||
case enums::LEGACY_COVER_COMMAND_OPEN:
|
||||
return "LEGACY_COVER_COMMAND_OPEN";
|
||||
case LEGACY_COVER_COMMAND_CLOSE:
|
||||
case enums::LEGACY_COVER_COMMAND_CLOSE:
|
||||
return "LEGACY_COVER_COMMAND_CLOSE";
|
||||
case LEGACY_COVER_COMMAND_STOP:
|
||||
case enums::LEGACY_COVER_COMMAND_STOP:
|
||||
return "LEGACY_COVER_COMMAND_STOP";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<EnumFanSpeed>(EnumFanSpeed value) {
|
||||
template<> const char *proto_enum_to_string<enums::FanSpeed>(enums::FanSpeed value) {
|
||||
switch (value) {
|
||||
case FAN_SPEED_LOW:
|
||||
case enums::FAN_SPEED_LOW:
|
||||
return "FAN_SPEED_LOW";
|
||||
case FAN_SPEED_MEDIUM:
|
||||
case enums::FAN_SPEED_MEDIUM:
|
||||
return "FAN_SPEED_MEDIUM";
|
||||
case FAN_SPEED_HIGH:
|
||||
case enums::FAN_SPEED_HIGH:
|
||||
return "FAN_SPEED_HIGH";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<EnumLogLevel>(EnumLogLevel value) {
|
||||
template<> const char *proto_enum_to_string<enums::LogLevel>(enums::LogLevel value) {
|
||||
switch (value) {
|
||||
case LOG_LEVEL_NONE:
|
||||
case enums::LOG_LEVEL_NONE:
|
||||
return "LOG_LEVEL_NONE";
|
||||
case LOG_LEVEL_ERROR:
|
||||
case enums::LOG_LEVEL_ERROR:
|
||||
return "LOG_LEVEL_ERROR";
|
||||
case LOG_LEVEL_WARN:
|
||||
case enums::LOG_LEVEL_WARN:
|
||||
return "LOG_LEVEL_WARN";
|
||||
case LOG_LEVEL_INFO:
|
||||
case enums::LOG_LEVEL_INFO:
|
||||
return "LOG_LEVEL_INFO";
|
||||
case LOG_LEVEL_DEBUG:
|
||||
case enums::LOG_LEVEL_DEBUG:
|
||||
return "LOG_LEVEL_DEBUG";
|
||||
case LOG_LEVEL_VERBOSE:
|
||||
case enums::LOG_LEVEL_VERBOSE:
|
||||
return "LOG_LEVEL_VERBOSE";
|
||||
case LOG_LEVEL_VERY_VERBOSE:
|
||||
case enums::LOG_LEVEL_VERY_VERBOSE:
|
||||
return "LOG_LEVEL_VERY_VERBOSE";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<EnumServiceArgType>(EnumServiceArgType value) {
|
||||
template<> const char *proto_enum_to_string<enums::ServiceArgType>(enums::ServiceArgType value) {
|
||||
switch (value) {
|
||||
case SERVICE_ARG_TYPE_BOOL:
|
||||
case enums::SERVICE_ARG_TYPE_BOOL:
|
||||
return "SERVICE_ARG_TYPE_BOOL";
|
||||
case SERVICE_ARG_TYPE_INT:
|
||||
case enums::SERVICE_ARG_TYPE_INT:
|
||||
return "SERVICE_ARG_TYPE_INT";
|
||||
case SERVICE_ARG_TYPE_FLOAT:
|
||||
case enums::SERVICE_ARG_TYPE_FLOAT:
|
||||
return "SERVICE_ARG_TYPE_FLOAT";
|
||||
case SERVICE_ARG_TYPE_STRING:
|
||||
case enums::SERVICE_ARG_TYPE_STRING:
|
||||
return "SERVICE_ARG_TYPE_STRING";
|
||||
case SERVICE_ARG_TYPE_BOOL_ARRAY:
|
||||
case enums::SERVICE_ARG_TYPE_BOOL_ARRAY:
|
||||
return "SERVICE_ARG_TYPE_BOOL_ARRAY";
|
||||
case SERVICE_ARG_TYPE_INT_ARRAY:
|
||||
case enums::SERVICE_ARG_TYPE_INT_ARRAY:
|
||||
return "SERVICE_ARG_TYPE_INT_ARRAY";
|
||||
case SERVICE_ARG_TYPE_FLOAT_ARRAY:
|
||||
case enums::SERVICE_ARG_TYPE_FLOAT_ARRAY:
|
||||
return "SERVICE_ARG_TYPE_FLOAT_ARRAY";
|
||||
case SERVICE_ARG_TYPE_STRING_ARRAY:
|
||||
case enums::SERVICE_ARG_TYPE_STRING_ARRAY:
|
||||
return "SERVICE_ARG_TYPE_STRING_ARRAY";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<EnumClimateMode>(EnumClimateMode value) {
|
||||
template<> const char *proto_enum_to_string<enums::ClimateMode>(enums::ClimateMode value) {
|
||||
switch (value) {
|
||||
case CLIMATE_MODE_OFF:
|
||||
case enums::CLIMATE_MODE_OFF:
|
||||
return "CLIMATE_MODE_OFF";
|
||||
case CLIMATE_MODE_AUTO:
|
||||
case enums::CLIMATE_MODE_AUTO:
|
||||
return "CLIMATE_MODE_AUTO";
|
||||
case CLIMATE_MODE_COOL:
|
||||
case enums::CLIMATE_MODE_COOL:
|
||||
return "CLIMATE_MODE_COOL";
|
||||
case CLIMATE_MODE_HEAT:
|
||||
case enums::CLIMATE_MODE_HEAT:
|
||||
return "CLIMATE_MODE_HEAT";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
template<> const char *proto_enum_to_string<EnumClimateAction>(EnumClimateAction value) {
|
||||
template<> const char *proto_enum_to_string<enums::ClimateAction>(enums::ClimateAction value) {
|
||||
switch (value) {
|
||||
case CLIMATE_ACTION_OFF:
|
||||
case enums::CLIMATE_ACTION_OFF:
|
||||
return "CLIMATE_ACTION_OFF";
|
||||
case CLIMATE_ACTION_COOLING:
|
||||
case enums::CLIMATE_ACTION_COOLING:
|
||||
return "CLIMATE_ACTION_COOLING";
|
||||
case CLIMATE_ACTION_HEATING:
|
||||
case enums::CLIMATE_ACTION_HEATING:
|
||||
return "CLIMATE_ACTION_HEATING";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
@@ -404,6 +404,10 @@ bool BinarySensorStateResponse::decode_varint(uint32_t field_id, ProtoVarInt val
|
||||
this->state = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 3: {
|
||||
this->missing_state = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -421,6 +425,7 @@ bool BinarySensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value
|
||||
void BinarySensorStateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_bool(2, this->state);
|
||||
buffer.encode_bool(3, this->missing_state);
|
||||
}
|
||||
void BinarySensorStateResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -433,6 +438,10 @@ void BinarySensorStateResponse::dump_to(std::string &out) const {
|
||||
out.append(" state: ");
|
||||
out.append(YESNO(this->state));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" missing_state: ");
|
||||
out.append(YESNO(this->missing_state));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
bool ListEntitiesCoverResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
@@ -535,11 +544,11 @@ void ListEntitiesCoverResponse::dump_to(std::string &out) const {
|
||||
bool CoverStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
this->legacy_state = value.as_enum<EnumLegacyCoverState>();
|
||||
this->legacy_state = value.as_enum<enums::LegacyCoverState>();
|
||||
return true;
|
||||
}
|
||||
case 5: {
|
||||
this->current_operation = value.as_enum<EnumCoverOperation>();
|
||||
this->current_operation = value.as_enum<enums::CoverOperation>();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@@ -566,10 +575,10 @@ bool CoverStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
||||
}
|
||||
void CoverStateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_enum<EnumLegacyCoverState>(2, this->legacy_state);
|
||||
buffer.encode_enum<enums::LegacyCoverState>(2, this->legacy_state);
|
||||
buffer.encode_float(3, this->position);
|
||||
buffer.encode_float(4, this->tilt);
|
||||
buffer.encode_enum<EnumCoverOperation>(5, this->current_operation);
|
||||
buffer.encode_enum<enums::CoverOperation>(5, this->current_operation);
|
||||
}
|
||||
void CoverStateResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -580,7 +589,7 @@ void CoverStateResponse::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" legacy_state: ");
|
||||
out.append(proto_enum_to_string<EnumLegacyCoverState>(this->legacy_state));
|
||||
out.append(proto_enum_to_string<enums::LegacyCoverState>(this->legacy_state));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" position: ");
|
||||
@@ -594,7 +603,7 @@ void CoverStateResponse::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" current_operation: ");
|
||||
out.append(proto_enum_to_string<EnumCoverOperation>(this->current_operation));
|
||||
out.append(proto_enum_to_string<enums::CoverOperation>(this->current_operation));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
@@ -605,7 +614,7 @@ bool CoverCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
return true;
|
||||
}
|
||||
case 3: {
|
||||
this->legacy_command = value.as_enum<EnumLegacyCoverCommand>();
|
||||
this->legacy_command = value.as_enum<enums::LegacyCoverCommand>();
|
||||
return true;
|
||||
}
|
||||
case 4: {
|
||||
@@ -645,7 +654,7 @@ bool CoverCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
||||
void CoverCommandRequest::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_bool(2, this->has_legacy_command);
|
||||
buffer.encode_enum<EnumLegacyCoverCommand>(3, this->legacy_command);
|
||||
buffer.encode_enum<enums::LegacyCoverCommand>(3, this->legacy_command);
|
||||
buffer.encode_bool(4, this->has_position);
|
||||
buffer.encode_float(5, this->position);
|
||||
buffer.encode_bool(6, this->has_tilt);
|
||||
@@ -665,7 +674,7 @@ void CoverCommandRequest::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" legacy_command: ");
|
||||
out.append(proto_enum_to_string<EnumLegacyCoverCommand>(this->legacy_command));
|
||||
out.append(proto_enum_to_string<enums::LegacyCoverCommand>(this->legacy_command));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" has_position: ");
|
||||
@@ -781,7 +790,7 @@ bool FanStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
return true;
|
||||
}
|
||||
case 4: {
|
||||
this->speed = value.as_enum<EnumFanSpeed>();
|
||||
this->speed = value.as_enum<enums::FanSpeed>();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@@ -802,7 +811,7 @@ void FanStateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_bool(2, this->state);
|
||||
buffer.encode_bool(3, this->oscillating);
|
||||
buffer.encode_enum<EnumFanSpeed>(4, this->speed);
|
||||
buffer.encode_enum<enums::FanSpeed>(4, this->speed);
|
||||
}
|
||||
void FanStateResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -821,7 +830,7 @@ void FanStateResponse::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" speed: ");
|
||||
out.append(proto_enum_to_string<EnumFanSpeed>(this->speed));
|
||||
out.append(proto_enum_to_string<enums::FanSpeed>(this->speed));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
@@ -840,7 +849,7 @@ bool FanCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
return true;
|
||||
}
|
||||
case 5: {
|
||||
this->speed = value.as_enum<EnumFanSpeed>();
|
||||
this->speed = value.as_enum<enums::FanSpeed>();
|
||||
return true;
|
||||
}
|
||||
case 6: {
|
||||
@@ -870,7 +879,7 @@ void FanCommandRequest::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(2, this->has_state);
|
||||
buffer.encode_bool(3, this->state);
|
||||
buffer.encode_bool(4, this->has_speed);
|
||||
buffer.encode_enum<EnumFanSpeed>(5, this->speed);
|
||||
buffer.encode_enum<enums::FanSpeed>(5, this->speed);
|
||||
buffer.encode_bool(6, this->has_oscillating);
|
||||
buffer.encode_bool(7, this->oscillating);
|
||||
}
|
||||
@@ -895,7 +904,7 @@ void FanCommandRequest::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" speed: ");
|
||||
out.append(proto_enum_to_string<EnumFanSpeed>(this->speed));
|
||||
out.append(proto_enum_to_string<enums::FanSpeed>(this->speed));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" has_oscillating: ");
|
||||
@@ -1359,6 +1368,10 @@ bool ListEntitiesSensorResponse::decode_varint(uint32_t field_id, ProtoVarInt va
|
||||
this->accuracy_decimals = value.as_int32();
|
||||
return true;
|
||||
}
|
||||
case 8: {
|
||||
this->force_update = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1407,6 +1420,7 @@ void ListEntitiesSensorResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(5, this->icon);
|
||||
buffer.encode_string(6, this->unit_of_measurement);
|
||||
buffer.encode_int32(7, this->accuracy_decimals);
|
||||
buffer.encode_bool(8, this->force_update);
|
||||
}
|
||||
void ListEntitiesSensorResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -1440,8 +1454,22 @@ void ListEntitiesSensorResponse::dump_to(std::string &out) const {
|
||||
sprintf(buffer, "%d", this->accuracy_decimals);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
|
||||
out.append(" force_update: ");
|
||||
out.append(YESNO(this->force_update));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
bool SensorStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 3: {
|
||||
this->missing_state = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool SensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
||||
switch (field_id) {
|
||||
case 1: {
|
||||
@@ -1459,6 +1487,7 @@ bool SensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
||||
void SensorStateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_float(2, this->state);
|
||||
buffer.encode_bool(3, this->missing_state);
|
||||
}
|
||||
void SensorStateResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -1472,6 +1501,10 @@ void SensorStateResponse::dump_to(std::string &out) const {
|
||||
sprintf(buffer, "%g", this->state);
|
||||
out.append(buffer);
|
||||
out.append("\n");
|
||||
|
||||
out.append(" missing_state: ");
|
||||
out.append(YESNO(this->missing_state));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
bool ListEntitiesSwitchResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
@@ -1691,6 +1724,16 @@ void ListEntitiesTextSensorResponse::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
bool TextSensorStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 3: {
|
||||
this->missing_state = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool TextSensorStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
@@ -1714,6 +1757,7 @@ bool TextSensorStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value)
|
||||
void TextSensorStateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_string(2, this->state);
|
||||
buffer.encode_bool(3, this->missing_state);
|
||||
}
|
||||
void TextSensorStateResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -1726,12 +1770,16 @@ void TextSensorStateResponse::dump_to(std::string &out) const {
|
||||
out.append(" state: ");
|
||||
out.append("'").append(this->state).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" missing_state: ");
|
||||
out.append(YESNO(this->missing_state));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
bool SubscribeLogsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1: {
|
||||
this->level = value.as_enum<EnumLogLevel>();
|
||||
this->level = value.as_enum<enums::LogLevel>();
|
||||
return true;
|
||||
}
|
||||
case 2: {
|
||||
@@ -1743,14 +1791,14 @@ bool SubscribeLogsRequest::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
}
|
||||
}
|
||||
void SubscribeLogsRequest::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_enum<EnumLogLevel>(1, this->level);
|
||||
buffer.encode_enum<enums::LogLevel>(1, this->level);
|
||||
buffer.encode_bool(2, this->dump_config);
|
||||
}
|
||||
void SubscribeLogsRequest::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
out.append("SubscribeLogsRequest {\n");
|
||||
out.append(" level: ");
|
||||
out.append(proto_enum_to_string<EnumLogLevel>(this->level));
|
||||
out.append(proto_enum_to_string<enums::LogLevel>(this->level));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" dump_config: ");
|
||||
@@ -1761,7 +1809,7 @@ void SubscribeLogsRequest::dump_to(std::string &out) const {
|
||||
bool SubscribeLogsResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 1: {
|
||||
this->level = value.as_enum<EnumLogLevel>();
|
||||
this->level = value.as_enum<enums::LogLevel>();
|
||||
return true;
|
||||
}
|
||||
case 4: {
|
||||
@@ -1787,7 +1835,7 @@ bool SubscribeLogsResponse::decode_length(uint32_t field_id, ProtoLengthDelimite
|
||||
}
|
||||
}
|
||||
void SubscribeLogsResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_enum<EnumLogLevel>(1, this->level);
|
||||
buffer.encode_enum<enums::LogLevel>(1, this->level);
|
||||
buffer.encode_string(2, this->tag);
|
||||
buffer.encode_string(3, this->message);
|
||||
buffer.encode_bool(4, this->send_failed);
|
||||
@@ -1796,7 +1844,7 @@ void SubscribeLogsResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
out.append("SubscribeLogsResponse {\n");
|
||||
out.append(" level: ");
|
||||
out.append(proto_enum_to_string<EnumLogLevel>(this->level));
|
||||
out.append(proto_enum_to_string<enums::LogLevel>(this->level));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" tag: ");
|
||||
@@ -2001,7 +2049,7 @@ void GetTimeResponse::dump_to(std::string &out) const {
|
||||
bool ListEntitiesServicesArgument::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
this->type = value.as_enum<EnumServiceArgType>();
|
||||
this->type = value.as_enum<enums::ServiceArgType>();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@@ -2020,7 +2068,7 @@ bool ListEntitiesServicesArgument::decode_length(uint32_t field_id, ProtoLengthD
|
||||
}
|
||||
void ListEntitiesServicesArgument::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_string(1, this->name);
|
||||
buffer.encode_enum<EnumServiceArgType>(2, this->type);
|
||||
buffer.encode_enum<enums::ServiceArgType>(2, this->type);
|
||||
}
|
||||
void ListEntitiesServicesArgument::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -2030,7 +2078,7 @@ void ListEntitiesServicesArgument::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" type: ");
|
||||
out.append(proto_enum_to_string<EnumServiceArgType>(this->type));
|
||||
out.append(proto_enum_to_string<enums::ServiceArgType>(this->type));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
@@ -2399,7 +2447,7 @@ bool ListEntitiesClimateResponse::decode_varint(uint32_t field_id, ProtoVarInt v
|
||||
return true;
|
||||
}
|
||||
case 7: {
|
||||
this->supported_modes.push_back(value.as_enum<EnumClimateMode>());
|
||||
this->supported_modes.push_back(value.as_enum<enums::ClimateMode>());
|
||||
return true;
|
||||
}
|
||||
case 11: {
|
||||
@@ -2462,7 +2510,7 @@ void ListEntitiesClimateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_bool(5, this->supports_current_temperature);
|
||||
buffer.encode_bool(6, this->supports_two_point_target_temperature);
|
||||
for (auto &it : this->supported_modes) {
|
||||
buffer.encode_enum<EnumClimateMode>(7, it, true);
|
||||
buffer.encode_enum<enums::ClimateMode>(7, it, true);
|
||||
}
|
||||
buffer.encode_float(8, this->visual_min_temperature);
|
||||
buffer.encode_float(9, this->visual_max_temperature);
|
||||
@@ -2500,7 +2548,7 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
|
||||
|
||||
for (const auto &it : this->supported_modes) {
|
||||
out.append(" supported_modes: ");
|
||||
out.append(proto_enum_to_string<EnumClimateMode>(it));
|
||||
out.append(proto_enum_to_string<enums::ClimateMode>(it));
|
||||
out.append("\n");
|
||||
}
|
||||
|
||||
@@ -2531,7 +2579,7 @@ void ListEntitiesClimateResponse::dump_to(std::string &out) const {
|
||||
bool ClimateStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
switch (field_id) {
|
||||
case 2: {
|
||||
this->mode = value.as_enum<EnumClimateMode>();
|
||||
this->mode = value.as_enum<enums::ClimateMode>();
|
||||
return true;
|
||||
}
|
||||
case 7: {
|
||||
@@ -2539,7 +2587,7 @@ bool ClimateStateResponse::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
||||
return true;
|
||||
}
|
||||
case 8: {
|
||||
this->action = value.as_enum<EnumClimateAction>();
|
||||
this->action = value.as_enum<enums::ClimateAction>();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@@ -2574,13 +2622,13 @@ bool ClimateStateResponse::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
||||
}
|
||||
void ClimateStateResponse::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_enum<EnumClimateMode>(2, this->mode);
|
||||
buffer.encode_enum<enums::ClimateMode>(2, this->mode);
|
||||
buffer.encode_float(3, this->current_temperature);
|
||||
buffer.encode_float(4, this->target_temperature);
|
||||
buffer.encode_float(5, this->target_temperature_low);
|
||||
buffer.encode_float(6, this->target_temperature_high);
|
||||
buffer.encode_bool(7, this->away);
|
||||
buffer.encode_enum<EnumClimateAction>(8, this->action);
|
||||
buffer.encode_enum<enums::ClimateAction>(8, this->action);
|
||||
}
|
||||
void ClimateStateResponse::dump_to(std::string &out) const {
|
||||
char buffer[64];
|
||||
@@ -2591,7 +2639,7 @@ void ClimateStateResponse::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" mode: ");
|
||||
out.append(proto_enum_to_string<EnumClimateMode>(this->mode));
|
||||
out.append(proto_enum_to_string<enums::ClimateMode>(this->mode));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" current_temperature: ");
|
||||
@@ -2619,7 +2667,7 @@ void ClimateStateResponse::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" action: ");
|
||||
out.append(proto_enum_to_string<EnumClimateAction>(this->action));
|
||||
out.append(proto_enum_to_string<enums::ClimateAction>(this->action));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
@@ -2630,7 +2678,7 @@ bool ClimateCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt value)
|
||||
return true;
|
||||
}
|
||||
case 3: {
|
||||
this->mode = value.as_enum<EnumClimateMode>();
|
||||
this->mode = value.as_enum<enums::ClimateMode>();
|
||||
return true;
|
||||
}
|
||||
case 4: {
|
||||
@@ -2682,7 +2730,7 @@ bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
||||
void ClimateCommandRequest::encode(ProtoWriteBuffer buffer) const {
|
||||
buffer.encode_fixed32(1, this->key);
|
||||
buffer.encode_bool(2, this->has_mode);
|
||||
buffer.encode_enum<EnumClimateMode>(3, this->mode);
|
||||
buffer.encode_enum<enums::ClimateMode>(3, this->mode);
|
||||
buffer.encode_bool(4, this->has_target_temperature);
|
||||
buffer.encode_float(5, this->target_temperature);
|
||||
buffer.encode_bool(6, this->has_target_temperature_low);
|
||||
@@ -2705,7 +2753,7 @@ void ClimateCommandRequest::dump_to(std::string &out) const {
|
||||
out.append("\n");
|
||||
|
||||
out.append(" mode: ");
|
||||
out.append(proto_enum_to_string<EnumClimateMode>(this->mode));
|
||||
out.append(proto_enum_to_string<enums::ClimateMode>(this->mode));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" has_target_temperature: ");
|
||||
|
||||
@@ -5,26 +5,28 @@
|
||||
namespace esphome {
|
||||
namespace api {
|
||||
|
||||
enum EnumLegacyCoverState : uint32_t {
|
||||
namespace enums {
|
||||
|
||||
enum LegacyCoverState : uint32_t {
|
||||
LEGACY_COVER_STATE_OPEN = 0,
|
||||
LEGACY_COVER_STATE_CLOSED = 1,
|
||||
};
|
||||
enum EnumCoverOperation : uint32_t {
|
||||
enum CoverOperation : uint32_t {
|
||||
COVER_OPERATION_IDLE = 0,
|
||||
COVER_OPERATION_IS_OPENING = 1,
|
||||
COVER_OPERATION_IS_CLOSING = 2,
|
||||
};
|
||||
enum EnumLegacyCoverCommand : uint32_t {
|
||||
enum LegacyCoverCommand : uint32_t {
|
||||
LEGACY_COVER_COMMAND_OPEN = 0,
|
||||
LEGACY_COVER_COMMAND_CLOSE = 1,
|
||||
LEGACY_COVER_COMMAND_STOP = 2,
|
||||
};
|
||||
enum EnumFanSpeed : uint32_t {
|
||||
enum FanSpeed : uint32_t {
|
||||
FAN_SPEED_LOW = 0,
|
||||
FAN_SPEED_MEDIUM = 1,
|
||||
FAN_SPEED_HIGH = 2,
|
||||
};
|
||||
enum EnumLogLevel : uint32_t {
|
||||
enum LogLevel : uint32_t {
|
||||
LOG_LEVEL_NONE = 0,
|
||||
LOG_LEVEL_ERROR = 1,
|
||||
LOG_LEVEL_WARN = 2,
|
||||
@@ -33,7 +35,7 @@ enum EnumLogLevel : uint32_t {
|
||||
LOG_LEVEL_VERBOSE = 5,
|
||||
LOG_LEVEL_VERY_VERBOSE = 6,
|
||||
};
|
||||
enum EnumServiceArgType : uint32_t {
|
||||
enum ServiceArgType : uint32_t {
|
||||
SERVICE_ARG_TYPE_BOOL = 0,
|
||||
SERVICE_ARG_TYPE_INT = 1,
|
||||
SERVICE_ARG_TYPE_FLOAT = 2,
|
||||
@@ -43,17 +45,20 @@ enum EnumServiceArgType : uint32_t {
|
||||
SERVICE_ARG_TYPE_FLOAT_ARRAY = 6,
|
||||
SERVICE_ARG_TYPE_STRING_ARRAY = 7,
|
||||
};
|
||||
enum EnumClimateMode : uint32_t {
|
||||
enum ClimateMode : uint32_t {
|
||||
CLIMATE_MODE_OFF = 0,
|
||||
CLIMATE_MODE_AUTO = 1,
|
||||
CLIMATE_MODE_COOL = 2,
|
||||
CLIMATE_MODE_HEAT = 3,
|
||||
};
|
||||
enum EnumClimateAction : uint32_t {
|
||||
enum ClimateAction : uint32_t {
|
||||
CLIMATE_ACTION_OFF = 0,
|
||||
CLIMATE_ACTION_COOLING = 2,
|
||||
CLIMATE_ACTION_HEATING = 3,
|
||||
};
|
||||
|
||||
} // namespace enums
|
||||
|
||||
class HelloRequest : public ProtoMessage {
|
||||
public:
|
||||
std::string client_info{}; // NOLINT
|
||||
@@ -183,8 +188,9 @@ class ListEntitiesBinarySensorResponse : public ProtoMessage {
|
||||
};
|
||||
class BinarySensorStateResponse : public ProtoMessage {
|
||||
public:
|
||||
uint32_t key{0}; // NOLINT
|
||||
bool state{false}; // NOLINT
|
||||
uint32_t key{0}; // NOLINT
|
||||
bool state{false}; // NOLINT
|
||||
bool missing_state{false}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
@@ -212,11 +218,11 @@ class ListEntitiesCoverResponse : public ProtoMessage {
|
||||
};
|
||||
class CoverStateResponse : public ProtoMessage {
|
||||
public:
|
||||
uint32_t key{0}; // NOLINT
|
||||
EnumLegacyCoverState legacy_state{}; // NOLINT
|
||||
float position{0.0f}; // NOLINT
|
||||
float tilt{0.0f}; // NOLINT
|
||||
EnumCoverOperation current_operation{}; // NOLINT
|
||||
uint32_t key{0}; // NOLINT
|
||||
enums::LegacyCoverState legacy_state{}; // NOLINT
|
||||
float position{0.0f}; // NOLINT
|
||||
float tilt{0.0f}; // NOLINT
|
||||
enums::CoverOperation current_operation{}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
@@ -226,14 +232,14 @@ class CoverStateResponse : public ProtoMessage {
|
||||
};
|
||||
class CoverCommandRequest : public ProtoMessage {
|
||||
public:
|
||||
uint32_t key{0}; // NOLINT
|
||||
bool has_legacy_command{false}; // NOLINT
|
||||
EnumLegacyCoverCommand legacy_command{}; // NOLINT
|
||||
bool has_position{false}; // NOLINT
|
||||
float position{0.0f}; // NOLINT
|
||||
bool has_tilt{false}; // NOLINT
|
||||
float tilt{0.0f}; // NOLINT
|
||||
bool stop{false}; // NOLINT
|
||||
uint32_t key{0}; // NOLINT
|
||||
bool has_legacy_command{false}; // NOLINT
|
||||
enums::LegacyCoverCommand legacy_command{}; // NOLINT
|
||||
bool has_position{false}; // NOLINT
|
||||
float position{0.0f}; // NOLINT
|
||||
bool has_tilt{false}; // NOLINT
|
||||
float tilt{0.0f}; // NOLINT
|
||||
bool stop{false}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
@@ -262,7 +268,7 @@ class FanStateResponse : public ProtoMessage {
|
||||
uint32_t key{0}; // NOLINT
|
||||
bool state{false}; // NOLINT
|
||||
bool oscillating{false}; // NOLINT
|
||||
EnumFanSpeed speed{}; // NOLINT
|
||||
enums::FanSpeed speed{}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
@@ -276,7 +282,7 @@ class FanCommandRequest : public ProtoMessage {
|
||||
bool has_state{false}; // NOLINT
|
||||
bool state{false}; // NOLINT
|
||||
bool has_speed{false}; // NOLINT
|
||||
EnumFanSpeed speed{}; // NOLINT
|
||||
enums::FanSpeed speed{}; // NOLINT
|
||||
bool has_oscillating{false}; // NOLINT
|
||||
bool oscillating{false}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
@@ -364,6 +370,7 @@ class ListEntitiesSensorResponse : public ProtoMessage {
|
||||
std::string icon{}; // NOLINT
|
||||
std::string unit_of_measurement{}; // NOLINT
|
||||
int32_t accuracy_decimals{0}; // NOLINT
|
||||
bool force_update{false}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
@@ -374,13 +381,15 @@ class ListEntitiesSensorResponse : public ProtoMessage {
|
||||
};
|
||||
class SensorStateResponse : public ProtoMessage {
|
||||
public:
|
||||
uint32_t key{0}; // NOLINT
|
||||
float state{0.0f}; // NOLINT
|
||||
uint32_t key{0}; // NOLINT
|
||||
float state{0.0f}; // NOLINT
|
||||
bool missing_state{false}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class ListEntitiesSwitchResponse : public ProtoMessage {
|
||||
public:
|
||||
@@ -436,18 +445,20 @@ class ListEntitiesTextSensorResponse : public ProtoMessage {
|
||||
};
|
||||
class TextSensorStateResponse : public ProtoMessage {
|
||||
public:
|
||||
uint32_t key{0}; // NOLINT
|
||||
std::string state{}; // NOLINT
|
||||
uint32_t key{0}; // NOLINT
|
||||
std::string state{}; // NOLINT
|
||||
bool missing_state{false}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
protected:
|
||||
bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
|
||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
|
||||
bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
|
||||
};
|
||||
class SubscribeLogsRequest : public ProtoMessage {
|
||||
public:
|
||||
EnumLogLevel level{}; // NOLINT
|
||||
enums::LogLevel level{}; // NOLINT
|
||||
bool dump_config{false}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
@@ -457,7 +468,7 @@ class SubscribeLogsRequest : public ProtoMessage {
|
||||
};
|
||||
class SubscribeLogsResponse : public ProtoMessage {
|
||||
public:
|
||||
EnumLogLevel level{}; // NOLINT
|
||||
enums::LogLevel level{}; // NOLINT
|
||||
std::string tag{}; // NOLINT
|
||||
std::string message{}; // NOLINT
|
||||
bool send_failed{false}; // NOLINT
|
||||
@@ -543,8 +554,8 @@ class GetTimeResponse : public ProtoMessage {
|
||||
};
|
||||
class ListEntitiesServicesArgument : public ProtoMessage {
|
||||
public:
|
||||
std::string name{}; // NOLINT
|
||||
EnumServiceArgType type{}; // NOLINT
|
||||
std::string name{}; // NOLINT
|
||||
enums::ServiceArgType type{}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
@@ -638,7 +649,7 @@ class ListEntitiesClimateResponse : public ProtoMessage {
|
||||
std::string unique_id{}; // NOLINT
|
||||
bool supports_current_temperature{false}; // NOLINT
|
||||
bool supports_two_point_target_temperature{false}; // NOLINT
|
||||
std::vector<EnumClimateMode> supported_modes{}; // NOLINT
|
||||
std::vector<enums::ClimateMode> supported_modes{}; // NOLINT
|
||||
float visual_min_temperature{0.0f}; // NOLINT
|
||||
float visual_max_temperature{0.0f}; // NOLINT
|
||||
float visual_temperature_step{0.0f}; // NOLINT
|
||||
@@ -655,13 +666,13 @@ class ListEntitiesClimateResponse : public ProtoMessage {
|
||||
class ClimateStateResponse : public ProtoMessage {
|
||||
public:
|
||||
uint32_t key{0}; // NOLINT
|
||||
EnumClimateMode mode{}; // NOLINT
|
||||
enums::ClimateMode mode{}; // NOLINT
|
||||
float current_temperature{0.0f}; // NOLINT
|
||||
float target_temperature{0.0f}; // NOLINT
|
||||
float target_temperature_low{0.0f}; // NOLINT
|
||||
float target_temperature_high{0.0f}; // NOLINT
|
||||
bool away{false}; // NOLINT
|
||||
EnumClimateAction action{}; // NOLINT
|
||||
enums::ClimateAction action{}; // NOLINT
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
void dump_to(std::string &out) const override;
|
||||
|
||||
@@ -673,7 +684,7 @@ class ClimateCommandRequest : public ProtoMessage {
|
||||
public:
|
||||
uint32_t key{0}; // NOLINT
|
||||
bool has_mode{false}; // NOLINT
|
||||
EnumClimateMode mode{}; // NOLINT
|
||||
enums::ClimateMode mode{}; // NOLINT
|
||||
bool has_target_temperature{false}; // NOLINT
|
||||
float target_temperature{0.0f}; // NOLINT
|
||||
bool has_target_temperature_low{false}; // NOLINT
|
||||
|
||||
@@ -7,9 +7,6 @@ namespace api {
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
bool InitialStateIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) {
|
||||
if (!binary_sensor->has_state())
|
||||
return true;
|
||||
|
||||
return this->client_->send_binary_sensor_state(binary_sensor, binary_sensor->state);
|
||||
}
|
||||
#endif
|
||||
@@ -24,9 +21,6 @@ bool InitialStateIterator::on_light(light::LightState *light) { return this->cli
|
||||
#endif
|
||||
#ifdef USE_SENSOR
|
||||
bool InitialStateIterator::on_sensor(sensor::Sensor *sensor) {
|
||||
if (!sensor->has_state())
|
||||
return true;
|
||||
|
||||
return this->client_->send_sensor_state(sensor, sensor->state);
|
||||
}
|
||||
#endif
|
||||
@@ -37,9 +31,6 @@ bool InitialStateIterator::on_switch(switch_::Switch *a_switch) {
|
||||
#endif
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
bool InitialStateIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
|
||||
if (!text_sensor->has_state())
|
||||
return true;
|
||||
|
||||
return this->client_->send_text_sensor_state(text_sensor, text_sensor->state);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -25,14 +25,18 @@ template<> std::vector<std::string> get_execute_arg_value<std::vector<std::strin
|
||||
return arg.string_array;
|
||||
}
|
||||
|
||||
template<> EnumServiceArgType to_service_arg_type<bool>() { return SERVICE_ARG_TYPE_BOOL; }
|
||||
template<> EnumServiceArgType to_service_arg_type<int>() { return SERVICE_ARG_TYPE_INT; }
|
||||
template<> EnumServiceArgType to_service_arg_type<float>() { return SERVICE_ARG_TYPE_FLOAT; }
|
||||
template<> EnumServiceArgType to_service_arg_type<std::string>() { return SERVICE_ARG_TYPE_STRING; }
|
||||
template<> EnumServiceArgType to_service_arg_type<std::vector<bool>>() { return SERVICE_ARG_TYPE_BOOL_ARRAY; }
|
||||
template<> EnumServiceArgType to_service_arg_type<std::vector<int>>() { return SERVICE_ARG_TYPE_INT_ARRAY; }
|
||||
template<> EnumServiceArgType to_service_arg_type<std::vector<float>>() { return SERVICE_ARG_TYPE_FLOAT_ARRAY; }
|
||||
template<> EnumServiceArgType to_service_arg_type<std::vector<std::string>>() { return SERVICE_ARG_TYPE_STRING_ARRAY; }
|
||||
template<> enums::ServiceArgType to_service_arg_type<bool>() { return enums::SERVICE_ARG_TYPE_BOOL; }
|
||||
template<> enums::ServiceArgType to_service_arg_type<int>() { return enums::SERVICE_ARG_TYPE_INT; }
|
||||
template<> enums::ServiceArgType to_service_arg_type<float>() { return enums::SERVICE_ARG_TYPE_FLOAT; }
|
||||
template<> enums::ServiceArgType to_service_arg_type<std::string>() { return enums::SERVICE_ARG_TYPE_STRING; }
|
||||
template<> enums::ServiceArgType to_service_arg_type<std::vector<bool>>() { return enums::SERVICE_ARG_TYPE_BOOL_ARRAY; }
|
||||
template<> enums::ServiceArgType to_service_arg_type<std::vector<int>>() { return enums::SERVICE_ARG_TYPE_INT_ARRAY; }
|
||||
template<> enums::ServiceArgType to_service_arg_type<std::vector<float>>() {
|
||||
return enums::SERVICE_ARG_TYPE_FLOAT_ARRAY;
|
||||
}
|
||||
template<> enums::ServiceArgType to_service_arg_type<std::vector<std::string>>() {
|
||||
return enums::SERVICE_ARG_TYPE_STRING_ARRAY;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
} // namespace esphome
|
||||
|
||||
@@ -16,7 +16,7 @@ class UserServiceDescriptor {
|
||||
|
||||
template<typename T> T get_execute_arg_value(const ExecuteServiceArgument &arg);
|
||||
|
||||
template<typename T> EnumServiceArgType to_service_arg_type();
|
||||
template<typename T> enums::ServiceArgType to_service_arg_type();
|
||||
|
||||
template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
|
||||
public:
|
||||
@@ -29,7 +29,7 @@ template<typename... Ts> class UserServiceBase : public UserServiceDescriptor {
|
||||
ListEntitiesServicesResponse msg;
|
||||
msg.name = this->name_;
|
||||
msg.key = this->key_;
|
||||
std::array<EnumServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
|
||||
std::array<enums::ServiceArgType, sizeof...(Ts)> arg_types = {to_service_arg_type<Ts>()...};
|
||||
for (int i = 0; i < sizeof...(Ts); i++) {
|
||||
ListEntitiesServicesArgument arg;
|
||||
arg.type = arg_types[i];
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.const import CONF_PIN, CONF_INDOOR, CONF_WATCHDOG_THRESHOLD, \
|
||||
from esphome.const import CONF_INDOOR, CONF_WATCHDOG_THRESHOLD, \
|
||||
CONF_NOISE_LEVEL, CONF_SPIKE_REJECTION, CONF_LIGHTNING_THRESHOLD, \
|
||||
CONF_MASK_DISTURBER, CONF_DIV_RATIO, CONF_CAPACITANCE
|
||||
from esphome.core import coroutine
|
||||
|
||||
|
||||
AUTO_LOAD = ['sensor', 'binary_sensor']
|
||||
MULTI_CONF = True
|
||||
|
||||
@@ -15,10 +14,10 @@ CONF_AS3935_ID = 'as3935_id'
|
||||
as3935_ns = cg.esphome_ns.namespace('as3935')
|
||||
AS3935 = as3935_ns.class_('AS3935Component', cg.Component)
|
||||
|
||||
CONF_IRQ_PIN = 'irq_pin'
|
||||
AS3935_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(AS3935),
|
||||
cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema,
|
||||
pins.validate_has_interrupt),
|
||||
cv.Required(CONF_IRQ_PIN): pins.gpio_input_pin_schema,
|
||||
|
||||
cv.Optional(CONF_INDOOR, default=True): cv.boolean,
|
||||
cv.Optional(CONF_NOISE_LEVEL, default=2): cv.int_range(min=1, max=7),
|
||||
@@ -35,8 +34,8 @@ AS3935_SCHEMA = cv.Schema({
|
||||
def setup_as3935(var, config):
|
||||
yield cg.register_component(var, config)
|
||||
|
||||
pin = yield cg.gpio_pin_expression(config[CONF_PIN])
|
||||
cg.add(var.set_pin(pin))
|
||||
irq_pin = yield cg.gpio_pin_expression(config[CONF_IRQ_PIN])
|
||||
cg.add(var.set_irq_pin(irq_pin))
|
||||
cg.add(var.set_indoor(config[CONF_INDOOR]))
|
||||
cg.add(var.set_noise_level(config[CONF_NOISE_LEVEL]))
|
||||
cg.add(var.set_watchdog_threshold(config[CONF_WATCHDOG_THRESHOLD]))
|
||||
|
||||
@@ -9,10 +9,8 @@ static const char *TAG = "as3935";
|
||||
void AS3935Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up AS3935...");
|
||||
|
||||
this->pin_->setup();
|
||||
this->store_.pin = this->pin_->to_isr();
|
||||
LOG_PIN(" Interrupt Pin: ", this->pin_);
|
||||
this->pin_->attach_interrupt(AS3935ComponentStore::gpio_intr, &this->store_, RISING);
|
||||
this->irq_pin_->setup();
|
||||
LOG_PIN(" IRQ Pin: ", this->irq_pin_);
|
||||
|
||||
// Write properties to sensor
|
||||
this->write_indoor(this->indoor_);
|
||||
@@ -27,13 +25,13 @@ void AS3935Component::setup() {
|
||||
|
||||
void AS3935Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "AS3935:");
|
||||
LOG_PIN(" Interrupt Pin: ", this->pin_);
|
||||
LOG_PIN(" Interrupt Pin: ", this->irq_pin_);
|
||||
}
|
||||
|
||||
float AS3935Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
void AS3935Component::loop() {
|
||||
if (!this->store_.interrupt)
|
||||
if (!this->irq_pin_->digital_read())
|
||||
return;
|
||||
|
||||
uint8_t int_value = this->read_interrupt_register_();
|
||||
@@ -53,7 +51,6 @@ void AS3935Component::loop() {
|
||||
this->energy_sensor_->publish_state(energy);
|
||||
}
|
||||
this->thunder_alert_binary_sensor_->publish_state(false);
|
||||
this->store_.interrupt = false;
|
||||
}
|
||||
|
||||
void AS3935Component::write_indoor(bool indoor) {
|
||||
@@ -222,7 +219,5 @@ uint8_t AS3935Component::read_register_(uint8_t reg, uint8_t mask) {
|
||||
return value;
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR AS3935ComponentStore::gpio_intr(AS3935ComponentStore *arg) { arg->interrupt = true; }
|
||||
|
||||
} // namespace as3935
|
||||
} // namespace esphome
|
||||
|
||||
@@ -50,14 +50,6 @@ enum AS3935Values {
|
||||
NOISE_INT = 0x01
|
||||
};
|
||||
|
||||
/// Store data in a class that doesn't use multiple-inheritance (vtables in flash)
|
||||
struct AS3935ComponentStore {
|
||||
volatile bool interrupt;
|
||||
|
||||
ISRInternalGPIOPin *pin;
|
||||
static void gpio_intr(AS3935ComponentStore *arg);
|
||||
};
|
||||
|
||||
class AS3935Component : public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
@@ -65,7 +57,7 @@ class AS3935Component : public Component {
|
||||
float get_setup_priority() const override;
|
||||
void loop() override;
|
||||
|
||||
void set_pin(GPIOPin *pin) { pin_ = pin; }
|
||||
void set_irq_pin(GPIOPin *irq_pin) { irq_pin_ = irq_pin; }
|
||||
void set_distance_sensor(sensor::Sensor *distance_sensor) { distance_sensor_ = distance_sensor; }
|
||||
void set_energy_sensor(sensor::Sensor *energy_sensor) { energy_sensor_ = energy_sensor; }
|
||||
void set_thunder_alert_binary_sensor(binary_sensor::BinarySensor *thunder_alert_binary_sensor) {
|
||||
@@ -102,8 +94,7 @@ class AS3935Component : public Component {
|
||||
sensor::Sensor *distance_sensor_;
|
||||
sensor::Sensor *energy_sensor_;
|
||||
binary_sensor::BinarySensor *thunder_alert_binary_sensor_;
|
||||
GPIOPin *pin_;
|
||||
AS3935ComponentStore store_;
|
||||
GPIOPin *irq_pin_;
|
||||
|
||||
bool indoor_;
|
||||
uint8_t noise_level_;
|
||||
|
||||
@@ -31,6 +31,10 @@ uint8_t I2CAS3935Component::read_register(uint8_t reg) {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
void I2CAS3935Component::dump_config() {
|
||||
AS3935Component::dump_config();
|
||||
LOG_I2C_DEVICE(this);
|
||||
}
|
||||
|
||||
} // namespace as3935_i2c
|
||||
} // namespace esphome
|
||||
|
||||
@@ -10,6 +10,9 @@ namespace esphome {
|
||||
namespace as3935_i2c {
|
||||
|
||||
class I2CAS3935Component : public as3935::AS3935Component, public i2c::I2CDevice {
|
||||
public:
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
void write_register(uint8_t reg, uint8_t mask, uint8_t bits, uint8_t start_position) override;
|
||||
uint8_t read_register(uint8_t reg) override;
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
# Dummy integration to allow relying on AsyncTCP
|
||||
import esphome.codegen as cg
|
||||
from esphome.const import ARDUINO_VERSION_ESP32_1_0_0, ARDUINO_VERSION_ESP32_1_0_1, \
|
||||
ARDUINO_VERSION_ESP32_1_0_2
|
||||
from esphome.core import CORE, coroutine_with_priority
|
||||
|
||||
|
||||
@coroutine_with_priority(200.0)
|
||||
def to_code(config):
|
||||
if CORE.is_esp32:
|
||||
# https://github.com/me-no-dev/AsyncTCP/blob/master/library.json
|
||||
versions_requiring_older_asynctcp = [
|
||||
ARDUINO_VERSION_ESP32_1_0_0,
|
||||
ARDUINO_VERSION_ESP32_1_0_1,
|
||||
ARDUINO_VERSION_ESP32_1_0_2,
|
||||
]
|
||||
if CORE.arduino_version in versions_requiring_older_asynctcp:
|
||||
cg.add_library('AsyncTCP', '1.0.3')
|
||||
else:
|
||||
cg.add_library('AsyncTCP', '1.1.1')
|
||||
# https://github.com/OttoWinter/AsyncTCP/blob/master/library.json
|
||||
cg.add_library('AsyncTCP-esphome', '1.1.1')
|
||||
elif CORE.is_esp8266:
|
||||
# https://github.com/OttoWinter/ESPAsyncTCP
|
||||
cg.add_library('ESPAsyncTCP-esphome', '1.2.2')
|
||||
|
||||
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
||||
from esphome.components import sensor, spi
|
||||
from esphome.const import \
|
||||
CONF_ID, CONF_VOLTAGE, CONF_CURRENT, CONF_POWER, CONF_FREQUENCY, \
|
||||
ICON_FLASH, UNIT_HZ, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT
|
||||
ICON_FLASH, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT, UNIT_HERTZ, ICON_CURRENT_AC
|
||||
|
||||
CONF_PHASE_A = 'phase_a'
|
||||
CONF_PHASE_B = 'phase_b'
|
||||
@@ -39,7 +39,7 @@ CONFIG_SCHEMA = cv.Schema({
|
||||
cv.Optional(CONF_PHASE_A): ATM90E32_PHASE_SCHEMA,
|
||||
cv.Optional(CONF_PHASE_B): ATM90E32_PHASE_SCHEMA,
|
||||
cv.Optional(CONF_PHASE_C): ATM90E32_PHASE_SCHEMA,
|
||||
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(UNIT_HZ, ICON_FLASH, 1),
|
||||
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(UNIT_HERTZ, ICON_CURRENT_AC, 1),
|
||||
cv.Required(CONF_LINE_FREQUENCY): cv.enum(LINE_FREQS, upper=True),
|
||||
cv.Optional(CONF_GAIN_PGA, default='2X'): cv.enum(PGA_GAINS, upper=True),
|
||||
}).extend(cv.polling_component_schema('60s')).extend(spi.SPI_DEVICE_SCHEMA)
|
||||
|
||||
@@ -145,6 +145,14 @@ Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger
|
||||
void BangBangClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
|
||||
Trigger<> *BangBangClimate::get_heat_trigger() const { return this->heat_trigger_; }
|
||||
void BangBangClimate::set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
|
||||
void BangBangClimate::dump_config() {
|
||||
LOG_CLIMATE("", "Bang Bang Climate", this);
|
||||
ESP_LOGCONFIG(TAG, " Supports HEAT: %s", YESNO(this->supports_heat_));
|
||||
ESP_LOGCONFIG(TAG, " Supports COOL: %s", YESNO(this->supports_cool_));
|
||||
ESP_LOGCONFIG(TAG, " Supports AWAY mode: %s", YESNO(this->supports_away_));
|
||||
ESP_LOGCONFIG(TAG, " Default Target Temperature Low: %.1f°C", this->normal_config_.default_temperature_low);
|
||||
ESP_LOGCONFIG(TAG, " Default Target Temperature High: %.1f°C", this->normal_config_.default_temperature_high);
|
||||
}
|
||||
|
||||
BangBangClimateTargetTempConfig::BangBangClimateTargetTempConfig() = default;
|
||||
BangBangClimateTargetTempConfig::BangBangClimateTargetTempConfig(float default_temperature_low,
|
||||
|
||||
@@ -21,6 +21,7 @@ class BangBangClimate : public climate::Climate, public Component {
|
||||
public:
|
||||
BangBangClimate();
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
|
||||
void set_sensor(sensor::Sensor *sensor);
|
||||
Trigger<> *get_idle_trigger() const;
|
||||
|
||||
@@ -24,4 +24,4 @@ def to_code(config):
|
||||
|
||||
if CONF_OSCILLATION_OUTPUT in config:
|
||||
oscillation_output = yield cg.get_variable(config[CONF_OSCILLATION_OUTPUT])
|
||||
cg.add(var.set_oscillation(oscillation_output))
|
||||
cg.add(var.set_oscillating(oscillation_output))
|
||||
|
||||
@@ -23,6 +23,7 @@ IS_PLATFORM_COMPONENT = True
|
||||
|
||||
binary_sensor_ns = cg.esphome_ns.namespace('binary_sensor')
|
||||
BinarySensor = binary_sensor_ns.class_('BinarySensor', cg.Nameable)
|
||||
BinarySensorInitiallyOff = binary_sensor_ns.class_('BinarySensorInitiallyOff', BinarySensor)
|
||||
BinarySensorPtr = BinarySensor.operator('ptr')
|
||||
|
||||
# Triggers
|
||||
|
||||
@@ -10,9 +10,9 @@ namespace binary_sensor {
|
||||
|
||||
#define LOG_BINARY_SENSOR(prefix, type, obj) \
|
||||
if (obj != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, prefix type " '%s'", obj->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, type, obj->get_name().c_str()); \
|
||||
if (!obj->get_device_class().empty()) { \
|
||||
ESP_LOGCONFIG(TAG, prefix " Device Class: '%s'", obj->get_device_class().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, obj->get_device_class().c_str()); \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ class BinarySensor : public Nameable {
|
||||
void send_state_internal(bool state, bool is_initial);
|
||||
|
||||
/// Return whether this binary sensor has outputted a state.
|
||||
bool has_state() const;
|
||||
virtual bool has_state() const;
|
||||
|
||||
virtual bool is_status_binary_sensor() const;
|
||||
|
||||
@@ -86,5 +86,10 @@ class BinarySensor : public Nameable {
|
||||
Deduplicator<bool> publish_dedup_;
|
||||
};
|
||||
|
||||
class BinarySensorInitiallyOff : public BinarySensor {
|
||||
public:
|
||||
bool has_state() const override { return true; }
|
||||
};
|
||||
|
||||
} // namespace binary_sensor
|
||||
} // namespace esphome
|
||||
|
||||
@@ -3,7 +3,7 @@ import esphome.config_validation as cv
|
||||
|
||||
from esphome.components import sensor, binary_sensor
|
||||
from esphome.const import CONF_ID, CONF_CHANNELS, CONF_VALUE, CONF_TYPE, UNIT_EMPTY, \
|
||||
ICON_CHECK_CIRCLE_OUTLINE, CONF_BINARY_SENSOR
|
||||
ICON_CHECK_CIRCLE_OUTLINE, CONF_BINARY_SENSOR, CONF_GROUP
|
||||
|
||||
DEPENDENCIES = ['binary_sensor']
|
||||
|
||||
@@ -11,7 +11,6 @@ binary_sensor_map_ns = cg.esphome_ns.namespace('binary_sensor_map')
|
||||
BinarySensorMap = binary_sensor_map_ns.class_('BinarySensorMap', cg.Component, sensor.Sensor)
|
||||
SensorMapType = binary_sensor_map_ns.enum('SensorMapType')
|
||||
|
||||
CONF_GROUP = 'group'
|
||||
SENSOR_MAP_TYPES = {
|
||||
CONF_GROUP: SensorMapType.BINARY_SENSOR_MAP_TYPE_GROUP,
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace esphome {
|
||||
namespace ble_presence {
|
||||
|
||||
class BLEPresenceDevice : public binary_sensor::BinarySensor,
|
||||
class BLEPresenceDevice : public binary_sensor::BinarySensorInitiallyOff,
|
||||
public esp32_ble_tracker::ESPBTDeviceListener,
|
||||
public Component {
|
||||
public:
|
||||
|
||||
@@ -166,6 +166,7 @@ float CaptivePortal::get_setup_priority() const {
|
||||
// Before WiFi
|
||||
return setup_priority::WIFI + 1.0f;
|
||||
}
|
||||
void CaptivePortal::dump_config() { ESP_LOGCONFIG(TAG, "Captive Portal:"); }
|
||||
|
||||
CaptivePortal *global_captive_portal = nullptr;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <DNSServer.h>
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
#include "esphome/components/web_server_base/web_server_base.h"
|
||||
|
||||
@@ -18,6 +19,7 @@ class CaptivePortal : public AsyncWebHandler, public Component {
|
||||
public:
|
||||
CaptivePortal(web_server_base::WebServerBase *base);
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void loop() override {
|
||||
if (this->dns_server_ != nullptr)
|
||||
this->dns_server_->processNextRequest();
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
namespace esphome {
|
||||
namespace climate {
|
||||
|
||||
#define LOG_CLIMATE(prefix, type, obj) \
|
||||
if (obj != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, type, obj->get_name().c_str()); \
|
||||
}
|
||||
|
||||
class Climate;
|
||||
|
||||
/** This class is used to encode all control actions on a climate device.
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate, remote_transmitter, remote_receiver, sensor, remote_base
|
||||
from esphome.components.remote_base import CONF_RECEIVER_ID, CONF_TRANSMITTER_ID
|
||||
from esphome.const import CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT, CONF_SENSOR
|
||||
from esphome.core import coroutine
|
||||
|
||||
AUTO_LOAD = ['sensor', 'remote_base']
|
||||
|
||||
climate_ir_ns = cg.esphome_ns.namespace('climate_ir')
|
||||
ClimateIR = climate_ir_ns.class_('ClimateIR', climate.Climate, cg.Component,
|
||||
remote_base.RemoteReceiverListener)
|
||||
|
||||
CLIMATE_IR_SCHEMA = climate.CLIMATE_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent),
|
||||
cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean,
|
||||
cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean,
|
||||
cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
CLIMATE_IR_WITH_RECEIVER_SCHEMA = CLIMATE_IR_SCHEMA.extend({
|
||||
cv.Optional(CONF_RECEIVER_ID): cv.use_id(remote_receiver.RemoteReceiverComponent),
|
||||
})
|
||||
|
||||
|
||||
@coroutine
|
||||
def register_climate_ir(var, config):
|
||||
yield cg.register_component(var, config)
|
||||
yield climate.register_climate(var, config)
|
||||
|
||||
cg.add(var.set_supports_cool(config[CONF_SUPPORTS_COOL]))
|
||||
cg.add(var.set_supports_heat(config[CONF_SUPPORTS_HEAT]))
|
||||
if CONF_SENSOR in config:
|
||||
sens = yield cg.get_variable(config[CONF_SENSOR])
|
||||
cg.add(var.set_sensor(sens))
|
||||
if CONF_RECEIVER_ID in config:
|
||||
receiver = yield cg.get_variable(config[CONF_RECEIVER_ID])
|
||||
cg.add(receiver.register_listener(var))
|
||||
|
||||
transmitter = yield cg.get_variable(config[CONF_TRANSMITTER_ID])
|
||||
cg.add(var.set_transmitter(transmitter))
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "climate_ir.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace climate {
|
||||
namespace climate_ir {
|
||||
|
||||
static const char *TAG = "climate_ir";
|
||||
|
||||
climate::ClimateTraits ClimateIR::traits() {
|
||||
auto traits = climate::ClimateTraits();
|
||||
@@ -52,6 +55,13 @@ void ClimateIR::control(const climate::ClimateCall &call) {
|
||||
this->transmit_state();
|
||||
this->publish_state();
|
||||
}
|
||||
void ClimateIR::dump_config() {
|
||||
LOG_CLIMATE("", "IR Climate", this);
|
||||
ESP_LOGCONFIG(TAG, " Min. Temperature: %.1f°C", this->minimum_temperature_);
|
||||
ESP_LOGCONFIG(TAG, " Max. Temperature: %.1f°C", this->maximum_temperature_);
|
||||
ESP_LOGCONFIG(TAG, " Supports HEAT: %s", YESNO(this->supports_heat_));
|
||||
ESP_LOGCONFIG(TAG, " Supports COOL: %s", YESNO(this->supports_cool_));
|
||||
}
|
||||
|
||||
} // namespace climate
|
||||
} // namespace climate_ir
|
||||
} // namespace esphome
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace climate {
|
||||
namespace climate_ir {
|
||||
|
||||
/* A base for climate which works by sending (and receiving) IR codes
|
||||
|
||||
@@ -25,6 +25,7 @@ class ClimateIR : public climate::Climate, public Component, public remote_base:
|
||||
}
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void set_transmitter(remote_transmitter::RemoteTransmitterComponent *transmitter) {
|
||||
this->transmitter_ = transmitter;
|
||||
}
|
||||
@@ -41,7 +42,7 @@ class ClimateIR : public climate::Climate, public Component, public remote_base:
|
||||
climate::ClimateTraits traits() override;
|
||||
|
||||
/// Transmit via IR the state of this climate controller.
|
||||
virtual void transmit_state() {}
|
||||
virtual void transmit_state() = 0;
|
||||
|
||||
bool supports_cool_{true};
|
||||
bool supports_heat_{true};
|
||||
@@ -49,5 +50,6 @@ class ClimateIR : public climate::Climate, public Component, public remote_base:
|
||||
remote_transmitter::RemoteTransmitterComponent *transmitter_;
|
||||
sensor::Sensor *sensor_{nullptr};
|
||||
};
|
||||
} // namespace climate
|
||||
|
||||
} // namespace climate_ir
|
||||
} // namespace esphome
|
||||
|
||||
@@ -1,41 +1,18 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate, remote_transmitter, remote_receiver, sensor
|
||||
from esphome.const import CONF_ID, CONF_SENSOR
|
||||
from esphome.components import climate_ir
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
AUTO_LOAD = ['sensor', 'climate_ir']
|
||||
AUTO_LOAD = ['climate_ir']
|
||||
|
||||
coolix_ns = cg.esphome_ns.namespace('coolix')
|
||||
CoolixClimate = coolix_ns.class_('CoolixClimate', climate.Climate, cg.Component)
|
||||
CoolixClimate = coolix_ns.class_('CoolixClimate', climate_ir.ClimateIR)
|
||||
|
||||
CONF_TRANSMITTER_ID = 'transmitter_id'
|
||||
CONF_RECEIVER_ID = 'receiver_id'
|
||||
CONF_SUPPORTS_HEAT = 'supports_heat'
|
||||
CONF_SUPPORTS_COOL = 'supports_cool'
|
||||
|
||||
CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({
|
||||
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(CoolixClimate),
|
||||
cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent),
|
||||
cv.Optional(CONF_RECEIVER_ID): cv.use_id(remote_receiver.RemoteReceiverComponent),
|
||||
cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean,
|
||||
cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean,
|
||||
cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor),
|
||||
}).extend(cv.COMPONENT_SCHEMA))
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield climate.register_climate(var, config)
|
||||
|
||||
cg.add(var.set_supports_cool(config[CONF_SUPPORTS_COOL]))
|
||||
cg.add(var.set_supports_heat(config[CONF_SUPPORTS_HEAT]))
|
||||
if CONF_SENSOR in config:
|
||||
sens = yield cg.get_variable(config[CONF_SENSOR])
|
||||
cg.add(var.set_sensor(sens))
|
||||
if CONF_RECEIVER_ID in config:
|
||||
receiver = yield cg.get_variable(config[CONF_RECEIVER_ID])
|
||||
cg.add(receiver.register_listener(var))
|
||||
|
||||
transmitter = yield cg.get_variable(config[CONF_TRANSMITTER_ID])
|
||||
cg.add(var.set_transmitter(transmitter))
|
||||
yield climate_ir.register_climate_ir(var, config)
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace coolix {
|
||||
const uint8_t COOLIX_TEMP_MIN = 17; // Celsius
|
||||
const uint8_t COOLIX_TEMP_MAX = 30; // Celsius
|
||||
|
||||
class CoolixClimate : public climate::ClimateIR {
|
||||
class CoolixClimate : public climate_ir::ClimateIR {
|
||||
public:
|
||||
CoolixClimate() : climate::ClimateIR(COOLIX_TEMP_MIN, COOLIX_TEMP_MAX) {}
|
||||
CoolixClimate() : climate_ir::ClimateIR(COOLIX_TEMP_MIN, COOLIX_TEMP_MAX) {}
|
||||
|
||||
protected:
|
||||
/// Transmit via IR the state of this climate controller.
|
||||
|
||||
@@ -13,13 +13,13 @@ const extern float COVER_CLOSED;
|
||||
|
||||
#define LOG_COVER(prefix, type, obj) \
|
||||
if (obj != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, prefix type " '%s'", obj->get_name().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s%s '%s'", prefix, type, obj->get_name().c_str()); \
|
||||
auto traits_ = obj->get_traits(); \
|
||||
if (traits_.get_is_assumed_state()) { \
|
||||
ESP_LOGCONFIG(TAG, prefix " Assumed State: YES"); \
|
||||
ESP_LOGCONFIG(TAG, "%s Assumed State: YES", prefix); \
|
||||
} \
|
||||
if (!obj->get_device_class().empty()) { \
|
||||
ESP_LOGCONFIG(TAG, prefix " Device Class: '%s'", obj->get_device_class().c_str()); \
|
||||
ESP_LOGCONFIG(TAG, "%s Device Class: '%s'", prefix, obj->get_device_class().c_str()); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,7 @@ void CSE7766Component::dump_config() {
|
||||
LOG_SENSOR(" ", "Voltage", this->voltage_sensor_);
|
||||
LOG_SENSOR(" ", "Current", this->current_sensor_);
|
||||
LOG_SENSOR(" ", "Power", this->power_sensor_);
|
||||
this->check_uart_settings(4800);
|
||||
}
|
||||
|
||||
} // namespace cse7766
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import output
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE
|
||||
from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE, CONF_BINARY
|
||||
from .. import custom_ns
|
||||
|
||||
CustomBinaryOutputConstructor = custom_ns.class_('CustomBinaryOutputConstructor')
|
||||
CustomFloatOutputConstructor = custom_ns.class_('CustomFloatOutputConstructor')
|
||||
|
||||
CONF_BINARY = 'binary'
|
||||
CONF_FLOAT = 'float'
|
||||
|
||||
CONFIG_SCHEMA = cv.typed_schema({
|
||||
|
||||
219
esphome/components/dfplayer/__init__.py
Normal file
219
esphome/components/dfplayer/__init__.py
Normal file
@@ -0,0 +1,219 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.const import CONF_ID, CONF_TRIGGER_ID, CONF_FILE, CONF_DEVICE
|
||||
from esphome.components import uart
|
||||
|
||||
DEPENDENCIES = ['uart']
|
||||
|
||||
dfplayer_ns = cg.esphome_ns.namespace('dfplayer')
|
||||
DFPlayer = dfplayer_ns.class_('DFPlayer', cg.Component)
|
||||
DFPlayerFinishedPlaybackTrigger = dfplayer_ns.class_('DFPlayerFinishedPlaybackTrigger',
|
||||
automation.Trigger.template())
|
||||
DFPlayerIsPlayingCondition = dfplayer_ns.class_('DFPlayerIsPlayingCondition', automation.Condition)
|
||||
|
||||
MULTI_CONF = True
|
||||
CONF_FOLDER = 'folder'
|
||||
CONF_LOOP = 'loop'
|
||||
CONF_VOLUME = 'volume'
|
||||
CONF_EQ_PRESET = 'eq_preset'
|
||||
CONF_ON_FINISHED_PLAYBACK = 'on_finished_playback'
|
||||
|
||||
EqPreset = dfplayer_ns.enum("EqPreset")
|
||||
EQ_PRESET = {
|
||||
'NORMAL': EqPreset.NORMAL,
|
||||
'POP': EqPreset.POP,
|
||||
'ROCK': EqPreset.ROCK,
|
||||
'JAZZ': EqPreset.JAZZ,
|
||||
'CLASSIC': EqPreset.CLASSIC,
|
||||
'BASS': EqPreset.BASS,
|
||||
}
|
||||
Device = dfplayer_ns.enum("Device")
|
||||
DEVICE = {
|
||||
'USB': Device.USB,
|
||||
'TF_CARD': Device.TF_CARD,
|
||||
}
|
||||
|
||||
NextAction = dfplayer_ns.class_('NextAction', automation.Action)
|
||||
PreviousAction = dfplayer_ns.class_('PreviousAction', automation.Action)
|
||||
PlayFileAction = dfplayer_ns.class_('PlayFileAction', automation.Action)
|
||||
PlayFolderAction = dfplayer_ns.class_('PlayFolderAction', automation.Action)
|
||||
SetVolumeAction = dfplayer_ns.class_('SetVolumeAction', automation.Action)
|
||||
SetEqAction = dfplayer_ns.class_('SetEqAction', automation.Action)
|
||||
SleepAction = dfplayer_ns.class_('SleepAction', automation.Action)
|
||||
ResetAction = dfplayer_ns.class_('ResetAction', automation.Action)
|
||||
StartAction = dfplayer_ns.class_('StartAction', automation.Action)
|
||||
PauseAction = dfplayer_ns.class_('PauseAction', automation.Action)
|
||||
StopAction = dfplayer_ns.class_('StopAction', automation.Action)
|
||||
RandomAction = dfplayer_ns.class_('RandomAction', automation.Action)
|
||||
SetDeviceAction = dfplayer_ns.class_('SetDeviceAction', automation.Action)
|
||||
|
||||
CONFIG_SCHEMA = cv.All(cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(DFPlayer),
|
||||
cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation({
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DFPlayerFinishedPlaybackTrigger),
|
||||
}),
|
||||
}).extend(uart.UART_DEVICE_SCHEMA))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield uart.register_uart_device(var, config)
|
||||
|
||||
for conf in config.get(CONF_ON_FINISHED_PLAYBACK, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
yield automation.build_automation(trigger, [], conf)
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.play_next', NextAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_next_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.play_previous', PreviousAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_previous_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.play', PlayFileAction, cv.maybe_simple_value({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
cv.Required(CONF_FILE): cv.templatable(cv.int_),
|
||||
cv.Optional(CONF_LOOP): cv.templatable(cv.boolean),
|
||||
}, key=CONF_FILE))
|
||||
def dfplayer_play_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
template_ = yield cg.templatable(config[CONF_FILE], args, float)
|
||||
cg.add(var.set_file(template_))
|
||||
if CONF_LOOP in config:
|
||||
template_ = yield cg.templatable(config[CONF_LOOP], args, float)
|
||||
cg.add(var.set_loop(template_))
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.play_folder', PlayFolderAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
cv.Required(CONF_FOLDER): cv.templatable(cv.int_),
|
||||
cv.Optional(CONF_FILE): cv.templatable(cv.int_),
|
||||
cv.Optional(CONF_LOOP): cv.templatable(cv.boolean),
|
||||
}))
|
||||
def dfplayer_play_folder_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
template_ = yield cg.templatable(config[CONF_FOLDER], args, float)
|
||||
cg.add(var.set_folder(template_))
|
||||
if CONF_FILE in config:
|
||||
template_ = yield cg.templatable(config[CONF_FILE], args, float)
|
||||
cg.add(var.set_file(template_))
|
||||
if CONF_LOOP in config:
|
||||
template_ = yield cg.templatable(config[CONF_LOOP], args, float)
|
||||
cg.add(var.set_loop(template_))
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.set_device', SetDeviceAction, cv.maybe_simple_value({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
cv.Required(CONF_DEVICE): cv.enum(DEVICE, upper=True),
|
||||
}, key=CONF_DEVICE))
|
||||
def dfplayer_set_device_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
template_ = yield cg.templatable(config[CONF_DEVICE], args, Device)
|
||||
cg.add(var.set_device(template_))
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.set_volume', SetVolumeAction, cv.maybe_simple_value({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
cv.Required(CONF_VOLUME): cv.templatable(cv.int_),
|
||||
}, key=CONF_VOLUME))
|
||||
def dfplayer_set_volume_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
template_ = yield cg.templatable(config[CONF_VOLUME], args, float)
|
||||
cg.add(var.set_volume(template_))
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.set_eq', SetEqAction, cv.maybe_simple_value({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
cv.Required(CONF_EQ_PRESET): cv.templatable(cv.enum(EQ_PRESET, upper=True)),
|
||||
}, key=CONF_EQ_PRESET))
|
||||
def dfplayer_set_eq_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
template_ = yield cg.templatable(config[CONF_EQ_PRESET], args, EqPreset)
|
||||
cg.add(var.set_eq(template_))
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.sleep', SleepAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_sleep_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.reset', ResetAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_reset_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.start', StartAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_start_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.pause', PauseAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_pause_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.stop', StopAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_stop_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_action('dfplayer.random', RandomAction, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplayer_random_to_code(config, action_id, template_arg, args):
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
|
||||
|
||||
@automation.register_condition('dfplayer.is_playing', DFPlayerIsPlayingCondition, cv.Schema({
|
||||
cv.GenerateID(): cv.use_id(DFPlayer),
|
||||
}))
|
||||
def dfplyaer_is_playing_to_code(config, condition_id, template_arg, args):
|
||||
var = cg.new_Pvariable(condition_id, template_arg)
|
||||
yield cg.register_parented(var, config[CONF_ID])
|
||||
yield var
|
||||
130
esphome/components/dfplayer/dfplayer.cpp
Normal file
130
esphome/components/dfplayer/dfplayer.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
#include "dfplayer.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace dfplayer {
|
||||
|
||||
static const char* TAG = "dfplayer";
|
||||
|
||||
void DFPlayer::play_folder(uint16_t folder, uint16_t file) {
|
||||
if (folder < 100 && file < 256) {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x0F, (uint8_t) folder, (uint8_t) file);
|
||||
} else if (folder <= 10 && file <= 1000) {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x14, (((uint16_t) folder) << 12) | file);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Cannot play folder %d file %d.", folder, file);
|
||||
}
|
||||
}
|
||||
|
||||
void DFPlayer::send_cmd_(uint8_t cmd, uint16_t argument) {
|
||||
uint8_t buffer[10]{0x7e, 0xff, 0x06, cmd, 0x01, (uint8_t)(argument >> 8), (uint8_t) argument, 0x00, 0x00, 0xef};
|
||||
uint16_t checksum = 0;
|
||||
for (uint8_t i = 1; i < 7; i++)
|
||||
checksum += buffer[i];
|
||||
checksum = -checksum;
|
||||
buffer[7] = checksum >> 8;
|
||||
buffer[8] = (uint8_t) checksum;
|
||||
|
||||
this->sent_cmd_ = cmd;
|
||||
|
||||
ESP_LOGD(TAG, "Send Command %#02x arg %#04x", cmd, argument);
|
||||
this->write_array(buffer, 10);
|
||||
}
|
||||
|
||||
void DFPlayer::loop() {
|
||||
// Read message
|
||||
while (this->available()) {
|
||||
uint8_t byte;
|
||||
this->read_byte(&byte);
|
||||
|
||||
if (this->read_pos_ == DFPLAYER_READ_BUFFER_LENGTH)
|
||||
this->read_pos_ = 0;
|
||||
|
||||
switch (this->read_pos_) {
|
||||
case 0: // Start mark
|
||||
if (byte != 0x7E)
|
||||
continue;
|
||||
break;
|
||||
case 1: // Version
|
||||
if (byte != 0xFF) {
|
||||
ESP_LOGW(TAG, "Expected Version 0xFF, got %#02x", byte);
|
||||
this->read_pos_ = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 2: // Buffer length
|
||||
if (byte != 0x06) {
|
||||
ESP_LOGW(TAG, "Expected Buffer length 0x06, got %#02x", byte);
|
||||
this->read_pos_ = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 9: // End byte
|
||||
if (byte != 0xEF) {
|
||||
ESP_LOGW(TAG, "Expected end byte 0xEF, got %#02x", byte);
|
||||
this->read_pos_ = 0;
|
||||
continue;
|
||||
}
|
||||
// Parse valid received command
|
||||
uint8_t cmd = this->read_buffer_[3];
|
||||
uint16_t argument = (this->read_buffer_[5] << 8) | this->read_buffer_[6];
|
||||
|
||||
ESP_LOGV(TAG, "Received message cmd: %#02x arg %#04x", cmd, argument);
|
||||
|
||||
switch (cmd) {
|
||||
case 0x3A:
|
||||
if (argument == 1) {
|
||||
ESP_LOGI(TAG, "USB loaded");
|
||||
} else if (argument == 2)
|
||||
ESP_LOGI(TAG, "TF Card loaded");
|
||||
break;
|
||||
case 0x3B:
|
||||
if (argument == 1) {
|
||||
ESP_LOGI(TAG, "USB unloaded");
|
||||
} else if (argument == 2)
|
||||
ESP_LOGI(TAG, "TF Card unloaded");
|
||||
break;
|
||||
case 0x3F:
|
||||
if (argument == 1) {
|
||||
ESP_LOGI(TAG, "USB available");
|
||||
} else if (argument == 2) {
|
||||
ESP_LOGI(TAG, "TF Card available");
|
||||
} else if (argument == 3) {
|
||||
ESP_LOGI(TAG, "USB, TF Card available");
|
||||
}
|
||||
break;
|
||||
case 0x40:
|
||||
ESP_LOGV(TAG, "Nack");
|
||||
this->ack_set_is_playing_ = false;
|
||||
this->ack_reset_is_playing_ = false;
|
||||
case 0x41:
|
||||
ESP_LOGV(TAG, "Ack ok");
|
||||
this->is_playing_ |= this->ack_set_is_playing_;
|
||||
this->is_playing_ &= !this->ack_reset_is_playing_;
|
||||
this->ack_set_is_playing_ = false;
|
||||
this->ack_reset_is_playing_ = false;
|
||||
break;
|
||||
case 0x3D: // Playback finished
|
||||
this->is_playing_ = false;
|
||||
this->on_finished_playback_callback_.call();
|
||||
break;
|
||||
default:
|
||||
ESP_LOGD(TAG, "Command %#02x arg %#04x", cmd, argument);
|
||||
}
|
||||
this->sent_cmd_ = 0;
|
||||
this->read_pos_ = 0;
|
||||
continue;
|
||||
}
|
||||
this->read_buffer_[this->read_pos_] = byte;
|
||||
this->read_pos_++;
|
||||
}
|
||||
}
|
||||
void DFPlayer::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "DFPlayer:");
|
||||
this->check_uart_settings(9600);
|
||||
}
|
||||
|
||||
} // namespace dfplayer
|
||||
} // namespace esphome
|
||||
193
esphome/components/dfplayer/dfplayer.h
Normal file
193
esphome/components/dfplayer/dfplayer.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/core/automation.h"
|
||||
|
||||
const size_t DFPLAYER_READ_BUFFER_LENGTH = 25; // two messages + some extra
|
||||
|
||||
namespace esphome {
|
||||
namespace dfplayer {
|
||||
|
||||
enum EqPreset {
|
||||
NORMAL = 0,
|
||||
POP = 1,
|
||||
ROCK = 2,
|
||||
JAZZ = 3,
|
||||
CLASSIC = 4,
|
||||
BASS = 5,
|
||||
};
|
||||
|
||||
enum Device {
|
||||
USB = 1,
|
||||
TF_CARD = 2,
|
||||
};
|
||||
|
||||
class DFPlayer : public uart::UARTDevice, public Component {
|
||||
public:
|
||||
void loop() override;
|
||||
|
||||
void next() {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x01);
|
||||
}
|
||||
void previous() {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x02);
|
||||
}
|
||||
void play_file(uint16_t file) {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x03, file);
|
||||
}
|
||||
void play_file_loop(uint16_t file) {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x08, file);
|
||||
}
|
||||
void play_folder(uint16_t folder, uint16_t file);
|
||||
void play_folder_loop(uint16_t folder) {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x17, folder);
|
||||
}
|
||||
void volume_up() { this->send_cmd_(0x04); }
|
||||
void volume_down() { this->send_cmd_(0x05); }
|
||||
void set_device(Device device) { this->send_cmd_(0x09, device); }
|
||||
void set_volume(uint8_t volume) { this->send_cmd_(0x06, volume); }
|
||||
void set_eq(EqPreset preset) { this->send_cmd_(0x07, preset); }
|
||||
void sleep() {
|
||||
this->ack_reset_is_playing_ = true;
|
||||
this->send_cmd_(0x0A);
|
||||
}
|
||||
void reset() {
|
||||
this->ack_reset_is_playing_ = true;
|
||||
this->send_cmd_(0x0C);
|
||||
}
|
||||
void start() {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x0D);
|
||||
}
|
||||
void pause() {
|
||||
this->ack_reset_is_playing_ = true;
|
||||
this->send_cmd_(0x0E);
|
||||
}
|
||||
void stop() {
|
||||
this->ack_reset_is_playing_ = true;
|
||||
this->send_cmd_(0x16);
|
||||
}
|
||||
void random() {
|
||||
this->ack_set_is_playing_ = true;
|
||||
this->send_cmd_(0x18);
|
||||
}
|
||||
|
||||
bool is_playing() { return is_playing_; }
|
||||
void dump_config() override;
|
||||
|
||||
void add_on_finished_playback_callback(std::function<void()> callback) {
|
||||
this->on_finished_playback_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
protected:
|
||||
void send_cmd_(uint8_t cmd, uint16_t argument = 0);
|
||||
void send_cmd_(uint8_t cmd, uint16_t high, uint16_t low) {
|
||||
this->send_cmd_(cmd, ((high & 0xFF) << 8) | (low & 0xFF));
|
||||
}
|
||||
uint8_t sent_cmd_{0};
|
||||
|
||||
char read_buffer_[DFPLAYER_READ_BUFFER_LENGTH];
|
||||
size_t read_pos_{0};
|
||||
|
||||
bool is_playing_{false};
|
||||
bool ack_set_is_playing_{false};
|
||||
bool ack_reset_is_playing_{false};
|
||||
|
||||
CallbackManager<void()> on_finished_playback_callback_;
|
||||
};
|
||||
|
||||
#define DFPLAYER_SIMPLE_ACTION(ACTION_CLASS, ACTION_METHOD) \
|
||||
template<typename... Ts> class ACTION_CLASS : public Action<Ts...>, public Parented<DFPlayer> { \
|
||||
public: \
|
||||
void play(Ts... x) override { this->parent_->ACTION_METHOD(); } \
|
||||
};
|
||||
|
||||
DFPLAYER_SIMPLE_ACTION(NextAction, next)
|
||||
DFPLAYER_SIMPLE_ACTION(PreviousAction, previous)
|
||||
|
||||
template<typename... Ts> class PlayFileAction : public Action<Ts...>, public Parented<DFPlayer> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint16_t, file)
|
||||
TEMPLATABLE_VALUE(boolean, loop)
|
||||
void play(Ts... x) override {
|
||||
auto file = this->file_.value(x...);
|
||||
auto loop = this->loop_.value(x...);
|
||||
if (loop) {
|
||||
this->parent_->play_file_loop(file);
|
||||
} else {
|
||||
this->parent_->play_file(file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class PlayFolderAction : public Action<Ts...>, public Parented<DFPlayer> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint16_t, folder)
|
||||
TEMPLATABLE_VALUE(uint16_t, file)
|
||||
TEMPLATABLE_VALUE(boolean, loop)
|
||||
void play(Ts... x) override {
|
||||
auto folder = this->folder_.value(x...);
|
||||
auto file = this->file_.value(x...);
|
||||
auto loop = this->loop_.value(x...);
|
||||
if (loop) {
|
||||
this->parent_->play_folder_loop(folder);
|
||||
} else {
|
||||
this->parent_->play_folder(folder, file);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetDeviceAction : public Action<Ts...>, public Parented<DFPlayer> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(Device, device)
|
||||
void play(Ts... x) override {
|
||||
auto device = this->device_.value(x...);
|
||||
this->parent_->set_device(device);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetVolumeAction : public Action<Ts...>, public Parented<DFPlayer> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(uint8_t, volume)
|
||||
void play(Ts... x) override {
|
||||
auto volume = this->volume_.value(x...);
|
||||
this->parent_->set_volume(volume);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class SetEqAction : public Action<Ts...>, public Parented<DFPlayer> {
|
||||
public:
|
||||
TEMPLATABLE_VALUE(EqPreset, eq)
|
||||
void play(Ts... x) override {
|
||||
auto eq = this->eq_.value(x...);
|
||||
this->parent_->set_eq(eq);
|
||||
}
|
||||
};
|
||||
|
||||
DFPLAYER_SIMPLE_ACTION(SleepAction, sleep)
|
||||
DFPLAYER_SIMPLE_ACTION(ResetAction, reset)
|
||||
DFPLAYER_SIMPLE_ACTION(StartAction, start)
|
||||
DFPLAYER_SIMPLE_ACTION(PauseAction, pause)
|
||||
DFPLAYER_SIMPLE_ACTION(StopAction, stop)
|
||||
DFPLAYER_SIMPLE_ACTION(RandomAction, random)
|
||||
|
||||
template<typename... Ts> class DFPlayerIsPlayingCondition : public Condition<Ts...>, public Parented<DFPlayer> {
|
||||
public:
|
||||
bool check(Ts... x) override { return this->parent_->is_playing(); }
|
||||
};
|
||||
|
||||
class DFPlayerFinishedPlaybackTrigger : public Trigger<> {
|
||||
public:
|
||||
explicit DFPlayerFinishedPlaybackTrigger(DFPlayer *parent) {
|
||||
parent->add_on_finished_playback_callback([this]() { this->trigger(); });
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace dfplayer
|
||||
} // namespace esphome
|
||||
@@ -47,8 +47,10 @@ void DHT::update() {
|
||||
if (error) {
|
||||
ESP_LOGD(TAG, "Got Temperature=%.1f°C Humidity=%.1f%%", temperature, humidity);
|
||||
|
||||
this->temperature_sensor_->publish_state(temperature);
|
||||
this->humidity_sensor_->publish_state(humidity);
|
||||
if (this->temperature_sensor_ != nullptr)
|
||||
this->temperature_sensor_->publish_state(temperature);
|
||||
if (this->humidity_sensor_ != nullptr)
|
||||
this->humidity_sensor_->publish_state(humidity);
|
||||
this->status_clear_warning();
|
||||
} else {
|
||||
const char *str = "";
|
||||
@@ -56,8 +58,10 @@ void DHT::update() {
|
||||
str = " and consider manually specifying the DHT model using the model option";
|
||||
}
|
||||
ESP_LOGW(TAG, "Invalid readings! Please check your wiring (pull-up resistor, pin number)%s.", str);
|
||||
this->temperature_sensor_->publish_state(NAN);
|
||||
this->humidity_sensor_->publish_state(NAN);
|
||||
if (this->temperature_sensor_ != nullptr)
|
||||
this->temperature_sensor_->publish_state(NAN);
|
||||
if (this->humidity_sensor_ != nullptr)
|
||||
this->humidity_sensor_->publish_state(NAN);
|
||||
this->status_set_warning();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ using display_writer_t = std::function<void(DisplayBuffer &)>;
|
||||
#define LOG_DISPLAY(prefix, type, obj) \
|
||||
if (obj != nullptr) { \
|
||||
ESP_LOGCONFIG(TAG, prefix type); \
|
||||
ESP_LOGCONFIG(TAG, prefix " Rotations: %d °", obj->rotation_); \
|
||||
ESP_LOGCONFIG(TAG, prefix " Dimensions: %dpx x %dpx", obj->get_width(), obj->get_height()); \
|
||||
ESP_LOGCONFIG(TAG, "%s Rotations: %d °", prefix, obj->rotation_); \
|
||||
ESP_LOGCONFIG(TAG, "%s Dimensions: %dpx x %dpx", prefix, obj->get_width(), obj->get_height()); \
|
||||
}
|
||||
|
||||
class DisplayBuffer {
|
||||
|
||||
@@ -31,6 +31,11 @@ static esp_ble_adv_params_t ble_adv_params = {
|
||||
static esp_ble_ibeacon_head_t ibeacon_common_head = {
|
||||
.flags = {0x02, 0x01, 0x06}, .length = 0x1A, .type = 0xFF, .company_id = 0x004C, .beacon_type = 0x1502};
|
||||
|
||||
void ESP32BLEBeacon::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "ESP32 BLE Beacon:");
|
||||
ESP_LOGCONFIG(TAG, " Major: %u, Minor: %u", this->major_, this->minor_);
|
||||
}
|
||||
|
||||
void ESP32BLEBeacon::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up ESP32 BLE beacon...");
|
||||
global_esp32_ble_beacon = this;
|
||||
@@ -50,7 +55,7 @@ void ESP32BLEBeacon::ble_core_task(void *params) {
|
||||
ble_setup();
|
||||
|
||||
while (true) {
|
||||
delay(1000);
|
||||
delay(1000); // NOLINT
|
||||
}
|
||||
}
|
||||
void ESP32BLEBeacon::ble_setup() {
|
||||
|
||||
@@ -34,6 +34,7 @@ class ESP32BLEBeacon : public Component {
|
||||
explicit ESP32BLEBeacon(const std::array<uint8_t, 16> &uuid) : uuid_(uuid) {}
|
||||
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
|
||||
void set_major(uint16_t major) { this->major_ = major; }
|
||||
|
||||
@@ -37,7 +37,7 @@ CONFIG_SCHEMA = cv.Schema({
|
||||
cv.Optional(CONF_SCAN_PARAMETERS, default={}): cv.All(cv.Schema({
|
||||
cv.Optional(CONF_DURATION, default='5min'): cv.positive_time_period_seconds,
|
||||
cv.Optional(CONF_INTERVAL, default='320ms'): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_WINDOW, default='200ms'): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_WINDOW, default='30ms'): cv.positive_time_period_milliseconds,
|
||||
cv.Optional(CONF_ACTIVE, default=True): cv.boolean,
|
||||
}), validate_scan_parameters),
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "esp32_ble_tracker.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
@@ -133,7 +134,7 @@ bool ESP32BLETracker::ble_setup() {
|
||||
}
|
||||
|
||||
// BLE takes some time to be fully set up, 200ms should be more than enough
|
||||
delay(200);
|
||||
delay(200); // NOLINT
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -202,20 +203,8 @@ void ESP32BLETracker::gap_scan_result(const esp_ble_gap_cb_param_t::ble_scan_res
|
||||
}
|
||||
}
|
||||
|
||||
std::string hexencode(const std::string &raw_data) {
|
||||
char buf[20];
|
||||
std::string res;
|
||||
for (size_t i = 0; i < raw_data.size(); i++) {
|
||||
if (i + 1 != raw_data.size()) {
|
||||
sprintf(buf, "0x%02X.", static_cast<uint8_t>(raw_data[i]));
|
||||
} else {
|
||||
sprintf(buf, "0x%02X ", static_cast<uint8_t>(raw_data[i]));
|
||||
}
|
||||
res += buf;
|
||||
}
|
||||
sprintf(buf, "(%zu)", raw_data.size());
|
||||
res += buf;
|
||||
return res;
|
||||
std::string hexencode_string(const std::string &raw_data) {
|
||||
return hexencode(reinterpret_cast<const uint8_t *>(raw_data.c_str()), raw_data.size());
|
||||
}
|
||||
|
||||
ESPBTUUID::ESPBTUUID() : uuid_() {}
|
||||
@@ -327,15 +316,15 @@ void ESPBTDevice::parse_scan_rst(const esp_ble_gap_cb_param_t::ble_scan_result_e
|
||||
for (auto uuid : this->service_uuids_) {
|
||||
ESP_LOGVV(TAG, " Service UUID: %s", uuid.to_string().c_str());
|
||||
}
|
||||
ESP_LOGVV(TAG, " Manufacturer data: %s", hexencode(this->manufacturer_data_).c_str());
|
||||
ESP_LOGVV(TAG, " Service data: %s", hexencode(this->service_data_).c_str());
|
||||
ESP_LOGVV(TAG, " Manufacturer data: %s", hexencode_string(this->manufacturer_data_).c_str());
|
||||
ESP_LOGVV(TAG, " Service data: %s", hexencode_string(this->service_data_).c_str());
|
||||
|
||||
if (this->service_data_uuid_.has_value()) {
|
||||
ESP_LOGVV(TAG, " Service Data UUID: %s", this->service_data_uuid_->to_string().c_str());
|
||||
}
|
||||
|
||||
ESP_LOGVV(TAG, "Adv data: %s",
|
||||
hexencode(std::string(reinterpret_cast<const char *>(param.ble_adv), param.adv_data_len)).c_str());
|
||||
hexencode_string(std::string(reinterpret_cast<const char *>(param.ble_adv), param.adv_data_len)).c_str());
|
||||
#endif
|
||||
}
|
||||
void ESPBTDevice::parse_adv_(const esp_ble_gap_cb_param_t::ble_scan_result_evt_param ¶m) {
|
||||
@@ -452,8 +441,8 @@ const optional<ESPBTUUID> &ESPBTDevice::get_service_data_uuid() const { return t
|
||||
void ESP32BLETracker::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "BLE Tracker:");
|
||||
ESP_LOGCONFIG(TAG, " Scan Duration: %u s", this->scan_duration_);
|
||||
ESP_LOGCONFIG(TAG, " Scan Interval: %u ms", this->scan_interval_);
|
||||
ESP_LOGCONFIG(TAG, " Scan Window: %u ms", this->scan_window_);
|
||||
ESP_LOGCONFIG(TAG, " Scan Interval: %.1f ms", this->scan_interval_ * 0.625f);
|
||||
ESP_LOGCONFIG(TAG, " Scan Window: %.1f ms", this->scan_window_ * 0.625f);
|
||||
ESP_LOGCONFIG(TAG, " Scan Type: %s", this->scan_active_ ? "ACTIVE" : "PASSIVE");
|
||||
}
|
||||
void ESP32BLETracker::print_bt_device_info(const ESPBTDevice &device) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.const import CONF_FREQUENCY, CONF_ID, CONF_NAME, CONF_PIN, CONF_SCL, CONF_SDA, \
|
||||
ESP_PLATFORM_ESP32
|
||||
ESP_PLATFORM_ESP32, CONF_DATA_PINS, CONF_RESET_PIN, CONF_RESOLUTION, CONF_BRIGHTNESS
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
DEPENDENCIES = ['api']
|
||||
@@ -35,23 +35,19 @@ FRAME_SIZES = {
|
||||
'UXGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200,
|
||||
}
|
||||
|
||||
CONF_DATA_PINS = 'data_pins'
|
||||
CONF_VSYNC_PIN = 'vsync_pin'
|
||||
CONF_HREF_PIN = 'href_pin'
|
||||
CONF_PIXEL_CLOCK_PIN = 'pixel_clock_pin'
|
||||
CONF_EXTERNAL_CLOCK = 'external_clock'
|
||||
CONF_I2C_PINS = 'i2c_pins'
|
||||
CONF_RESET_PIN = 'reset_pin'
|
||||
CONF_POWER_DOWN_PIN = 'power_down_pin'
|
||||
|
||||
CONF_MAX_FRAMERATE = 'max_framerate'
|
||||
CONF_IDLE_FRAMERATE = 'idle_framerate'
|
||||
CONF_RESOLUTION = 'resolution'
|
||||
CONF_JPEG_QUALITY = 'jpeg_quality'
|
||||
CONF_VERTICAL_FLIP = 'vertical_flip'
|
||||
CONF_HORIZONTAL_MIRROR = 'horizontal_mirror'
|
||||
CONF_CONTRAST = 'contrast'
|
||||
CONF_BRIGHTNESS = 'brightness'
|
||||
CONF_SATURATION = 'saturation'
|
||||
CONF_TEST_PATTERN = 'test_pattern'
|
||||
|
||||
|
||||
@@ -108,6 +108,8 @@ void ESP32TouchComponent::dump_config() {
|
||||
}
|
||||
|
||||
void ESP32TouchComponent::loop() {
|
||||
const uint32_t now = millis();
|
||||
bool should_print = this->setup_mode_ && now - this->setup_mode_last_log_print_ > 250;
|
||||
for (auto *child : this->children_) {
|
||||
uint16_t value;
|
||||
if (this->iir_filter_enabled_()) {
|
||||
@@ -119,14 +121,14 @@ void ESP32TouchComponent::loop() {
|
||||
child->value_ = value;
|
||||
child->publish_state(value < child->get_threshold());
|
||||
|
||||
if (this->setup_mode_) {
|
||||
if (should_print) {
|
||||
ESP_LOGD(TAG, "Touch Pad '%s' (T%u): %u", child->get_name().c_str(), child->get_touch_pad(), value);
|
||||
}
|
||||
}
|
||||
|
||||
if (this->setup_mode_) {
|
||||
if (should_print) {
|
||||
// Avoid spamming logs
|
||||
delay(250);
|
||||
this->setup_mode_last_log_print_ = now;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ class ESP32TouchComponent : public Component {
|
||||
touch_volt_atten_t voltage_attenuation_{};
|
||||
std::vector<ESP32TouchBinarySensor *> children_;
|
||||
bool setup_mode_{false};
|
||||
uint32_t setup_mode_last_log_print_{};
|
||||
uint32_t iir_filter_{0};
|
||||
};
|
||||
|
||||
|
||||
0
esphome/components/fujitsu_general/__init__.py
Normal file
0
esphome/components/fujitsu_general/__init__.py
Normal file
18
esphome/components/fujitsu_general/climate.py
Normal file
18
esphome/components/fujitsu_general/climate.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate_ir
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
AUTO_LOAD = ['climate_ir']
|
||||
|
||||
fujitsu_general_ns = cg.esphome_ns.namespace('fujitsu_general')
|
||||
FujitsuGeneralClimate = fujitsu_general_ns.class_('FujitsuGeneralClimate', climate_ir.ClimateIR)
|
||||
|
||||
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(FujitsuGeneralClimate),
|
||||
})
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield climate_ir.register_climate_ir(var, config)
|
||||
212
esphome/components/fujitsu_general/fujitsu_general.cpp
Normal file
212
esphome/components/fujitsu_general/fujitsu_general.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
#include "fujitsu_general.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace fujitsu_general {
|
||||
|
||||
static const char *TAG = "fujitsu_general.climate";
|
||||
|
||||
// Control packet
|
||||
const uint16_t FUJITSU_GENERAL_STATE_LENGTH = 16;
|
||||
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE0 = 0x14;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE1 = 0x63;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE2 = 0x00;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE3 = 0x10;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE4 = 0x10;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE5 = 0xFE;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE6 = 0x09;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE7 = 0x30;
|
||||
|
||||
// Temperature and POWER ON
|
||||
const uint8_t FUJITSU_GENERAL_POWER_ON_MASK_BYTE8 = 0b00000001;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE8 = 0x40;
|
||||
|
||||
// Mode
|
||||
const uint8_t FUJITSU_GENERAL_MODE_AUTO_BYTE9 = 0x00;
|
||||
const uint8_t FUJITSU_GENERAL_MODE_HEAT_BYTE9 = 0x04;
|
||||
const uint8_t FUJITSU_GENERAL_MODE_COOL_BYTE9 = 0x01;
|
||||
const uint8_t FUJITSU_GENERAL_MODE_DRY_BYTE9 = 0x02;
|
||||
const uint8_t FUJITSU_GENERAL_MODE_FAN_BYTE9 = 0x03;
|
||||
const uint8_t FUJITSU_GENERAL_MODE_10C_BYTE9 = 0x0B;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE9 = 0x01;
|
||||
|
||||
// Fan speed and swing
|
||||
const uint8_t FUJITSU_GENERAL_FAN_AUTO_BYTE10 = 0x00;
|
||||
const uint8_t FUJITSU_GENERAL_FAN_HIGH_BYTE10 = 0x01;
|
||||
const uint8_t FUJITSU_GENERAL_FAN_MEDIUM_BYTE10 = 0x02;
|
||||
const uint8_t FUJITSU_GENERAL_FAN_LOW_BYTE10 = 0x03;
|
||||
const uint8_t FUJITSU_GENERAL_FAN_SILENT_BYTE10 = 0x04;
|
||||
const uint8_t FUJITSU_GENERAL_SWING_MASK_BYTE10 = 0b00010000;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE10 = 0x00;
|
||||
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE11 = 0x00;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE12 = 0x00;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE13 = 0x00;
|
||||
|
||||
// Outdoor Unit Low Noise
|
||||
const uint8_t FUJITSU_GENERAL_OUTDOOR_UNIT_LOW_NOISE_BYTE14 = 0xA0;
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE14 = 0x20;
|
||||
|
||||
// CRC
|
||||
const uint8_t FUJITSU_GENERAL_BASE_BYTE15 = 0x6F;
|
||||
|
||||
// Power off packet is specific
|
||||
const uint16_t FUJITSU_GENERAL_OFF_LENGTH = 7;
|
||||
|
||||
const uint8_t FUJITSU_GENERAL_OFF_BYTE0 = FUJITSU_GENERAL_BASE_BYTE0;
|
||||
const uint8_t FUJITSU_GENERAL_OFF_BYTE1 = FUJITSU_GENERAL_BASE_BYTE1;
|
||||
const uint8_t FUJITSU_GENERAL_OFF_BYTE2 = FUJITSU_GENERAL_BASE_BYTE2;
|
||||
const uint8_t FUJITSU_GENERAL_OFF_BYTE3 = FUJITSU_GENERAL_BASE_BYTE3;
|
||||
const uint8_t FUJITSU_GENERAL_OFF_BYTE4 = FUJITSU_GENERAL_BASE_BYTE4;
|
||||
const uint8_t FUJITSU_GENERAL_OFF_BYTE5 = 0x02;
|
||||
const uint8_t FUJITSU_GENERAL_OFF_BYTE6 = 0xFD;
|
||||
|
||||
const uint8_t FUJITSU_GENERAL_TEMP_MAX = 30; // Celsius
|
||||
const uint8_t FUJITSU_GENERAL_TEMP_MIN = 16; // Celsius
|
||||
|
||||
const uint16_t FUJITSU_GENERAL_HEADER_MARK = 3300;
|
||||
const uint16_t FUJITSU_GENERAL_HEADER_SPACE = 1600;
|
||||
const uint16_t FUJITSU_GENERAL_BIT_MARK = 420;
|
||||
const uint16_t FUJITSU_GENERAL_ONE_SPACE = 1200;
|
||||
const uint16_t FUJITSU_GENERAL_ZERO_SPACE = 420;
|
||||
const uint16_t FUJITSU_GENERAL_TRL_MARK = 420;
|
||||
const uint16_t FUJITSU_GENERAL_TRL_SPACE = 8000;
|
||||
|
||||
const uint32_t FUJITSU_GENERAL_CARRIER_FREQUENCY = 38000;
|
||||
|
||||
FujitsuGeneralClimate::FujitsuGeneralClimate() : ClimateIR(FUJITSU_GENERAL_TEMP_MIN, FUJITSU_GENERAL_TEMP_MAX, 1) {}
|
||||
|
||||
void FujitsuGeneralClimate::transmit_state() {
|
||||
if (this->mode == climate::CLIMATE_MODE_OFF) {
|
||||
this->transmit_off_();
|
||||
return;
|
||||
}
|
||||
uint8_t remote_state[FUJITSU_GENERAL_STATE_LENGTH] = {0};
|
||||
|
||||
remote_state[0] = FUJITSU_GENERAL_BASE_BYTE0;
|
||||
remote_state[1] = FUJITSU_GENERAL_BASE_BYTE1;
|
||||
remote_state[2] = FUJITSU_GENERAL_BASE_BYTE2;
|
||||
remote_state[3] = FUJITSU_GENERAL_BASE_BYTE3;
|
||||
remote_state[4] = FUJITSU_GENERAL_BASE_BYTE4;
|
||||
remote_state[5] = FUJITSU_GENERAL_BASE_BYTE5;
|
||||
remote_state[6] = FUJITSU_GENERAL_BASE_BYTE6;
|
||||
remote_state[7] = FUJITSU_GENERAL_BASE_BYTE7;
|
||||
remote_state[8] = FUJITSU_GENERAL_BASE_BYTE8;
|
||||
remote_state[9] = FUJITSU_GENERAL_BASE_BYTE9;
|
||||
remote_state[10] = FUJITSU_GENERAL_BASE_BYTE10;
|
||||
remote_state[11] = FUJITSU_GENERAL_BASE_BYTE11;
|
||||
remote_state[12] = FUJITSU_GENERAL_BASE_BYTE12;
|
||||
remote_state[13] = FUJITSU_GENERAL_BASE_BYTE13;
|
||||
remote_state[14] = FUJITSU_GENERAL_BASE_BYTE14;
|
||||
remote_state[15] = FUJITSU_GENERAL_BASE_BYTE15;
|
||||
|
||||
// Set temperature
|
||||
uint8_t safecelsius = std::max((uint8_t) this->target_temperature, FUJITSU_GENERAL_TEMP_MIN);
|
||||
safecelsius = std::min(safecelsius, FUJITSU_GENERAL_TEMP_MAX);
|
||||
remote_state[8] = (byte) safecelsius - 16;
|
||||
remote_state[8] = remote_state[8] << 4;
|
||||
|
||||
// If not powered - set power on flag
|
||||
if (!this->power_) {
|
||||
remote_state[8] = (byte) remote_state[8] | FUJITSU_GENERAL_POWER_ON_MASK_BYTE8;
|
||||
}
|
||||
|
||||
// Set mode
|
||||
switch (this->mode) {
|
||||
case climate::CLIMATE_MODE_COOL:
|
||||
remote_state[9] = FUJITSU_GENERAL_MODE_COOL_BYTE9;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_HEAT:
|
||||
remote_state[9] = FUJITSU_GENERAL_MODE_HEAT_BYTE9;
|
||||
break;
|
||||
case climate::CLIMATE_MODE_AUTO:
|
||||
default:
|
||||
remote_state[9] = FUJITSU_GENERAL_MODE_AUTO_BYTE9;
|
||||
break;
|
||||
// TODO: CLIMATE_MODE_FAN_ONLY, CLIMATE_MODE_DRY, CLIMATE_MODE_10C are missing in esphome
|
||||
}
|
||||
|
||||
// TODO: missing support for fan speed
|
||||
remote_state[10] = FUJITSU_GENERAL_FAN_AUTO_BYTE10;
|
||||
|
||||
// TODO: missing support for swing
|
||||
// remote_state[10] = (byte) remote_state[10] | FUJITSU_GENERAL_SWING_MASK_BYTE10;
|
||||
|
||||
// TODO: missing support for outdoor unit low noise
|
||||
// remote_state[14] = (byte) remote_state[14] | FUJITSU_GENERAL_OUTDOOR_UNIT_LOW_NOISE_BYTE14;
|
||||
|
||||
// CRC
|
||||
remote_state[15] = 0;
|
||||
for (int i = 7; i < 15; i++) {
|
||||
remote_state[15] += (byte) remote_state[i]; // Addiction
|
||||
}
|
||||
remote_state[15] = 0x100 - remote_state[15]; // mod 256
|
||||
|
||||
auto transmit = this->transmitter_->transmit();
|
||||
auto data = transmit.get_data();
|
||||
|
||||
data->set_carrier_frequency(FUJITSU_GENERAL_CARRIER_FREQUENCY);
|
||||
|
||||
// Header
|
||||
data->mark(FUJITSU_GENERAL_HEADER_MARK);
|
||||
data->space(FUJITSU_GENERAL_HEADER_SPACE);
|
||||
// Data
|
||||
for (uint8_t i : remote_state) {
|
||||
// Send all Bits from Byte Data in Reverse Order
|
||||
for (uint8_t mask = 00000001; mask > 0; mask <<= 1) { // iterate through bit mask
|
||||
data->mark(FUJITSU_GENERAL_BIT_MARK);
|
||||
bool bit = i & mask;
|
||||
data->space(bit ? FUJITSU_GENERAL_ONE_SPACE : FUJITSU_GENERAL_ZERO_SPACE);
|
||||
// Next bits
|
||||
}
|
||||
}
|
||||
// Footer
|
||||
data->mark(FUJITSU_GENERAL_TRL_MARK);
|
||||
data->space(FUJITSU_GENERAL_TRL_SPACE);
|
||||
|
||||
transmit.perform();
|
||||
|
||||
this->power_ = true;
|
||||
}
|
||||
|
||||
void FujitsuGeneralClimate::transmit_off_() {
|
||||
uint8_t remote_state[FUJITSU_GENERAL_OFF_LENGTH] = {0};
|
||||
|
||||
remote_state[0] = FUJITSU_GENERAL_OFF_BYTE0;
|
||||
remote_state[1] = FUJITSU_GENERAL_OFF_BYTE1;
|
||||
remote_state[2] = FUJITSU_GENERAL_OFF_BYTE2;
|
||||
remote_state[3] = FUJITSU_GENERAL_OFF_BYTE3;
|
||||
remote_state[4] = FUJITSU_GENERAL_OFF_BYTE4;
|
||||
remote_state[5] = FUJITSU_GENERAL_OFF_BYTE5;
|
||||
remote_state[6] = FUJITSU_GENERAL_OFF_BYTE6;
|
||||
|
||||
auto transmit = this->transmitter_->transmit();
|
||||
auto data = transmit.get_data();
|
||||
|
||||
data->set_carrier_frequency(FUJITSU_GENERAL_CARRIER_FREQUENCY);
|
||||
|
||||
// Header
|
||||
data->mark(FUJITSU_GENERAL_HEADER_MARK);
|
||||
data->space(FUJITSU_GENERAL_HEADER_SPACE);
|
||||
|
||||
// Data
|
||||
for (uint8_t i : remote_state) {
|
||||
// Send all Bits from Byte Data in Reverse Order
|
||||
for (uint8_t mask = 00000001; mask > 0; mask <<= 1) { // iterate through bit mask
|
||||
data->mark(FUJITSU_GENERAL_BIT_MARK);
|
||||
bool bit = i & mask;
|
||||
data->space(bit ? FUJITSU_GENERAL_ONE_SPACE : FUJITSU_GENERAL_ZERO_SPACE);
|
||||
// Next bits
|
||||
}
|
||||
}
|
||||
// Footer
|
||||
data->mark(FUJITSU_GENERAL_TRL_MARK);
|
||||
data->space(FUJITSU_GENERAL_TRL_SPACE);
|
||||
|
||||
transmit.perform();
|
||||
|
||||
this->power_ = false;
|
||||
}
|
||||
|
||||
} // namespace fujitsu_general
|
||||
} // namespace esphome
|
||||
24
esphome/components/fujitsu_general/fujitsu_general.h
Normal file
24
esphome/components/fujitsu_general/fujitsu_general.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/climate_ir/climate_ir.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace fujitsu_general {
|
||||
|
||||
class FujitsuGeneralClimate : public climate_ir::ClimateIR {
|
||||
public:
|
||||
FujitsuGeneralClimate();
|
||||
|
||||
protected:
|
||||
/// Transmit via IR the state of this climate controller.
|
||||
void transmit_state() override;
|
||||
/// Transmit via IR power off command.
|
||||
void transmit_off_();
|
||||
|
||||
bool power_{false};
|
||||
};
|
||||
|
||||
} // namespace fujitsu_general
|
||||
} // namespace esphome
|
||||
@@ -15,12 +15,14 @@ RESTORE_MODES = {
|
||||
'ALWAYS_ON': GPIOSwitchRestoreMode.GPIO_SWITCH_ALWAYS_ON,
|
||||
}
|
||||
|
||||
CONF_INTERLOCK_WAIT_TIME = 'interlock_wait_time'
|
||||
CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({
|
||||
cv.GenerateID(): cv.declare_id(GPIOSwitch),
|
||||
cv.Required(CONF_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_RESTORE_MODE, default='RESTORE_DEFAULT_OFF'):
|
||||
cv.enum(RESTORE_MODES, upper=True, space='_'),
|
||||
cv.Optional(CONF_INTERLOCK): cv.ensure_list(cv.use_id(switch.Switch)),
|
||||
cv.Optional(CONF_INTERLOCK_WAIT_TIME, default='0ms'): cv.positive_time_period_milliseconds,
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
@@ -40,3 +42,4 @@ def to_code(config):
|
||||
lock = yield cg.get_variable(it)
|
||||
interlock.append(lock)
|
||||
cg.add(var.set_interlock(interlock))
|
||||
cg.add(var.set_interlock_wait_time(config[CONF_INTERLOCK_WAIT_TIME]))
|
||||
|
||||
@@ -69,13 +69,29 @@ void GPIOSwitch::dump_config() {
|
||||
void GPIOSwitch::write_state(bool state) {
|
||||
if (state != this->inverted_) {
|
||||
// Turning ON, check interlocking
|
||||
|
||||
bool found = false;
|
||||
for (auto *lock : this->interlock_) {
|
||||
if (lock == this)
|
||||
continue;
|
||||
|
||||
if (lock->state)
|
||||
if (lock->state) {
|
||||
lock->turn_off();
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found && this->interlock_wait_time_ != 0) {
|
||||
this->set_timeout("interlock", this->interlock_wait_time_, [this, state] {
|
||||
// Don't write directly, call the function again
|
||||
// (some other switch may have changed state while we were waiting)
|
||||
this->write_state(state);
|
||||
});
|
||||
return;
|
||||
}
|
||||
} else if (this->interlock_wait_time_ != 0) {
|
||||
// If we are switched off during the interlock wait time, cancel any pending
|
||||
// re-activations
|
||||
this->cancel_timeout("interlock");
|
||||
}
|
||||
|
||||
this->pin_->digital_write(state);
|
||||
|
||||
@@ -26,6 +26,7 @@ class GPIOSwitch : public switch_::Switch, public Component {
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
void set_interlock(const std::vector<Switch *> &interlock);
|
||||
void set_interlock_wait_time(uint32_t interlock_wait_time) { interlock_wait_time_ = interlock_wait_time; }
|
||||
|
||||
protected:
|
||||
void write_state(bool state) override;
|
||||
@@ -33,6 +34,7 @@ class GPIOSwitch : public switch_::Switch, public Component {
|
||||
GPIOPin *pin_;
|
||||
GPIOSwitchRestoreMode restore_mode_{GPIO_SWITCH_RESTORE_DEFAULT_OFF};
|
||||
std::vector<Switch *> interlock_;
|
||||
uint32_t interlock_wait_time_{0};
|
||||
};
|
||||
|
||||
} // namespace gpio
|
||||
|
||||
@@ -208,5 +208,30 @@ void I2CDevice::set_i2c_parent(I2CComponent *parent) { this->parent_ = parent; }
|
||||
uint8_t next_i2c_bus_num_ = 0;
|
||||
#endif
|
||||
|
||||
I2CRegister &I2CRegister::operator=(uint8_t value) {
|
||||
this->parent_->write_byte(this->register_, value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
I2CRegister &I2CRegister::operator&=(uint8_t value) {
|
||||
this->parent_->write_byte(this->register_, this->get() & value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
I2CRegister &I2CRegister::operator|=(uint8_t value) {
|
||||
this->parent_->write_byte(this->register_, this->get() | value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint8_t I2CRegister::get() {
|
||||
uint8_t value = 0x00;
|
||||
this->parent_->read_byte(this->register_, &value);
|
||||
return value;
|
||||
}
|
||||
I2CRegister &I2CRegister::operator=(const std::vector<uint8_t> &value) {
|
||||
this->parent_->write_bytes(this->register_, value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace i2c
|
||||
} // namespace esphome
|
||||
|
||||
@@ -134,6 +134,24 @@ class I2CComponent : public Component {
|
||||
extern uint8_t next_i2c_bus_num_;
|
||||
#endif
|
||||
|
||||
class I2CDevice;
|
||||
|
||||
class I2CRegister {
|
||||
public:
|
||||
I2CRegister(I2CDevice *parent, uint8_t a_register) : parent_(parent), register_(a_register) {}
|
||||
|
||||
I2CRegister &operator=(uint8_t value);
|
||||
I2CRegister &operator=(const std::vector<uint8_t> &value);
|
||||
I2CRegister &operator&=(uint8_t value);
|
||||
I2CRegister &operator|=(uint8_t value);
|
||||
|
||||
uint8_t get();
|
||||
|
||||
protected:
|
||||
I2CDevice *parent_;
|
||||
uint8_t register_;
|
||||
};
|
||||
|
||||
/** All components doing communication on the I2C bus should subclass I2CDevice.
|
||||
*
|
||||
* This class stores 1. the address of the i2c device and has a helper function to allow
|
||||
@@ -153,6 +171,8 @@ class I2CDevice {
|
||||
/// Manually set the parent i2c bus for this device.
|
||||
void set_i2c_parent(I2CComponent *parent);
|
||||
|
||||
I2CRegister reg(uint8_t a_register) { return {this, a_register}; }
|
||||
|
||||
/** Read len amount of bytes from a register into data. Optionally with a conversion time after
|
||||
* writing the register value to the bus.
|
||||
*
|
||||
|
||||
@@ -148,6 +148,11 @@ void LCDDisplay::printf(const char *format, ...) {
|
||||
if (ret > 0)
|
||||
this->print(0, 0, buffer);
|
||||
}
|
||||
void LCDDisplay::clear() {
|
||||
// clear display, also sets DDRAM address to 0 (home)
|
||||
this->command_(LCD_DISPLAY_COMMAND_CLEAR_DISPLAY);
|
||||
delay(2);
|
||||
}
|
||||
#ifdef USE_TIME
|
||||
void LCDDisplay::strftime(uint8_t column, uint8_t row, const char *format, time::ESPTime time) {
|
||||
char buffer[64];
|
||||
|
||||
@@ -23,6 +23,8 @@ class LCDDisplay : public PollingComponent {
|
||||
float get_setup_priority() const override;
|
||||
void update() override;
|
||||
void display();
|
||||
//// Clear LCD display
|
||||
void clear();
|
||||
|
||||
/// Print the given text at the specified column and row.
|
||||
void print(uint8_t column, uint8_t row, const char *str);
|
||||
|
||||
@@ -42,8 +42,8 @@ float ledc_min_frequency_for_bit_depth(uint8_t bit_depth) {
|
||||
}
|
||||
optional<uint8_t> ledc_bit_depth_for_frequency(float frequency) {
|
||||
for (int i = 20; i >= 1; i--) {
|
||||
const float min_frequency = ledc_min_frequency_for_bit_depth(frequency);
|
||||
const float max_frequency = ledc_max_frequency_for_bit_depth(frequency);
|
||||
const float min_frequency = ledc_min_frequency_for_bit_depth(i);
|
||||
const float max_frequency = ledc_max_frequency_for_bit_depth(i);
|
||||
if (min_frequency <= frequency && frequency <= max_frequency)
|
||||
return i;
|
||||
}
|
||||
@@ -56,7 +56,7 @@ void LEDCOutput::apply_frequency(float frequency) {
|
||||
ESP_LOGW(TAG, "Frequency %f can't be achieved with any bit depth", frequency);
|
||||
this->status_set_warning();
|
||||
}
|
||||
this->bit_depth_ = *bit_depth_opt;
|
||||
this->bit_depth_ = bit_depth_opt.value_or(8);
|
||||
this->frequency_ = frequency;
|
||||
ledcSetup(this->channel_, frequency, this->bit_depth_);
|
||||
// re-apply duty
|
||||
|
||||
@@ -30,6 +30,8 @@ class Logger : public Component {
|
||||
|
||||
/// Manually set the baud rate for serial, set to 0 to disable.
|
||||
void set_baud_rate(uint32_t baud_rate);
|
||||
uint32_t get_baud_rate() const { return baud_rate_; }
|
||||
HardwareSerial *get_hw_serial() const { return hw_serial_; }
|
||||
|
||||
/// Get the UART used by the logger.
|
||||
UARTSelection get_uart() const;
|
||||
|
||||
@@ -94,6 +94,7 @@ void MHZ19Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "MH-Z19:");
|
||||
LOG_SENSOR(" ", "CO2", this->co2_sensor_);
|
||||
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
||||
this->check_uart_settings(9600);
|
||||
|
||||
if (this->abc_boot_logic_ == MHZ19_ABC_ENABLED) {
|
||||
ESP_LOGCONFIG(TAG, " Automatic baseline calibration enabled on boot");
|
||||
|
||||
44
esphome/components/modbus/__init__.py
Normal file
44
esphome/components/modbus/__init__.py
Normal file
@@ -0,0 +1,44 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import uart
|
||||
from esphome.const import CONF_ID, CONF_ADDRESS
|
||||
from esphome.core import coroutine
|
||||
|
||||
DEPENDENCIES = ['uart']
|
||||
|
||||
modbus_ns = cg.esphome_ns.namespace('modbus')
|
||||
Modbus = modbus_ns.class_('Modbus', cg.Component, uart.UARTDevice)
|
||||
ModbusDevice = modbus_ns.class_('ModbusDevice')
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_MODBUS_ID = 'modbus_id'
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(Modbus),
|
||||
}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
cg.add_global(modbus_ns.using)
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
|
||||
yield uart.register_uart_device(var, config)
|
||||
|
||||
|
||||
def modbus_device_schema(default_address):
|
||||
schema = {
|
||||
cv.GenerateID(CONF_MODBUS_ID): cv.use_id(Modbus),
|
||||
}
|
||||
if default_address is None:
|
||||
schema[cv.Required(CONF_ADDRESS)] = cv.hex_uint8_t
|
||||
else:
|
||||
schema[cv.Optional(CONF_ADDRESS, default=default_address)] = cv.hex_uint8_t
|
||||
return cv.Schema(schema)
|
||||
|
||||
|
||||
@coroutine
|
||||
def register_modbus_device(var, config):
|
||||
parent = yield cg.get_variable(config[CONF_MODBUS_ID])
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_address(config[CONF_ADDRESS]))
|
||||
cg.add(parent.register_device(var))
|
||||
119
esphome/components/modbus/modbus.cpp
Normal file
119
esphome/components/modbus/modbus.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#include "modbus.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace modbus {
|
||||
|
||||
static const char *TAG = "modbus";
|
||||
|
||||
void Modbus::loop() {
|
||||
const uint32_t now = millis();
|
||||
if (now - this->last_modbus_byte_ > 50) {
|
||||
this->rx_buffer_.clear();
|
||||
this->last_modbus_byte_ = now;
|
||||
}
|
||||
|
||||
while (this->available()) {
|
||||
uint8_t byte;
|
||||
this->read_byte(&byte);
|
||||
if (this->parse_modbus_byte_(byte)) {
|
||||
this->last_modbus_byte_ = now;
|
||||
} else {
|
||||
this->rx_buffer_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t crc16(const uint8_t *data, uint8_t len) {
|
||||
uint16_t crc = 0xFFFF;
|
||||
while (len--) {
|
||||
crc ^= *data++;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if ((crc & 0x01) != 0) {
|
||||
crc >>= 1;
|
||||
crc ^= 0xA001;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
bool Modbus::parse_modbus_byte_(uint8_t byte) {
|
||||
size_t at = this->rx_buffer_.size();
|
||||
this->rx_buffer_.push_back(byte);
|
||||
const uint8_t *raw = &this->rx_buffer_[0];
|
||||
|
||||
// Byte 0: modbus address (match all)
|
||||
if (at == 0)
|
||||
return true;
|
||||
uint8_t address = raw[0];
|
||||
|
||||
// Byte 1: Function (msb indicates error)
|
||||
if (at == 1)
|
||||
return (byte & 0x80) != 0x80;
|
||||
|
||||
// Byte 2: Size (with modbus rtu function code 4/3)
|
||||
// See also https://en.wikipedia.org/wiki/Modbus
|
||||
if (at == 2)
|
||||
return true;
|
||||
|
||||
uint8_t data_len = raw[2];
|
||||
// Byte 3..3+data_len-1: Data
|
||||
if (at < 3 + data_len)
|
||||
return true;
|
||||
|
||||
// Byte 3+data_len: CRC_LO (over all bytes)
|
||||
if (at == 3 + data_len)
|
||||
return true;
|
||||
// Byte 3+len+1: CRC_HI (over all bytes)
|
||||
uint16_t computed_crc = crc16(raw, 3 + data_len);
|
||||
uint16_t remote_crc = uint16_t(raw[3 + data_len]) | (uint16_t(raw[3 + data_len + 1]) << 8);
|
||||
if (computed_crc != remote_crc) {
|
||||
ESP_LOGW(TAG, "Modbus CRC Check failed! %02X!=%02X", computed_crc, remote_crc);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data(this->rx_buffer_.begin() + 3, this->rx_buffer_.begin() + 3 + data_len);
|
||||
|
||||
bool found = false;
|
||||
for (auto *device : this->devices_) {
|
||||
if (device->address_ == address) {
|
||||
device->on_modbus_data(data);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
ESP_LOGW(TAG, "Got Modbus frame from unknown address 0x%02X!", address);
|
||||
}
|
||||
|
||||
// return false to reset buffer
|
||||
return false;
|
||||
}
|
||||
|
||||
void Modbus::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "Modbus:");
|
||||
this->check_uart_settings(9600, 2);
|
||||
}
|
||||
float Modbus::get_setup_priority() const {
|
||||
// After UART bus
|
||||
return setup_priority::BUS - 1.0f;
|
||||
}
|
||||
void Modbus::send(uint8_t address, uint8_t function, uint16_t start_address, uint16_t register_count) {
|
||||
uint8_t frame[8];
|
||||
frame[0] = address;
|
||||
frame[1] = function;
|
||||
frame[2] = start_address >> 8;
|
||||
frame[3] = start_address >> 0;
|
||||
frame[4] = register_count >> 8;
|
||||
frame[5] = register_count >> 0;
|
||||
auto crc = crc16(frame, 6);
|
||||
frame[6] = crc >> 0;
|
||||
frame[7] = crc >> 8;
|
||||
|
||||
this->write_array(frame, 8);
|
||||
}
|
||||
|
||||
} // namespace modbus
|
||||
} // namespace esphome
|
||||
51
esphome/components/modbus/modbus.h
Normal file
51
esphome/components/modbus/modbus.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace modbus {
|
||||
|
||||
class ModbusDevice;
|
||||
|
||||
class Modbus : public uart::UARTDevice, public Component {
|
||||
public:
|
||||
Modbus() = default;
|
||||
|
||||
void loop() override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
void register_device(ModbusDevice *device) { this->devices_.push_back(device); }
|
||||
|
||||
float get_setup_priority() const override;
|
||||
|
||||
void send(uint8_t address, uint8_t function, uint16_t start_address, uint16_t register_count);
|
||||
|
||||
protected:
|
||||
bool parse_modbus_byte_(uint8_t byte);
|
||||
|
||||
std::vector<uint8_t> rx_buffer_;
|
||||
uint32_t last_modbus_byte_{0};
|
||||
std::vector<ModbusDevice *> devices_;
|
||||
};
|
||||
|
||||
class ModbusDevice {
|
||||
public:
|
||||
void set_parent(Modbus *parent) { parent_ = parent; }
|
||||
void set_address(uint8_t address) { address_ = address; }
|
||||
virtual void on_modbus_data(const std::vector<uint8_t> &data) = 0;
|
||||
|
||||
void send(uint8_t function, uint16_t start_address, uint16_t register_count) {
|
||||
this->parent_->send(this->address_, function, start_address, register_count);
|
||||
}
|
||||
|
||||
protected:
|
||||
friend Modbus;
|
||||
|
||||
Modbus *parent_;
|
||||
uint8_t address_;
|
||||
};
|
||||
|
||||
} // namespace modbus
|
||||
} // namespace esphome
|
||||
@@ -10,7 +10,7 @@ void MPR121Component::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up MPR121...");
|
||||
// soft reset device
|
||||
this->write_byte(MPR121_SOFTRESET, 0x63);
|
||||
delay(100);
|
||||
delay(100); // NOLINT
|
||||
if (!this->write_byte(MPR121_ECR, 0x0)) {
|
||||
this->error_code_ = COMMUNICATION_FAILED;
|
||||
this->mark_failed();
|
||||
|
||||
@@ -154,8 +154,8 @@ def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
|
||||
# https://github.com/marvinroger/async-mqtt-client/blob/master/library.json
|
||||
cg.add_library('AsyncMqttClient-esphome', '0.8.2')
|
||||
# https://github.com/OttoWinter/async-mqtt-client/blob/master/library.json
|
||||
cg.add_library('AsyncMqttClient-esphome', '0.8.4')
|
||||
cg.add_define('USE_MQTT')
|
||||
cg.add_global(mqtt_ns.using)
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ void MQTTClientComponent::check_connected() {
|
||||
this->status_clear_warning();
|
||||
ESP_LOGI(TAG, "MQTT Connected!");
|
||||
// MQTT Client needs some time to be fully set up.
|
||||
delay(100);
|
||||
delay(100); // NOLINT
|
||||
|
||||
this->resubscribe_subscriptions_();
|
||||
|
||||
|
||||
@@ -55,6 +55,9 @@ void MQTTSensorComponent::send_discovery(JsonObject &root, mqtt::SendDiscoveryCo
|
||||
if (!this->sensor_->get_icon().empty())
|
||||
root["icon"] = this->sensor_->get_icon();
|
||||
|
||||
if (this->sensor_->get_force_update())
|
||||
root["force_update"] = true;
|
||||
|
||||
config.command_topic = false;
|
||||
}
|
||||
bool MQTTSensorComponent::send_initial_state() {
|
||||
|
||||
@@ -19,7 +19,7 @@ void MS5611Component::setup() {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
delay(100);
|
||||
delay(100); // NOLINT
|
||||
for (uint8_t offset = 0; offset < 6; offset++) {
|
||||
if (!this->read_byte_16(MS5611_CMD_READ_PROM + (offset * 2), &this->prom_[offset])) {
|
||||
this->mark_failed();
|
||||
|
||||
@@ -74,7 +74,11 @@ def validate_method_pin(value):
|
||||
method_pins['BIT_BANG'] = list(range(0, 16))
|
||||
elif CORE.is_esp32:
|
||||
method_pins['BIT_BANG'] = list(range(0, 32))
|
||||
pins_ = method_pins[method]
|
||||
pins_ = method_pins.get(method)
|
||||
if pins_ is None:
|
||||
# all pins allowed for this method
|
||||
return value
|
||||
|
||||
for opt in (CONF_PIN, CONF_CLOCK_PIN, CONF_DATA_PIN):
|
||||
if opt in value and value[opt] not in pins_:
|
||||
raise cv.Invalid("Method {} only supports pin(s) {}".format(
|
||||
|
||||
@@ -394,7 +394,7 @@ class Nextion : public PollingComponent, public uart::UARTDevice {
|
||||
bool wait_for_ack_{true};
|
||||
};
|
||||
|
||||
class NextionTouchComponent : public binary_sensor::BinarySensor {
|
||||
class NextionTouchComponent : public binary_sensor::BinarySensorInitiallyOff {
|
||||
public:
|
||||
void set_page_id(uint8_t page_id) { page_id_ = page_id; }
|
||||
void set_component_id(uint8_t component_id) { component_id_ = component_id; }
|
||||
|
||||
@@ -19,9 +19,9 @@ void NTC::process_(float value) {
|
||||
return;
|
||||
}
|
||||
|
||||
float lr = logf(value);
|
||||
float v = this->a_ + this->b_ * lr + this->c_ * lr * lr * lr;
|
||||
float temp = 1 / v - 273.15f;
|
||||
double lr = log(double(value));
|
||||
double v = this->a_ + this->b_ * lr + this->c_ * lr * lr * lr;
|
||||
auto temp = float(1.0 / v - 273.15);
|
||||
|
||||
ESP_LOGD(TAG, "'%s' - Temperature: %.1f°C", this->name_.c_str(), temp);
|
||||
this->publish_state(temp);
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace ntc {
|
||||
class NTC : public Component, public sensor::Sensor {
|
||||
public:
|
||||
void set_sensor(Sensor *sensor) { sensor_ = sensor; }
|
||||
void set_a(float a) { a_ = a; }
|
||||
void set_b(float b) { b_ = b; }
|
||||
void set_c(float c) { c_ = c; }
|
||||
void set_a(double a) { a_ = a; }
|
||||
void set_b(double b) { b_ = b; }
|
||||
void set_c(double c) { c_ = c; }
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
@@ -20,9 +20,9 @@ class NTC : public Component, public sensor::Sensor {
|
||||
void process_(float value);
|
||||
|
||||
sensor::Sensor *sensor_;
|
||||
float a_;
|
||||
float b_;
|
||||
float c_;
|
||||
double a_;
|
||||
double b_;
|
||||
double c_;
|
||||
};
|
||||
|
||||
} // namespace ntc
|
||||
|
||||
@@ -266,7 +266,7 @@ void OTAComponent::handle_() {
|
||||
delay(10);
|
||||
ESP_LOGI(TAG, "OTA update finished!");
|
||||
this->status_clear_warning();
|
||||
delay(100);
|
||||
delay(100); // NOLINT
|
||||
App.safe_reboot();
|
||||
|
||||
error:
|
||||
|
||||
@@ -11,7 +11,6 @@ pcf8574_ns = cg.esphome_ns.namespace('pcf8574')
|
||||
PCF8574GPIOMode = pcf8574_ns.enum('PCF8574GPIOMode')
|
||||
PCF8674_GPIO_MODES = {
|
||||
'INPUT': PCF8574GPIOMode.PCF8574_INPUT,
|
||||
'INPUT_PULLUP': PCF8574GPIOMode.PCF8574_INPUT_PULLUP,
|
||||
'OUTPUT': PCF8574GPIOMode.PCF8574_OUTPUT,
|
||||
}
|
||||
|
||||
@@ -33,16 +32,24 @@ def to_code(config):
|
||||
cg.add(var.set_pcf8575(config[CONF_PCF8575]))
|
||||
|
||||
|
||||
def validate_pcf8574_gpio_mode(value):
|
||||
value = cv.string(value)
|
||||
if value.upper() == 'INPUT_PULLUP':
|
||||
raise cv.Invalid("INPUT_PULLUP mode has been removed in 1.14 and been combined into "
|
||||
"INPUT mode (they were the same thing). Please use INPUT instead.")
|
||||
return cv.enum(PCF8674_GPIO_MODES, upper=True)(value)
|
||||
|
||||
|
||||
PCF8574_OUTPUT_PIN_SCHEMA = cv.Schema({
|
||||
cv.Required(CONF_PCF8574): cv.use_id(PCF8574Component),
|
||||
cv.Required(CONF_NUMBER): cv.int_,
|
||||
cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(PCF8674_GPIO_MODES, upper=True),
|
||||
cv.Optional(CONF_MODE, default="OUTPUT"): validate_pcf8574_gpio_mode,
|
||||
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||
})
|
||||
PCF8574_INPUT_PIN_SCHEMA = cv.Schema({
|
||||
cv.Required(CONF_PCF8574): cv.use_id(PCF8574Component),
|
||||
cv.Required(CONF_NUMBER): cv.int_,
|
||||
cv.Optional(CONF_MODE, default="INPUT"): cv.enum(PCF8674_GPIO_MODES, upper=True),
|
||||
cv.Optional(CONF_MODE, default="INPUT"): validate_pcf8574_gpio_mode,
|
||||
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||
})
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ bool PCF8574Component::digital_read(uint8_t pin) {
|
||||
}
|
||||
void PCF8574Component::digital_write(uint8_t pin, bool value) {
|
||||
if (value) {
|
||||
this->port_mask_ |= (1 << pin);
|
||||
this->output_mask_ |= (1 << pin);
|
||||
} else {
|
||||
this->port_mask_ &= ~(1 << pin);
|
||||
this->output_mask_ &= ~(1 << pin);
|
||||
}
|
||||
|
||||
this->write_gpio_();
|
||||
@@ -41,16 +41,14 @@ void PCF8574Component::digital_write(uint8_t pin, bool value) {
|
||||
void PCF8574Component::pin_mode(uint8_t pin, uint8_t mode) {
|
||||
switch (mode) {
|
||||
case PCF8574_INPUT:
|
||||
this->ddr_mask_ &= ~(1 << pin);
|
||||
this->port_mask_ &= ~(1 << pin);
|
||||
break;
|
||||
case PCF8574_INPUT_PULLUP:
|
||||
this->ddr_mask_ &= ~(1 << pin);
|
||||
this->port_mask_ |= (1 << pin);
|
||||
// Clear mode mask bit
|
||||
this->mode_mask_ &= ~(1 << pin);
|
||||
// Write GPIO to enable input mode
|
||||
this->write_gpio_();
|
||||
break;
|
||||
case PCF8574_OUTPUT:
|
||||
this->ddr_mask_ |= (1 << pin);
|
||||
this->port_mask_ &= ~(1 << pin);
|
||||
// Set mode mask bit
|
||||
this->mode_mask_ |= 1 << pin;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -59,21 +57,20 @@ void PCF8574Component::pin_mode(uint8_t pin, uint8_t mode) {
|
||||
bool PCF8574Component::read_gpio_() {
|
||||
if (this->is_failed())
|
||||
return false;
|
||||
|
||||
bool success;
|
||||
uint8_t data[2];
|
||||
if (this->pcf8575_) {
|
||||
if (!this->parent_->raw_receive_16(this->address_, &this->input_mask_, 1)) {
|
||||
this->status_set_warning();
|
||||
return false;
|
||||
}
|
||||
success = this->read_bytes_raw(data, 2);
|
||||
this->input_mask_ = (uint16_t(data[1]) << 8) | (uint16_t(data[0]) << 0);
|
||||
} else {
|
||||
uint8_t data;
|
||||
if (!this->parent_->raw_receive(this->address_, &data, 1)) {
|
||||
this->status_set_warning();
|
||||
return false;
|
||||
}
|
||||
this->input_mask_ = data;
|
||||
success = this->read_bytes_raw(data, 1);
|
||||
this->input_mask_ = data[0];
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
this->status_set_warning();
|
||||
return false;
|
||||
}
|
||||
this->status_clear_warning();
|
||||
return true;
|
||||
}
|
||||
@@ -81,20 +78,20 @@ bool PCF8574Component::write_gpio_() {
|
||||
if (this->is_failed())
|
||||
return false;
|
||||
|
||||
uint16_t value = (this->input_mask_ & ~this->ddr_mask_) | this->port_mask_;
|
||||
uint16_t value = 0;
|
||||
// Pins in OUTPUT mode and where pin is HIGH.
|
||||
value |= this->mode_mask_ & this->output_mask_;
|
||||
// Pins in INPUT mode must also be set here
|
||||
value |= ~this->mode_mask_;
|
||||
|
||||
this->parent_->raw_begin_transmission(this->address_);
|
||||
uint8_t data = value & 0xFF;
|
||||
this->parent_->raw_write(this->address_, &data, 1);
|
||||
|
||||
if (this->pcf8575_) {
|
||||
data = (value >> 8) & 0xFF;
|
||||
this->parent_->raw_write(this->address_, &data, 1);
|
||||
}
|
||||
if (!this->parent_->raw_end_transmission(this->address_)) {
|
||||
uint8_t data[2];
|
||||
data[0] = value;
|
||||
data[1] = value >> 8;
|
||||
if (!this->write_bytes_raw(data, this->pcf8575_ ? 2 : 1)) {
|
||||
this->status_set_warning();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->status_clear_warning();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ namespace pcf8574 {
|
||||
/// Modes for PCF8574 pins
|
||||
enum PCF8574GPIOMode : uint8_t {
|
||||
PCF8574_INPUT = INPUT,
|
||||
PCF8574_INPUT_PULLUP = INPUT_PULLUP,
|
||||
PCF8574_OUTPUT = OUTPUT,
|
||||
};
|
||||
|
||||
@@ -38,9 +37,12 @@ class PCF8574Component : public Component, public i2c::I2CDevice {
|
||||
|
||||
bool write_gpio_();
|
||||
|
||||
uint16_t ddr_mask_{0x00};
|
||||
/// Mask for the pin mode - 1 means output, 0 means input
|
||||
uint16_t mode_mask_{0x00};
|
||||
/// The mask to write as output state - 1 means HIGH, 0 means LOW
|
||||
uint16_t output_mask_{0x00};
|
||||
/// The state read in read_gpio_ - 1 means HIGH, 0 means LOW
|
||||
uint16_t input_mask_{0x00};
|
||||
uint16_t port_mask_{0x00};
|
||||
bool pcf8575_; ///< TRUE->16-channel PCF8575, FALSE->8-channel PCF8574
|
||||
};
|
||||
|
||||
|
||||
@@ -169,6 +169,7 @@ void PMSX003Component::dump_config() {
|
||||
LOG_SENSOR(" ", "Temperature", this->temperature_sensor_);
|
||||
LOG_SENSOR(" ", "Humidity", this->humidity_sensor_);
|
||||
LOG_SENSOR(" ", "Formaldehyde", this->formaldehyde_sensor_);
|
||||
this->check_uart_settings(9600);
|
||||
}
|
||||
|
||||
} // namespace pmsx003
|
||||
|
||||
@@ -12,24 +12,24 @@ pmsx003_ns = cg.esphome_ns.namespace('pmsx003')
|
||||
PMSX003Component = pmsx003_ns.class_('PMSX003Component', uart.UARTDevice, cg.Component)
|
||||
PMSX003Sensor = pmsx003_ns.class_('PMSX003Sensor', sensor.Sensor)
|
||||
|
||||
CONF_PMSX003 = 'PMSX003'
|
||||
CONF_PMS5003T = 'PMS5003T'
|
||||
CONF_PMS5003ST = 'PMS5003ST'
|
||||
TYPE_PMSX003 = 'PMSX003'
|
||||
TYPE_PMS5003T = 'PMS5003T'
|
||||
TYPE_PMS5003ST = 'PMS5003ST'
|
||||
|
||||
PMSX003Type = pmsx003_ns.enum('PMSX003Type')
|
||||
PMSX003_TYPES = {
|
||||
CONF_PMSX003: PMSX003Type.PMSX003_TYPE_X003,
|
||||
CONF_PMS5003T: PMSX003Type.PMSX003_TYPE_5003T,
|
||||
CONF_PMS5003ST: PMSX003Type.PMSX003_TYPE_5003ST,
|
||||
TYPE_PMSX003: PMSX003Type.PMSX003_TYPE_X003,
|
||||
TYPE_PMS5003T: PMSX003Type.PMSX003_TYPE_5003T,
|
||||
TYPE_PMS5003ST: PMSX003Type.PMSX003_TYPE_5003ST,
|
||||
}
|
||||
|
||||
SENSORS_TO_TYPE = {
|
||||
CONF_PM_1_0: [CONF_PMSX003, CONF_PMS5003ST],
|
||||
CONF_PM_2_5: [CONF_PMSX003, CONF_PMS5003T, CONF_PMS5003ST],
|
||||
CONF_PM_10_0: [CONF_PMSX003, CONF_PMS5003ST],
|
||||
CONF_TEMPERATURE: [CONF_PMS5003T, CONF_PMS5003ST],
|
||||
CONF_HUMIDITY: [CONF_PMS5003T, CONF_PMS5003ST],
|
||||
CONF_FORMALDEHYDE: [CONF_PMS5003ST],
|
||||
CONF_PM_1_0: [TYPE_PMSX003, TYPE_PMS5003ST],
|
||||
CONF_PM_2_5: [TYPE_PMSX003, TYPE_PMS5003T, TYPE_PMS5003ST],
|
||||
CONF_PM_10_0: [TYPE_PMSX003, TYPE_PMS5003ST],
|
||||
CONF_TEMPERATURE: [TYPE_PMS5003T, TYPE_PMS5003ST],
|
||||
CONF_HUMIDITY: [TYPE_PMS5003T, TYPE_PMS5003ST],
|
||||
CONF_FORMALDEHYDE: [TYPE_PMS5003ST],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ void PulseCounterSensor::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, " Rising Edge: %s", EDGE_MODE_TO_STRING[this->storage_.rising_edge_mode]);
|
||||
ESP_LOGCONFIG(TAG, " Falling Edge: %s", EDGE_MODE_TO_STRING[this->storage_.falling_edge_mode]);
|
||||
ESP_LOGCONFIG(TAG, " Filtering pulses shorter than %u µs", this->storage_.filter_us);
|
||||
LOG_UPDATE_INTERVAL(this);
|
||||
}
|
||||
|
||||
void PulseCounterSensor::update() {
|
||||
|
||||
0
esphome/components/pzem004t/__init__.py
Normal file
0
esphome/components/pzem004t/__init__.py
Normal file
109
esphome/components/pzem004t/pzem004t.cpp
Normal file
109
esphome/components/pzem004t/pzem004t.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "pzem004t.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pzem004t {
|
||||
|
||||
static const char *TAG = "pzem004t";
|
||||
|
||||
void PZEM004T::loop() {
|
||||
const uint32_t now = millis();
|
||||
if (now - this->last_read_ > 500 && this->available() < 7) {
|
||||
while (this->available())
|
||||
this->read();
|
||||
this->last_read_ = now;
|
||||
}
|
||||
|
||||
// PZEM004T packet size is 7 byte
|
||||
while (this->available() >= 7) {
|
||||
auto resp = *this->read_array<7>();
|
||||
// packet format:
|
||||
// 0: packet type
|
||||
// 1-5: data
|
||||
// 6: checksum (sum of other bytes)
|
||||
// see https://github.com/olehs/PZEM004T
|
||||
uint8_t sum = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
sum += resp[i];
|
||||
|
||||
if (sum != resp[6]) {
|
||||
ESP_LOGV(TAG, "PZEM004T invalid checksum! 0x%02X != 0x%02X", sum, resp[6]);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (resp[0]) {
|
||||
case 0xA4: { // Set Module Address Response
|
||||
this->write_state_(READ_VOLTAGE);
|
||||
break;
|
||||
}
|
||||
case 0xA0: { // Voltage Response
|
||||
uint16_t int_voltage = (uint16_t(resp[1]) << 8) | (uint16_t(resp[2]) << 0);
|
||||
float voltage = int_voltage + (resp[3] / 10.0f);
|
||||
if (this->voltage_sensor_ != nullptr)
|
||||
this->voltage_sensor_->publish_state(voltage);
|
||||
ESP_LOGD(TAG, "Got Voltage %.1f V", voltage);
|
||||
this->write_state_(READ_CURRENT);
|
||||
break;
|
||||
}
|
||||
case 0xA1: { // Current Response
|
||||
uint16_t int_current = (uint16_t(resp[1]) << 8) | (uint16_t(resp[2]) << 0);
|
||||
float current = int_current + (resp[3] / 100.0f);
|
||||
if (this->current_sensor_ != nullptr)
|
||||
this->current_sensor_->publish_state(current);
|
||||
ESP_LOGD(TAG, "Got Current %.2f A", current);
|
||||
this->write_state_(READ_POWER);
|
||||
break;
|
||||
}
|
||||
case 0xA2: { // Active Power Response
|
||||
uint16_t power = (uint16_t(resp[1]) << 8) | (uint16_t(resp[2]) << 0);
|
||||
if (this->power_sensor_ != nullptr)
|
||||
this->power_sensor_->publish_state(power);
|
||||
ESP_LOGD(TAG, "Got Power %u W", power);
|
||||
this->write_state_(DONE);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xA3: // Energy Response
|
||||
case 0xA5: // Set Power Alarm Response
|
||||
case 0xB0: // Voltage Request
|
||||
case 0xB1: // Current Request
|
||||
case 0xB2: // Active Power Response
|
||||
case 0xB3: // Energy Request
|
||||
case 0xB4: // Set Module Address Request
|
||||
case 0xB5: // Set Power Alarm Request
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
this->last_read_ = now;
|
||||
}
|
||||
}
|
||||
void PZEM004T::update() { this->write_state_(READ_VOLTAGE); }
|
||||
void PZEM004T::write_state_(PZEM004T::PZEM004TReadState state) {
|
||||
if (state == DONE) {
|
||||
this->read_state_ = state;
|
||||
return;
|
||||
}
|
||||
std::array<uint8_t, 7> data{};
|
||||
data[0] = state;
|
||||
data[1] = 192;
|
||||
data[2] = 168;
|
||||
data[3] = 1;
|
||||
data[4] = 1;
|
||||
data[5] = 0;
|
||||
data[6] = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
data[6] += data[i];
|
||||
|
||||
this->write_array(data);
|
||||
this->read_state_ = state;
|
||||
}
|
||||
void PZEM004T::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "PZEM004T:");
|
||||
LOG_SENSOR("", "Voltage", this->voltage_sensor_);
|
||||
LOG_SENSOR("", "Current", this->current_sensor_);
|
||||
LOG_SENSOR("", "Power", this->power_sensor_);
|
||||
}
|
||||
|
||||
} // namespace pzem004t
|
||||
} // namespace esphome
|
||||
41
esphome/components/pzem004t/pzem004t.h
Normal file
41
esphome/components/pzem004t/pzem004t.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/uart/uart.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pzem004t {
|
||||
|
||||
class PZEM004T : public PollingComponent, public uart::UARTDevice {
|
||||
public:
|
||||
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
|
||||
void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
|
||||
void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }
|
||||
|
||||
void loop() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
sensor::Sensor *voltage_sensor_;
|
||||
sensor::Sensor *current_sensor_;
|
||||
sensor::Sensor *power_sensor_;
|
||||
|
||||
enum PZEM004TReadState {
|
||||
SET_ADDRESS = 0xB4,
|
||||
READ_VOLTAGE = 0xB0,
|
||||
READ_CURRENT = 0xB1,
|
||||
READ_POWER = 0xB2,
|
||||
DONE = 0x00,
|
||||
} read_state_{DONE};
|
||||
|
||||
void write_state_(PZEM004TReadState state);
|
||||
|
||||
uint32_t last_read_{0};
|
||||
};
|
||||
|
||||
} // namespace pzem004t
|
||||
} // namespace esphome
|
||||
37
esphome/components/pzem004t/sensor.py
Normal file
37
esphome/components/pzem004t/sensor.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, uart
|
||||
from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_VOLTAGE, \
|
||||
UNIT_VOLT, ICON_FLASH, UNIT_AMPERE, UNIT_WATT
|
||||
|
||||
DEPENDENCIES = ['uart']
|
||||
|
||||
pzem004t_ns = cg.esphome_ns.namespace('pzem004t')
|
||||
PZEM004T = pzem004t_ns.class_('PZEM004T', cg.PollingComponent, uart.UARTDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(PZEM004T),
|
||||
|
||||
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 1),
|
||||
cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_FLASH, 2),
|
||||
cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_FLASH, 0),
|
||||
}).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield uart.register_uart_device(var, config)
|
||||
|
||||
if CONF_VOLTAGE in config:
|
||||
conf = config[CONF_VOLTAGE]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_voltage_sensor(sens))
|
||||
if CONF_CURRENT in config:
|
||||
conf = config[CONF_CURRENT]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_current_sensor(sens))
|
||||
if CONF_POWER in config:
|
||||
conf = config[CONF_POWER]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_power_sensor(sens))
|
||||
0
esphome/components/pzemac/__init__.py
Normal file
0
esphome/components/pzemac/__init__.py
Normal file
71
esphome/components/pzemac/pzemac.cpp
Normal file
71
esphome/components/pzemac/pzemac.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "pzemac.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pzemac {
|
||||
|
||||
static const char *TAG = "pzemac";
|
||||
|
||||
static const uint8_t PZEM_CMD_READ_IN_REGISTERS = 0x04;
|
||||
static const uint8_t PZEM_REGISTER_COUNT = 10; // 10x 16-bit registers
|
||||
|
||||
void PZEMAC::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||
if (data.size() < 20) {
|
||||
ESP_LOGW(TAG, "Invalid size for PZEM AC!");
|
||||
return;
|
||||
}
|
||||
|
||||
// See https://github.com/esphome/feature-requests/issues/49#issuecomment-538636809
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
||||
// 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34
|
||||
// Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc--
|
||||
|
||||
auto pzem_get_16bit = [&](size_t i) -> uint16_t {
|
||||
return (uint16_t(data[i + 0]) << 8) | (uint16_t(data[i + 1]) << 0);
|
||||
};
|
||||
auto pzem_get_32bit = [&](size_t i) -> uint32_t {
|
||||
return (uint32_t(pzem_get_16bit(i + 2)) << 16) | (uint32_t(pzem_get_16bit(i + 0)) << 0);
|
||||
};
|
||||
|
||||
uint16_t raw_voltage = pzem_get_16bit(0);
|
||||
float voltage = raw_voltage / 10.0f; // max 6553.5 V
|
||||
|
||||
uint32_t raw_current = pzem_get_32bit(2);
|
||||
float current = raw_current / 1000.0f; // max 4294967.295 A
|
||||
|
||||
uint32_t raw_active_power = pzem_get_32bit(6);
|
||||
float active_power = raw_active_power / 10.0f; // max 429496729.5 W
|
||||
|
||||
uint16_t raw_frequency = pzem_get_16bit(14);
|
||||
float frequency = raw_frequency / 10.0f;
|
||||
|
||||
uint16_t raw_power_factor = pzem_get_16bit(16);
|
||||
float power_factor = raw_power_factor / 100.0f;
|
||||
|
||||
ESP_LOGD(TAG, "PZEM AC: V=%.1f V, I=%.3f A, P=%.1f W, F=%.1f Hz, PF=%.2f", voltage, current, active_power, frequency,
|
||||
power_factor);
|
||||
if (this->voltage_sensor_ != nullptr)
|
||||
this->voltage_sensor_->publish_state(voltage);
|
||||
if (this->current_sensor_ != nullptr)
|
||||
this->current_sensor_->publish_state(current);
|
||||
if (this->power_sensor_ != nullptr)
|
||||
this->power_sensor_->publish_state(active_power);
|
||||
if (this->frequency_sensor_ != nullptr)
|
||||
this->frequency_sensor_->publish_state(frequency);
|
||||
if (this->power_factor_sensor_ != nullptr)
|
||||
this->power_factor_sensor_->publish_state(power_factor);
|
||||
}
|
||||
|
||||
void PZEMAC::update() { this->send(PZEM_CMD_READ_IN_REGISTERS, 0, PZEM_REGISTER_COUNT); }
|
||||
void PZEMAC::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "PZEMAC:");
|
||||
ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
|
||||
LOG_SENSOR("", "Voltage", this->voltage_sensor_);
|
||||
LOG_SENSOR("", "Current", this->current_sensor_);
|
||||
LOG_SENSOR("", "Power", this->power_sensor_);
|
||||
LOG_SENSOR("", "Frequency", this->frequency_sensor_);
|
||||
LOG_SENSOR("", "Power Factor", this->power_factor_sensor_);
|
||||
}
|
||||
|
||||
} // namespace pzemac
|
||||
} // namespace esphome
|
||||
33
esphome/components/pzemac/pzemac.h
Normal file
33
esphome/components/pzemac/pzemac.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/modbus/modbus.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pzemac {
|
||||
|
||||
class PZEMAC : public PollingComponent, public modbus::ModbusDevice {
|
||||
public:
|
||||
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
|
||||
void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
|
||||
void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }
|
||||
void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; }
|
||||
void set_power_factor_sensor(sensor::Sensor *power_factor_sensor) { power_factor_sensor_ = power_factor_sensor; }
|
||||
|
||||
void update() override;
|
||||
|
||||
void on_modbus_data(const std::vector<uint8_t> &data) override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
sensor::Sensor *voltage_sensor_;
|
||||
sensor::Sensor *current_sensor_;
|
||||
sensor::Sensor *power_sensor_;
|
||||
sensor::Sensor *frequency_sensor_;
|
||||
sensor::Sensor *power_factor_sensor_;
|
||||
};
|
||||
|
||||
} // namespace pzemac
|
||||
} // namespace esphome
|
||||
47
esphome/components/pzemac/sensor.py
Normal file
47
esphome/components/pzemac/sensor.py
Normal file
@@ -0,0 +1,47 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, modbus
|
||||
from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_VOLTAGE, \
|
||||
CONF_FREQUENCY, UNIT_VOLT, ICON_FLASH, UNIT_AMPERE, UNIT_WATT, UNIT_EMPTY, \
|
||||
ICON_POWER, CONF_POWER_FACTOR, ICON_CURRENT_AC, UNIT_HERTZ
|
||||
|
||||
AUTO_LOAD = ['modbus']
|
||||
|
||||
pzemac_ns = cg.esphome_ns.namespace('pzemac')
|
||||
PZEMAC = pzemac_ns.class_('PZEMAC', cg.PollingComponent, modbus.ModbusDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(PZEMAC),
|
||||
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 1),
|
||||
cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_CURRENT_AC, 3),
|
||||
cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_POWER, 1),
|
||||
cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(UNIT_HERTZ, ICON_CURRENT_AC, 1),
|
||||
cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema(UNIT_EMPTY, ICON_FLASH, 2),
|
||||
}).extend(cv.polling_component_schema('60s')).extend(modbus.modbus_device_schema(0x01))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield modbus.register_modbus_device(var, config)
|
||||
|
||||
if CONF_VOLTAGE in config:
|
||||
conf = config[CONF_VOLTAGE]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_voltage_sensor(sens))
|
||||
if CONF_CURRENT in config:
|
||||
conf = config[CONF_CURRENT]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_current_sensor(sens))
|
||||
if CONF_POWER in config:
|
||||
conf = config[CONF_POWER]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_power_sensor(sens))
|
||||
if CONF_FREQUENCY in config:
|
||||
conf = config[CONF_FREQUENCY]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_frequency_sensor(sens))
|
||||
if CONF_POWER_FACTOR in config:
|
||||
conf = config[CONF_POWER_FACTOR]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_power_factor_sensor(sens))
|
||||
0
esphome/components/pzemdc/__init__.py
Normal file
0
esphome/components/pzemdc/__init__.py
Normal file
59
esphome/components/pzemdc/pzemdc.cpp
Normal file
59
esphome/components/pzemdc/pzemdc.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "pzemdc.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pzemdc {
|
||||
|
||||
static const char *TAG = "pzemdc";
|
||||
|
||||
static const uint8_t PZEM_CMD_READ_IN_REGISTERS = 0x04;
|
||||
static const uint8_t PZEM_REGISTER_COUNT = 10; // 10x 16-bit registers
|
||||
|
||||
void PZEMDC::on_modbus_data(const std::vector<uint8_t> &data) {
|
||||
if (data.size() < 16) {
|
||||
ESP_LOGW(TAG, "Invalid size for PZEM DC!");
|
||||
return;
|
||||
}
|
||||
|
||||
// See https://github.com/esphome/feature-requests/issues/49#issuecomment-538636809
|
||||
// 0 1 2 3 4 5 6 7 = ModBus register
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 = Buffer index
|
||||
// 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29
|
||||
// Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc--
|
||||
|
||||
auto pzem_get_16bit = [&](size_t i) -> uint16_t {
|
||||
return (uint16_t(data[i + 0]) << 8) | (uint16_t(data[i + 1]) << 0);
|
||||
};
|
||||
auto pzem_get_32bit = [&](size_t i) -> uint32_t {
|
||||
return (uint32_t(pzem_get_16bit(i + 2)) << 16) | (uint32_t(pzem_get_16bit(i + 0)) << 0);
|
||||
};
|
||||
|
||||
uint16_t raw_voltage = pzem_get_16bit(0);
|
||||
float voltage = raw_voltage / 100.0f; // max 655.35 V
|
||||
|
||||
uint16_t raw_current = pzem_get_16bit(2);
|
||||
float current = raw_current / 100.0f; // max 655.35 A
|
||||
|
||||
uint32_t raw_power = pzem_get_32bit(4);
|
||||
float power = raw_power / 10.0f; // max 429496729.5 W
|
||||
|
||||
ESP_LOGD(TAG, "PZEM DC: V=%.1f V, I=%.3f A, P=%.1f W", voltage, current, power);
|
||||
if (this->voltage_sensor_ != nullptr)
|
||||
this->voltage_sensor_->publish_state(voltage);
|
||||
if (this->current_sensor_ != nullptr)
|
||||
this->current_sensor_->publish_state(current);
|
||||
if (this->power_sensor_ != nullptr)
|
||||
this->power_sensor_->publish_state(power);
|
||||
}
|
||||
|
||||
void PZEMDC::update() { this->send(PZEM_CMD_READ_IN_REGISTERS, 0, 8); }
|
||||
void PZEMDC::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "PZEMDC:");
|
||||
ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
|
||||
LOG_SENSOR("", "Voltage", this->voltage_sensor_);
|
||||
LOG_SENSOR("", "Current", this->current_sensor_);
|
||||
LOG_SENSOR("", "Power", this->power_sensor_);
|
||||
}
|
||||
|
||||
} // namespace pzemdc
|
||||
} // namespace esphome
|
||||
33
esphome/components/pzemdc/pzemdc.h
Normal file
33
esphome/components/pzemdc/pzemdc.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/modbus/modbus.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace pzemdc {
|
||||
|
||||
class PZEMDC : public PollingComponent, public modbus::ModbusDevice {
|
||||
public:
|
||||
void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; }
|
||||
void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; }
|
||||
void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; }
|
||||
void set_frequency_sensor(sensor::Sensor *frequency_sensor) { frequency_sensor_ = frequency_sensor; }
|
||||
void set_powerfactor_sensor(sensor::Sensor *powerfactor_sensor) { power_factor_sensor_ = powerfactor_sensor; }
|
||||
|
||||
void update() override;
|
||||
|
||||
void on_modbus_data(const std::vector<uint8_t> &data) override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
protected:
|
||||
sensor::Sensor *voltage_sensor_;
|
||||
sensor::Sensor *current_sensor_;
|
||||
sensor::Sensor *power_sensor_;
|
||||
sensor::Sensor *frequency_sensor_;
|
||||
sensor::Sensor *power_factor_sensor_;
|
||||
};
|
||||
|
||||
} // namespace pzemdc
|
||||
} // namespace esphome
|
||||
36
esphome/components/pzemdc/sensor.py
Normal file
36
esphome/components/pzemdc/sensor.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, modbus
|
||||
from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_VOLTAGE, \
|
||||
UNIT_VOLT, ICON_FLASH, UNIT_AMPERE, UNIT_WATT, ICON_POWER, ICON_CURRENT_AC
|
||||
|
||||
AUTO_LOAD = ['modbus']
|
||||
|
||||
pzemdc_ns = cg.esphome_ns.namespace('pzemdc')
|
||||
PZEMDC = pzemdc_ns.class_('PZEMDC', cg.PollingComponent, modbus.ModbusDevice)
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(PZEMDC),
|
||||
cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 1),
|
||||
cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_CURRENT_AC, 3),
|
||||
cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_POWER, 1),
|
||||
}).extend(cv.polling_component_schema('60s')).extend(modbus.modbus_device_schema(0x01))
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
yield modbus.register_modbus_device(var, config)
|
||||
|
||||
if CONF_VOLTAGE in config:
|
||||
conf = config[CONF_VOLTAGE]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_voltage_sensor(sens))
|
||||
if CONF_CURRENT in config:
|
||||
conf = config[CONF_CURRENT]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_current_sensor(sens))
|
||||
if CONF_POWER in config:
|
||||
conf = config[CONF_POWER]
|
||||
sens = yield sensor.new_sensor(conf)
|
||||
cg.add(var.set_power_sensor(sens))
|
||||
@@ -28,7 +28,7 @@ class RDM6300Component : public Component, public uart::UARTDevice {
|
||||
uint32_t last_id_{0};
|
||||
};
|
||||
|
||||
class RDM6300BinarySensor : public binary_sensor::BinarySensor {
|
||||
class RDM6300BinarySensor : public binary_sensor::BinarySensorInitiallyOff {
|
||||
public:
|
||||
void set_id(uint32_t id) { id_ = id; }
|
||||
|
||||
|
||||
@@ -267,11 +267,11 @@ class RemoteReceiverBase : public RemoteComponentBase {
|
||||
uint8_t tolerance_{25};
|
||||
};
|
||||
|
||||
class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensor,
|
||||
class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitiallyOff,
|
||||
public Component,
|
||||
public RemoteReceiverListener {
|
||||
public:
|
||||
explicit RemoteReceiverBinarySensorBase() : BinarySensor() {}
|
||||
explicit RemoteReceiverBinarySensorBase() : BinarySensorInitiallyOff() {}
|
||||
void dump_config() override;
|
||||
virtual bool matches(RemoteReceiveData src) = 0;
|
||||
bool on_receive(RemoteReceiveData src) override {
|
||||
|
||||
@@ -13,8 +13,8 @@ void RestartSwitch::write_state(bool state) {
|
||||
|
||||
if (state) {
|
||||
ESP_LOGI(TAG, "Restarting device...");
|
||||
// then execute
|
||||
delay(100); // Let MQTT settle a bit
|
||||
// Let MQTT settle a bit
|
||||
delay(100); // NOLINT
|
||||
App.safe_reboot();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,13 @@ static const uint16_t STATE_DECREMENT_COUNTER_1 = 0x1000;
|
||||
// Bit 2&3 (0x0C) encodes state S0-S3
|
||||
// Bit 4 (0x10) encodes clockwise/counter-clockwise rotation
|
||||
|
||||
static const uint16_t STATE_LOOKUP_TABLE[32] = {
|
||||
// Only apply if DRAM_ATTR exists on this platform (exists on ESP32, not on ESP8266)
|
||||
#ifndef DRAM_ATTR
|
||||
#define DRAM_ATTR
|
||||
#endif
|
||||
// array needs to be placed in .dram1 for ESP32
|
||||
// otherwise it will automatically go into flash, and cause cache disabled issues
|
||||
static const uint16_t DRAM_ATTR STATE_LOOKUP_TABLE[32] = {
|
||||
// act state S0 in CCW direction
|
||||
STATE_CCW | STATE_S0, // 0x00: stay here
|
||||
STATE_CW | STATE_S1 | STATE_INCREMENT_COUNTER_1, // 0x01: goto CW+S1 and increment counter (dir change)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user