Tasmota/lib/IRremoteESP8266-2.6.0/examples/IRMQTTServer/IRMQTTServer.h

259 lines
11 KiB
C

/*
* Send & receive arbitrary IR codes via a web server or MQTT.
* Copyright David Conran 2016, 2017, 2018, 2019
*/
#ifndef EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
#define EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRsend.h>
#include <IRtimer.h>
#include <IRutils.h>
#include <IRac.h>
// ---------------- Start of User Configuration Section ------------------------
#ifndef MQTT_ENABLE
#define MQTT_ENABLE true // Whether or not MQTT is used at all.
#endif // MQTT_ENABLE
// ---------------------- Board Related Settings -------------------------------
// NOTE: Make sure you set your Serial Monitor to the same speed.
#define BAUD_RATE 115200 // Serial port Baud rate.
// GPIO the IR LED is connected to/controlled by. GPIO 4 = D2.
#define IR_LED 4 // <=- CHANGE_ME (optional)
// define IR_LED 3 // For an ESP-01 we suggest you use RX/GPIO3/Pin 7.
// GPIO the IR RX module is connected to/controlled by. e.g. GPIO 14 = D5.
// Comment this out to disable receiving/decoding IR messages entirely.
#define IR_RX 14 // <=- CHANGE_ME (optional)
#define IR_RX_PULLUP false
// --------------------- Network Related Settings ------------------------------
const uint16_t kHttpPort = 80; // The TCP port the HTTP server is listening on.
// Change to 'true'/'false' if you do/don't want these features or functions.
#define USE_STATIC_IP false // Change to 'true' if you don't want to use DHCP.
// We obtain our network config via DHCP by default but allow an easy way to
// use a static IP config.
#if USE_STATIC_IP
const IPAddress kIPAddress = IPAddress(10, 0, 1, 78);
const IPAddress kGateway = IPAddress(10, 0, 1, 1);
const IPAddress kSubnetMask = IPAddress(255, 255, 255, 0);
#endif // USE_STATIC_IP
// See: https://github.com/tzapu/WiFiManager#filter-networks for these settings.
#define HIDE_DUPLIATE_NETWORKS false // Should WifiManager hide duplicate SSIDs
// #define MIN_SIGNAL_STRENGTH 20 // Minimum WiFi signal stength (percentage)
// before we will connect.
// The unset default is 8%.
// (Uncomment to enable)
// ----------------------- HTTP Related Settings -------------------------------
#define FIRMWARE_OTA true // Allow remote update of the firmware via http.
// Less secure if enabled.
// Note: Firmware OTA is also disabled until
// a password is set.
#define HTML_PASSWORD_ENABLE false // Protect access to the HTML interface.
// Note: OTA update is always passworded.
// If you do not set a password, Firmware OTA updates will be blocked.
// ----------------------- MQTT Related Settings -------------------------------
#if MQTT_ENABLE
const uint32_t kMqttReconnectTime = 5000; // Delay(ms) between reconnect tries.
#define MQTT_ACK "sent" // Sub-topic we send back acknowledgements on.
#define MQTT_SEND "send" // Sub-topic we get new commands from.
#define MQTT_RECV "received" // Topic we send received IRs to.
#define MQTT_LOG "log" // Topic we send log messages to.
#define MQTT_LWT "status" // Topic for the Last Will & Testament.
#define MQTT_CLIMATE "ac" // Sub-topic for the climate topics.
#define MQTT_CLIMATE_CMND "cmnd" // Sub-topic for the climate command topics.
#define MQTT_CLIMATE_STAT "stat" // Sub-topic for the climate stat topics.
#define MQTTbroadcastInterval 10 * 60 // Seconds between rebroadcasts
#define QOS 1 // MQTT broker should queue up any unreceived messages for us
// #define QOS 0 // MQTT broker WON'T queue up messages for us. Fire & Forget.
#endif // MQTT_ENABLE
// ------------------------ IR Capture Settings --------------------------------
// Let's use a larger than normal buffer so we can handle AirCon remote codes.
const uint16_t kCaptureBufferSize = 1024;
#if DECODE_AC
// Some A/C units have gaps in their protocols of ~40ms. e.g. Kelvinator
// A value this large may swallow repeats of some protocols
const uint8_t kCaptureTimeout = 50; // Milliseconds
#else // DECODE_AC
// Suits most messages, while not swallowing many repeats.
const uint8_t kCaptureTimeout = 15; // Milliseconds
#endif // DECODE_AC
// Ignore unknown messages with <10 pulses (see also REPORT_UNKNOWNS)
const uint16_t kMinUnknownSize = 2 * 10;
#define REPORT_UNKNOWNS false // Report inbound IR messages that we don't know.
#define REPORT_RAW_UNKNOWNS false // Report the whole buffer, recommended:
// MQTT_MAX_PACKET_SIZE of 1024 or more
// ------------------------ Advanced Usage Only --------------------------------
// Change if you need multiple independent send gpio/topics.
const uint8_t gpioTable[] = {
IR_LED, // Default GPIO. e.g. ir_server/send or ir_server/send_0
// Uncomment the following as needed.
// NOTE: Remember to disable DEBUG if you are using one of the serial pins.
// 5, // GPIO 5 / D1 e.g. ir_server/send_1
// 14, // GPIO 14 / D5 e.g. ir_server/send_2
// 16, // GPIO 16 / D0 e.g. ir_server/send_3
};
#define KEY_PROTOCOL "protocol"
#define KEY_MODEL "model"
#define KEY_POWER "power"
#define KEY_MODE "mode"
#define KEY_TEMP "temp"
#define KEY_FANSPEED "fanspeed"
#define KEY_SWINGV "swingv"
#define KEY_SWINGH "swingh"
#define KEY_QUIET "quiet"
#define KEY_TURBO "turbo"
#define KEY_LIGHT "light"
#define KEY_BEEP "beep"
#define KEY_ECONO "econo"
#define KEY_SLEEP "sleep"
#define KEY_CLOCK "clock"
#define KEY_FILTER "filter"
#define KEY_CLEAN "clean"
#define KEY_CELSIUS "use_celsius"
// HTML arguments we will parse for IR code information.
#define KEY_TYPE "type" // KEY_PROTOCOL is also checked too.
#define KEY_CODE "code"
#define KEY_BITS "bits"
#define KEY_REPEAT "repeats"
// Text for Last Will & Testament status messages.
const char* kLwtOnline = "Online";
const char* kLwtOffline = "Offline";
const uint8_t kHostnameLength = 30;
const uint8_t kPortLength = 5; // Largest value of uint16_t is "65535".
const uint8_t kUsernameLength = 15;
const uint8_t kPasswordLength = 20;
// -------------------------- Debug Settings -----------------------------------
// Disable debug output if any of the IR pins are on the TX (D1) pin.
// Note: This is a crude method to catch the common use cases.
// See `isSerialGpioUsedByIr()` for the better method.
#if (IR_LED != 1 && IR_RX != 1)
#ifndef DEBUG
#define DEBUG true // Change to 'false' to disable all serial output.
#endif // DEBUG
#else // (IR_LED != 1 && IR_RX != 1)
#undef DEBUG
#define DEBUG false
#endif
// ----------------- End of User Configuration Section -------------------------
// Constants
#define _MY_VERSION_ "v1.0.0"
const uint8_t kSendTableSize = sizeof(gpioTable);
// JSON stuff
// Name of the json config file in SPIFFS.
const char* kConfigFile = "/config.json";
const char* kMqttServerKey = "mqtt_server";
const char* kMqttPortKey = "mqtt_port";
const char* kMqttUserKey = "mqtt_user";
const char* kMqttPassKey = "mqtt_pass";
const char* kMqttPrefixKey = "mqtt_prefix";
const char* kHostnameKey = "hostname";
const char* kHttpUserKey = "http_user";
const char* kHttpPassKey = "http_pass";
#if MQTT_ENABLE
const uint32_t kBroadcastPeriodMs = MQTTbroadcastInterval * 1000; // mSeconds.
const uint32_t kStatListenPeriodMs = 5 * 1000; // mSeconds
void mqttCallback(char* topic, byte* payload, unsigned int length);
String listOfCommandTopics(void);
void handleSendMqttDiscovery(void);
void subscribing(const String topic_name);
void unsubscribing(const String topic_name);
void mqttLog(const String mesg);
bool reconnect(void);
void receivingMQTT(String const topic_name, String const callback_str);
void callback(char* topic, byte* payload, unsigned int length);
void sendMQTTDiscovery(const char *topic);
void doBroadcast(TimerMs *timer, const uint32_t interval,
const commonAcState_t state, const bool retain,
const bool force);
#endif // MQTT_ENABLE
bool isSerialGpioUsedByIr(void);
void debug(const char *str);
void saveWifiConfigCallback(void);
void saveWifiConfig(void);
void loadWifiConfigFile(void);
String msToHumanString(uint32_t const msecs);
String timeElapsed(uint32_t const msec);
String timeSince(uint32_t const start);
String listOfSendGpios(void);
bool hasUnsafeHTMLChars(String input);
String htmlMenu(void);
void handleRoot(void);
String addJsReloadUrl(const String url, const uint16_t timeout_s,
const bool notify);
void handleExamples(void);
String boolToString(const bool value);
String opmodeToString(const stdAc::opmode_t mode);
String fanspeedToString(const stdAc::fanspeed_t speed);
String swingvToString(const stdAc::swingv_t swingv);
String swinghToString(const stdAc::swingh_t swingh);
String htmlSelectBool(const String name, const bool def);
String htmlSelectProtocol(const String name, const decode_type_t def);
String htmlSelectModel(const String name, const int16_t def);
String htmlSelectMode(const String name, const stdAc::opmode_t def);
String htmlSelectFanspeed(const String name, const stdAc::fanspeed_t def);
String htmlSelectSwingv(const String name, const stdAc::swingv_t def);
String htmlSelectSwingh(const String name, const stdAc::swingh_t def);
void handleAirCon(void);
void handleAirConSet(void);
void handleAdmin(void);
void handleInfo(void);
void handleReset(void);
void handleReboot(void);
bool parseStringAndSendAirCon(IRsend *irsend, const uint16_t irType,
const String str);
uint16_t countValuesInStr(const String str, char sep);
uint16_t * newCodeArray(const uint16_t size);
#if SEND_GLOBALCACHE
bool parseStringAndSendGC(IRsend *irsend, const String str);
#endif // SEND_GLOBALCACHE
#if SEND_PRONTO
bool parseStringAndSendPronto(IRsend *irsend, const String str,
uint16_t repeats);
#endif // SEND_PRONTO
#if SEND_RAW
bool parseStringAndSendRaw(IRsend *irsend, const String str);
#endif // SEND_RAW
void handleIr(void);
void handleNotFound(void);
void setup_wifi(void);
void init_vars(void);
void setup(void);
void loop(void);
uint64_t getUInt64fromHex(char const *str);
bool sendIRCode(IRsend *irsend, int const ir_type,
uint64_t const code, char const * code_str, uint16_t bits,
uint16_t repeat);
bool sendInt(const String topic, const int32_t num, const bool retain);
bool sendBool(const String topic, const bool on, const bool retain);
bool sendString(const String topic, const String str, const bool retain);
bool sendFloat(const String topic, const float_t temp, const bool retain);
commonAcState_t updateClimate(commonAcState_t current, const String str,
const String prefix, const String payload);
bool cmpClimate(const commonAcState_t a, const commonAcState_t b);
bool sendClimate(const commonAcState_t prev, const commonAcState_t next,
const String topic_prefix, const bool retain,
const bool forceMQTT, const bool forceIR);
#endif // EXAMPLES_IRMQTTSERVER_IRMQTTSERVER_H_