Skip to content

Commit

Permalink
Merge pull request #4744 from tonhuisman/feature/P035-add-inverted-ou…
Browse files Browse the repository at this point in the history
…tput-option

[P035] Add Inverted output option, as supported by the IRsend library
  • Loading branch information
TD-er committed Jul 25, 2023
2 parents f4b3241 + 704d418 commit 6c6a8d3
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 114 deletions.
47 changes: 37 additions & 10 deletions docs/source/Plugin/P035.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.. include:: ../Plugin/_plugin_substitutions_p03x.repl
.. include:: ../Plugin/_plugin_substitutions_p03x.repl
.. _P035_page:

|P035_typename|
Expand All @@ -21,27 +21,54 @@ Maintainer: |P035_maintainer|

Used libraries: |P035_usedlibraries|

Supported hardware
------------------
Introduction
------------
This plugin can be used to send out IR signals, usually at 38 kHz, to IR-controlled devices like ventilators, TVs, airconditioners etc.

|P035_usedby|
.. Supported hardware
.. ------------------
.. Commands available
.. ^^^^^^^^^^^^^^^^^^
.. .. |P035_usedby|
.. .. include:: P035_commands.repl
Wiring
------

.. Events
.. ~~~~~~
The IR led can be connected directly to an ESP GPIO pin. The default is that the Anode of the LED is connected to the GPIO pin, and the Cathode to GND, but using the **Inverted output** configuration setting allows to connect the Anode to VCC, and the Cathode to the GPIO pin.

.. .. include:: P035_events.repl
Device Configuration
--------------------

.. image:: P035_DeviceConfiguration.png

* **Name**: Required by ESPEasy, must be unique among the list of available devices/tasks.

* **Enabled**: The device can be disabled or enabled. When not enabled the device should not use any resources.

Actuator
^^^^^^^^

* **GPIO -> LED**: Select the GPIO pin the LED is connected to.

Device Settings
^^^^^^^^^^^^^^^

* **Inverted output**: With this setting enabled, the signal will be sent out inverted (On and Off swapped), so the LED can be connected to VCC and the GPIO pin, instead of between the GPIO pin and GND. This allows for a somewhat larger current through the LED.


Commands available
^^^^^^^^^^^^^^^^^^

.. include:: P035_commands.repl

Change log
----------

.. versionchanged:: 2.0
...

|added|
2023-07-21 Inverted output option introduced.

|added|
Major overhaul for 2.0 release.

Expand Down
Binary file added docs/source/Plugin/P035_DeviceConfiguration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 0 additions & 70 deletions docs/source/Plugin/P035_IR_transmitter.rst

This file was deleted.

44 changes: 44 additions & 0 deletions docs/source/Plugin/P035_commands.repl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.. csv-table::
:header: "Command", "Extra information"
:widths: 20, 30

"
| ``irsend,<protocol>,<data>[,<bits>[,<repeats>]]``

| Arguments:

| ``<protocol>``: Required. The IR protocol to use for sending the data.

| ``<data>``: Required. The data to send out.

| ``<bits>``: Optional. The number of bits of the protocol used. When using 0 (or not providing a value), the protocol-default will be used.

| ``<repeats>``: Optional. How often should the data be transmitted. Many manual IR remotes repeat the same signal up to 3 times, and each protocol has a default setting for this parameter, that will be used when not specified.
","
| Send data out, using the protocol specified. The protocol and required data for a specific command can be obtained from f.i. a manual IR remote by using a TSOP4838 IR receiver and plugin P016: :ref:`P016_page`, retrieving the relevant data from the logs.

| Supported protocols are available from the |IR_protocols_page| (external link)
"
"
| ``irsendac,<{JSON-formatted-AC-command}>``

| Argument:

| ``<{JSON-formatted-AC-command}>``: Required. A complete JSON string (single line) to control an airconditioner.
","
| Send a complete AC control command. These devices often require more complex commands and arguments, that can be \'carefully crafted\' and sent using this command.

| Documentation on how to craft these JSON commands can be found in this |IR_aircondition_commands| (external link)

| This JSON string does *not* have to be quoted if it contains spaces or commas, the entire text supplied is used as-is. It has to be valid JSON to be successfully processed, though.

| This command is only available if the Extended AC support is included in the build. (This command is shown on the Device Configuration page when included)
"

.. |IR_protocols_page| raw:: html

<a href="https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md" target="_blank">Protocols page at IRremoteESP8266</a>

.. |IR_aircondition_commands| raw:: html

<a href="https://github.com/crankyoldgit/IRremoteESP8266/wiki/Frequently-Asked-Questions#user-content-The_libraryexample_code_doesnt_understand_my_Air_Conditioner_remote_" target="_blank">IRremoteESP8266 F.A.Q. answer</a>
6 changes: 3 additions & 3 deletions docs/source/Reference/Command.rst
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,10 @@ P022 :ref:`P022_page`
.. .. include:: ../Plugin/P034_commands.repl
.. P035 :ref:`P035_page`
.. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
P035 :ref:`P035_page`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. .. include:: ../Plugin/P035_commands.repl
.. include:: ../Plugin/P035_commands.repl


P036 :ref:`P036_page`
Expand Down
34 changes: 22 additions & 12 deletions src/_P035_IRTX.ino
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
// #######################################################################################################
//
// Changelog:
// 2022-08-08, tonhuisman: Fix listProtocols()/listACProtocols() to ignore 1-character type names
// 2023-07-22, tonhuisman: Minor code improvements, show IRSENDAC command only in config page if included in build
// 2023-07-21, tonhuisman: Add 'Inverted output' option, as supported by the IRsend class.
// 2022-08-08, tonhuisman: Fix listProtocols()/listACProtocols() to ignore 1-character type names
// 2022-01-11, tonhuisman: Move all code and globals to PluginStructs/P035_data_struct to enable multi-instance use
// No previous changelog recorded.

Expand Down Expand Up @@ -75,34 +77,43 @@ boolean Plugin_035(uint8_t function, struct EventStruct *event, String& string)
}
case PLUGIN_WEBFORM_LOAD:
{
addFormCheckBox(F("Inverted output"), F("invert"), PCONFIG(0) == 1);

addRowLabel(F("Command"));
addHtml(F("IRSEND,[PROTOCOL],[DATA],[BITS optional],[REPEATS optional]<BR>BITS and REPEATS are optional and default to 0<BR/>"));
addHtml(F("IRSENDAC,{JSON formated AC command}"));
# ifdef P016_P035_Extended_AC
addHtml(F("IRSENDAC,{JSON formatted AC command}"));
# endif // ifdef P016_P035_Extended_AC

success = true;
break;
}

case PLUGIN_WEBFORM_SAVE:
{
PCONFIG(0) = isFormItemChecked(F("invert")) ? 1 : 0;
success = true;
break;
}

case PLUGIN_INIT:
{
initPluginTaskData(event->TaskIndex, new (std::nothrow) P035_data_struct(CONFIG_PIN1));
initPluginTaskData(event->TaskIndex, new (std::nothrow) P035_data_struct(CONFIG_PIN1, PCONFIG(0) == 1));
P035_data_struct *P035_data = static_cast<P035_data_struct *>(getPluginTaskData(event->TaskIndex));

if (nullptr == P035_data) {
return success;
if (nullptr != P035_data) {
success = P035_data->plugin_init(event);
}
success = P035_data->plugin_init(event);
break;
}

case PLUGIN_EXIT:
{
P035_data_struct *P035_data = static_cast<P035_data_struct *>(getPluginTaskData(event->TaskIndex));

if (nullptr == P035_data) {
return success;
if (nullptr != P035_data) {
success = P035_data->plugin_exit(event);
}
success = P035_data->plugin_exit(event);

break;
}
Expand All @@ -111,10 +122,9 @@ boolean Plugin_035(uint8_t function, struct EventStruct *event, String& string)
{
P035_data_struct *P035_data = static_cast<P035_data_struct *>(getPluginTaskData(event->TaskIndex));

if (nullptr == P035_data) {
return success;
if (nullptr != P035_data) {
success = P035_data->plugin_write(event, string);
}
success = P035_data->plugin_write(event, string);

break;
} // PLUGIN_WRITE END
Expand Down
33 changes: 18 additions & 15 deletions src/src/PluginStructs/P035_data_struct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// **************************************************************************/
// Constructor
// **************************************************************************/
P035_data_struct::P035_data_struct(int8_t gpioPin)
: _gpioPin(gpioPin) {}
P035_data_struct::P035_data_struct(int8_t gpioPin, bool inverted)
: _gpioPin(gpioPin), _inverted(inverted) {}

// **************************************************************************/
// Destructor
Expand All @@ -33,10 +33,10 @@ bool P035_data_struct::plugin_init(struct EventStruct *event) {
addLog(LOG_LEVEL_INFO, F("INIT: IR TX"));
addLog(LOG_LEVEL_INFO, F("IR lib Version: " _IRREMOTEESP8266_VERSION_STR));
# ifdef P035_DEBUG_LOG
addLog(LOG_LEVEL_INFO, String(F("Supported Protocols by IRSEND: ")) + listProtocols());
addLog(LOG_LEVEL_INFO, concat(F("Supported Protocols by IRSEND: "), listProtocols()));
# endif // ifdef P035_DEBUG_LOG
}
Plugin_035_irSender = new (std::nothrow) IRsend(_gpioPin);
Plugin_035_irSender = new (std::nothrow) IRsend(_gpioPin, _inverted);

if (Plugin_035_irSender != nullptr) {
Plugin_035_irSender->begin(); // Start the sender
Expand All @@ -57,7 +57,7 @@ bool P035_data_struct::plugin_init(struct EventStruct *event) {
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLog(LOG_LEVEL_INFO, F("INIT AC: IR TX"));
# ifdef P035_DEBUG_LOG
addLog(LOG_LEVEL_INFO, String(F("Supported Protocols by IRSENDAC: ")) + listACProtocols());
addLog(LOG_LEVEL_INFO, concat(F("Supported Protocols by IRSENDAC: "), listACProtocols()));
# endif // ifdef P035_DEBUG_LOG
}
Plugin_035_commonAc = new (std::nothrow) IRac(_gpioPin);
Expand Down Expand Up @@ -91,9 +91,9 @@ bool P035_data_struct::plugin_exit(struct EventStruct *event) {
bool P035_data_struct::plugin_write(struct EventStruct *event, const String& string) {
bool success = false;

String cmdCode = parseString(string, 1);
const String cmdCode = parseString(string, 1);

if (cmdCode.equalsIgnoreCase(F("IRSEND")) && (Plugin_035_irSender != nullptr)) {
if (equals(cmdCode, F("irsend")) && (Plugin_035_irSender != nullptr)) {
success = true;
enableIR_RX(false);

Expand All @@ -105,7 +105,7 @@ bool P035_data_struct::plugin_write(struct EventStruct *event, const String& str
}

# ifdef P016_P035_Extended_AC
else if (cmdCode.equalsIgnoreCase(F("IRSENDAC")) && (Plugin_035_commonAc != nullptr)) {
else if (equals(cmdCode, F("irsendac")) && (Plugin_035_commonAc != nullptr)) {
success = true;
enableIR_RX(false);
handle_AC_IRremote(parseStringToEnd(string, 2));
Expand Down Expand Up @@ -164,7 +164,8 @@ bool P035_data_struct::handle_AC_IRremote(const String& irData) {

if (error) { // Test if parsing succeeds.
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLog(LOG_LEVEL_INFO, String(F("IRTX: Deserialize Json failed: ")) + error.c_str());
String errorMsg(error.c_str());
addLog(LOG_LEVEL_INFO, concat(F("IRTX: Deserialize Json failed: "), errorMsg));
}
return false; // do not continue with sending the signal.
}
Expand All @@ -174,7 +175,7 @@ bool P035_data_struct::handle_AC_IRremote(const String& irData) {

if (!IRac::isProtocolSupported(st.protocol)) { // Check if we support the protocol
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLog(LOG_LEVEL_INFO, String(F("IRTX: Protocol not supported:")) + sprotocol);
addLog(LOG_LEVEL_INFO, concat(F("IRTX: Protocol not supported:"), sprotocol));
}
return false; // do not continue with sending of the signal.
}
Expand Down Expand Up @@ -244,7 +245,7 @@ bool P035_data_struct::handleRawRaw2Encoding(const String& cmd) {
bool raw = true;
String IrType = parseString(cmd, 2);

if (IrType.isEmpty()) { return false; }
if (IrType.isEmpty()) { return false; }

if (IrType.equalsIgnoreCase(F("RAW"))) {
raw = true;
Expand Down Expand Up @@ -493,10 +494,12 @@ bool P035_data_struct::addErrorTrue() {
// repeat: Nr. of times the message is to be repeated. (Not all protcols.)
// Returns:
// bool: Successfully sent or not.
bool P035_data_struct::sendIRCode(int const irtype,
uint64_t const code, char const *code_str, uint16_t bits,
uint16_t repeat) {
decode_type_t irType = (decode_type_t)irtype;
bool P035_data_struct::sendIRCode(const int irtype,
const uint64_t code,
const char *code_str,
uint16_t bits,
uint16_t repeat) {
decode_type_t irType = static_cast<decode_type_t>(irtype);
bool success = true; // Assume success.

repeat = std::max(IRsend::minRepeats(irType), repeat);
Expand Down
Loading

0 comments on commit 6c6a8d3

Please sign in to comment.