Okay, I’ve done as you’ve suggested.
I’ve changed up the wemos code to eliminate one of the fans to minimize confusion. I reformatted some of it as well to try and make it more legible (I’m still a novice).
/*
* RF_Transmitter
* a Home-Automation-friendly ESP8266-based MQTT Hunter Ceiling Fan RF Controller
* 2020 essaysee
*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "config.h"
boolean recordedSignal_fanlow2[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0};
boolean recordedSignal_fanmed2[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0};
boolean recordedSignal_fanhigh2[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0};
boolean recordedSignal_fanoff2[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0};
boolean recordedSignal_lightoffon2[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0};
int a;
// Mapping NodeMCU Ports to Arduino GPIO Pins
// THIS IS ALL YOU NEED TO CHANGE IN THIS FILE
#define D0 16
#define D2 15
#define D3 0
#define D4 2
#define D5 14
#define D6 12
#define D7 13
#define D8 15
#define WIFI_SSID "wifi name"
#define WIFI_PASSWORD "wifi password"
#define MQTT_BROKER "HA installation / MQTT"
#define MQTT_CLIENTID "RF_Transmitter"
#define MQTT_USERNAME "rf"
#define MQTT_PASSWORD "rf"
#define BEDROOM2_ALIAS "Guest Bedroom 2"
#define MQTT_ROOM2_FAN_ACTION_TOPIC "bedroom/fan/2/FanSpeed"
#define MQTT_ROOM2_FAN_STATUS_TOPIC "bedroom/fan/2/status"
#define MQTT_ROOM2_LIGHT_ACTION_TOPIC "bedroom/light/2/action"
#define MQTT_ROOM2_LIGHT_STATUS_TOPIC "bedroom/light/2/status"
#define TRANSMITTER_PIN D2
#define RECEIVER_PIN D8
//THAT WAS ALL YOU NEEDED TO CHANGE IN THE FILE
const char* ssid = WIFI_SSID;
const char* password = WIFI_PASSWORD;
//const boolean static_ip = STATIC_IP;
//IPAddress ip(IP);
//IPAddress gateway(GATEWAY);
//IPAddress subnet(SUBNET);
const char* mqtt_broker = MQTT_BROKER;
const char* mqtt_clientId = MQTT_CLIENTID;
const char* mqtt_username = MQTT_USERNAME;
const char* mqtt_password = MQTT_PASSWORD;
const char* bedroom2_alias = BEDROOM2_ALIAS;
const char* mqtt_room2_fan_action_topic = MQTT_ROOM2_FAN_ACTION_TOPIC;
const char* mqtt_room2_fan_status_topic = MQTT_ROOM2_FAN_STATUS_TOPIC;
const char* mqtt_room2_light_action_topic = MQTT_ROOM2_LIGHT_ACTION_TOPIC;
const char* mqtt_room2_light_status_topic = MQTT_ROOM2_LIGHT_STATUS_TOPIC;
const int transmitter_pin = TRANSMITTER_PIN;
const int receiver_pin = RECEIVER_PIN;
String availabilityBase = MQTT_CLIENTID;
String availabilitySuffix = "/availability";
String availabilityTopicStr = availabilityBase + availabilitySuffix;
const char* availabilityTopic = availabilityTopicStr.c_str();
const char* birthMessage = "online";
const char* lwtMessage = "offline";
WiFiClient espClient;
PubSubClient client(espClient);
// Wifi setup function
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.print(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
// if (static_ip) {
// WiFi.config(ip, gateway, subnet);
// }
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print(" WiFi connected - IP address: ");
Serial.println(WiFi.localIP());
}
// Callback when MQTT message is received; calls triggerBedroomAction(), passing topic and payload as parameters
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
String topicToProcess = topic;
payload[length] = '\0';
String payloadToProcess = (char*)payload;
triggerBedroomAction(topicToProcess, payloadToProcess);
}
// Function that publishes birthMessage
void publish_birth_message() {
// Publish the birthMessage
Serial.print("Publishing birth message \"");
Serial.print(birthMessage);
Serial.print("\" to ");
Serial.print(availabilityTopic);
Serial.println("...");
client.publish(availabilityTopic, birthMessage, true);
}
// Function called by callback() when a message is received
// Passes the message topic as the "requestedRoom" parameter and the message payload as the "requestedAction" parameter
// THIS JUST PRINTS OUT THE ACTION AND MESSAGE RECEIVED VIA SERIAL CONNECTION
// KEEP AN EYE OUT FOR THE transmitRFsignal ACTION
void triggerBedroomAction(String requestedRoom, String requestedAction) {
if (requestedRoom == mqtt_room2_fan_action_topic && requestedAction == "1") {
Serial.print("Setting ");
Serial.print(bedroom2_alias);
Serial.println("'s fan speed to low!");
{
for (a = 0; a < 8; a++) {
for (int i = 0; i < sizeof(recordedSignal_fanlow2) - 1; i++) {
digitalWrite(transmitter_pin, recordedSignal_fanlow2[i]);
delayMicroseconds(393.9);
}
delayMicroseconds(9000); }
delay(800);
}
client.publish(mqtt_room2_fan_status_topic, "1");
}
else if (requestedRoom == mqtt_room2_fan_action_topic && requestedAction == "2") {
Serial.print("Setting ");
Serial.print(bedroom2_alias);
Serial.println("'s fan speed to medium!");
{
for (a = 0; a < 8; a++) {
for (int i = 0; i < sizeof(recordedSignal_fanmed2) - 1; i++) {
digitalWrite(transmitter_pin, recordedSignal_fanmed2[i]);
delayMicroseconds(393.9);
}
delayMicroseconds(9000);
}
delay(800);
}
client.publish(mqtt_room2_fan_status_topic, "2");
}
else if (requestedRoom == mqtt_room2_fan_action_topic && requestedAction == "3") {
Serial.print("Setting ");
Serial.print(bedroom2_alias);
Serial.println("'s fan speed to high!");
{
for (a = 0; a < 8; a++) {
for (int i = 0; i < sizeof(recordedSignal_fanhigh2) - 1; i++) {
digitalWrite(transmitter_pin, recordedSignal_fanhigh2[i]);
delayMicroseconds(393.9);
}
delayMicroseconds(9000);
}
delay(800);
}
client.publish(mqtt_room2_fan_status_topic, "3");
}
else if (requestedRoom == mqtt_room2_fan_action_topic && requestedAction == "0") {
Serial.print("Setting ");
Serial.print(bedroom2_alias);
Serial.println("'s fan off!");
{
for (a = 0; a < 8; a++) {
for (int i = 0; i < sizeof(recordedSignal_fanoff2) - 1; i++) {
digitalWrite(transmitter_pin, recordedSignal_fanoff2[i]);
delayMicroseconds(393.9);
}
delayMicroseconds(9000);
}
delay(800);
}
client.publish(mqtt_room2_fan_status_topic, "0");
}
else if (requestedRoom == mqtt_room2_light_action_topic && requestedAction == "off") {
Serial.print("Changing ");
Serial.print(bedroom2_alias);
Serial.println("'s light status!");
{
for (a = 0; a < 8; a++) {
for (int i = 0; i < sizeof(recordedSignal_lightoffon2) - 1; i++) {
digitalWrite(transmitter_pin, recordedSignal_lightoffon2[i]);
delayMicroseconds(393.9);
}
delayMicroseconds(9000);
}
delay(600);
}
client.publish(mqtt_room2_light_status_topic, "off");
}
else if (requestedRoom == mqtt_room2_light_action_topic && requestedAction == "on") {
Serial.print("Changing ");
Serial.print(bedroom2_alias);
Serial.println("'s light status!");
{
for (a = 0; a < 8; a++) {
for (int i = 0; i < sizeof(recordedSignal_lightoffon2) - 1; i++) {
digitalWrite(transmitter_pin, recordedSignal_lightoffon2[i]);
delayMicroseconds(393.9);
}
delayMicroseconds(9000);
}
delay(600);
}
client.publish(mqtt_room2_light_status_topic, "on");
}
else { Serial.println("Unrecognized action payload... taking no action!");
}
}
//ENDS THE ACTION OF WRITING IN SERIAL WHAT WAS RECEIVED AND WHAT IT WAS TOLD TO DO
// Function that runs in loop() to connect/reconnect to the MQTT broker, and publish the current door statuses on connect
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect(mqtt_clientId, mqtt_username, mqtt_password, availabilityTopic, 0, true, lwtMessage)) {
Serial.println("Connected!");
// Publish the birth message on connect/reconnect
publish_birth_message();
// Subscribe to the action topics to listen for action messages
Serial.print("Subscribing to ");
Serial.print(mqtt_room2_fan_action_topic);
Serial.println("...");
client.subscribe(mqtt_room2_fan_action_topic);
Serial.print("Subscribing also to ");
Serial.print(mqtt_room2_light_action_topic);
Serial.println("...");
client.subscribe(mqtt_room2_light_action_topic);
Serial.println("I am all subscribed.");
}
else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
// Setup the output and input pins used in the sketch
// Set the lastStatusValue variables to the state of the status pins at setup time
// Setup Door 1 pins
pinMode(transmitter_pin, OUTPUT);
// Setup serial output, connect to wifi, connect to MQTT broker, set MQTT message callback
Serial.begin(115200);
delay(2);
Serial.println("Starting RF transmitter for Hunter Fans...");
setup_wifi();
client.setServer(mqtt_broker, 1883);
client.setCallback(callback);
}
void loop() {
// Connect/reconnect to the MQTT broker and listen for messages
if (!client.connected()) {
reconnect();
}
client.loop();
}
fan.yaml :
- platform: mqtt
name: "Guest Bedroom 2 Fan"
state_topic: "bedroom/fan/2/FanSpeed"
speed_state_topic: "bedroom/fan/2/FanSpeed"
state_value_template: >
{% if value_json.FanSpeed is defined %}
{% if value_json.FanSpeed == 0 -%}0{%- elif value_json.FanSpeed > 0 -%}4{%- endif %}
{% else %}
{% if states.fan.guest_bedroom_2_fan.state == 'off' -%}0{%- elif states.fan.guest_bedroom_2_fan.state == 'on' -%}4{%- endif %}
{% endif %}
speed_value_template: "{{ value_json.FanSpeed }}"
availability:
- topic: "RF_Transmitter/availability"
payload_available: Online
payload_not_available: Offline
speed_command_topic: "bedroom/fan/2/FanSpeed"
payload_low_speed: "1"
payload_medium_speed: "2"
payload_high_speed: "3"
command_topic: "bedroom/fan/2/FanSpeed"
payload_off: "0"
payload_on: "4"
qos: 0
retain: false
speeds:
- off
- low
- medium
- high
I know you’re going to point out that my status topci doesn’t quite align with conventional coding too, I changed this to “…/RESULT” as well in my testing. I’m open to any suggestions, I just wanted to point out I am aware the status topic matches the action topic.
The ‘off’ button does not seem to send any command to the wemos; no payload is sent over MQTT.
Also the buttons still don’t seem to change upon changing fan speed.
Seen here in this image, I’ve selected “M” or payload 2:
And the serial output from hitting button “M” (payload 2):
Payloads are all being received, and I can confirm that the publish is working, as you can see that the light status changes.
In the following image, I have clicked on all buttons, changing the status (including the off button).
I guess one of my questions also is "what is the necessity for payload 4?
EDIT: I found your thread trying to work out your jinja:
How does this implement into the TASMOTA fans? My fan’s remote only has 5 buttons:
Low
Medium
High
Off
Light (off/on)
I changed the speed state topic to match the javascript “FanSpeed” also to try to narrow down the issue/solution.
I’m not real strong in javascript but I imagine the js in the fan.yaml, says that any FanSpeed payload higher than 0 should change the icon color status.
I imagine in your fan-control-entity-row.js it says that if the button is pressed, the color of the button changes too, but that doesn’t seem to work for me.
Should I be publishing payload 4 in addition to any of my fan speeds 1,2,3?
Would that tell the card that the fan is on?
EDIT: I tried publishing payload 4 as well at the same time, this was a novice experimet, but I now believe I understand what you were achieving in your jinja code (I found an old link you were working on in 2018)
oops, I forgot to mention that I do have an ‘else’ statement that should serial print if it receives a payload it is not familiar with.
Any help or instruction greatly appreciated! I’m just trying to get this to work like you have and I think there may be some things still I don’t quite fully understand that are influencing my unexpected results.