Has anyone used one of these or is it possible to integrate this transceiver into ESPhome.
A quick search on ESPhome does not show anything.
Thanks
Has anyone used one of these or is it possible to integrate this transceiver into ESPhome.
A quick search on ESPhome does not show anything.
Thanks
Are you sure this does what you think it does?
They seem to work in Sender/Receiver pairs, with whatever you send on the sender side through the UART interface received on the other side…
It won’t replace a 433MHz remote.
Correct. Or they can also be used in a multicast or mesh configuration. Basically they’re transceiver chips providing only the RF layer and transparent data transport. You will have to write your own protocol on top of that (error correction, retransmit, Node IDs, routing, etc).
They’re excellent devices btw, the range is really good.
Yes I know, but i’m just trying to get a simple 2 way 433mhz link for a reed switch to trigger a relay. The reason I chose the HC-12 was its range and performance.
However, it seems like a mission to work with.
Still have not had any luck getting it up and running on my esp8266 D1 mini board
You could go with a LoRa transceiver, you would get a very good range, and there are boards combining already an ESP32 and LoRa transceiver.
Thanks, can you please give me some examples of some LoRa board that are compatible with esphome?
Thanks
i am using this, actually quite easy once configured and delimited string that is sent:
example of single message: “n1:n2:n3;”
n1 - device id
n2 - sensor id on this device
n3 - sensor data
message parts delimied with :
end of message announced with ;
these are transceivers, so easy to think of some sort of simple protocol to add a message id and confirming that message was received.
from the device in remote location i am transmitting info like:
transmitting part (called from various places as scripts):
script:
- id: transmitt_info_boot_complete
mode: restart
then:
- uart.write:
id: uart_bus
data: !lambda |-
std::string mss = String( "1:0:1;" ).c_str();
return std::vector<unsigned char>(mss.begin(), mss.end());
- id: transmitt_info_interval_update
mode: restart
then:
- uart.write:
id: uart_bus
data: !lambda |-
std::string mss = String( "1:0:2;" ).c_str();
return std::vector<unsigned char>(mss.begin(), mss.end());
- id: transmitt_info_door_sensor_update
mode: restart
then:
- uart.write:
id: uart_bus
data: !lambda |-
std::string mss = String( "1:0:3;" ).c_str();
return std::vector<unsigned char>(mss.begin(), mss.end());
- id: transmitt_dht11
mode: restart
then:
# data: "device_id_hc12:sensor_id:sensor_data;"
# dht11 temperature & humidity sensor
- uart.write:
id: uart_bus
data: !lambda |-
std::string mss = ( "1:1:" + String(id(dht11_temp).state) + "!" + String(id(dht11_hum).state) + ";" ).c_str();
return std::vector<unsigned char>(mss.begin(), mss.end());
# door sensor
- id: transmitt_door_state
mode: restart
then:
- uart.write:
id: uart_bus
data: !lambda |-
std::string mss = String("1:2:1;").c_str();
if ( id(contracton).state == false ) {
mss = String("1:2:0;").c_str();
}
return std::vector<unsigned char>(mss.begin(), mss.end());
- id: transmitt_uptime
mode: restart
then:
- uart.write:
id: uart_bus
data: !lambda |-
std::string mss = ( "1:3:" + String(id(device_uptime).state) + ";" ).c_str();
return std::vector<unsigned char>(mss.begin(), mss.end());
as you can see, the door sensor sends state 0 or 1, and is listed as a sensor 2 on a device 1
dht11 it additionally delimit temperature and humity with an !
“1:1:dht11_temp!dht11_hum;”
as you can see i use a lot of datatype converting, careless use of strings etc, but im not an expert on c, so probably better way to do this… it does work however flawlesly for about a year now, so not that heavy for esp8266 i am runnings this on, i suppose…
and receiving part (the hub that receives all my “clients” data - even though technically all HC12 devices are transceivers, as mentioned):
uart:
id: uart_bus
rx_pin: GPIO6
tx_pin: GPIO7
baud_rate: 9600
debug:
direction: BOTH
dummy_receiver: true
after:
delimiter: ";"
sequence:
- lambda: |-
UARTDebug::log_string(direction, bytes);
int deviceUID=0;
int sensorUID=0;
String sensor_data="";
std::string str(bytes.begin(), bytes.end());
ESP_LOGD("HC12", "received something...");
if (sscanf(str.c_str(), "%d:%d:%s", &deviceUID, &sensorUID, &sensor_data ) == 3 ) {
if(deviceUID==1) {
ESP_LOGD("HC12", "received device_1 data");
// sensorUID=1 is dht11
if ( sensorUID == 1 ) {
float sensor_temp=0;
float sensor_hum=0;
if (sscanf(sensor_data.c_str(), "%f!%f", &sensor_temp, &sensor_hum ) == 2 )
{
id(device1_temp).publish_state(sensor_temp);
id(device1_hum).publish_state(sensor_hum);
ESP_LOGD("HC12", "received device1 temperature and humidity");
}
}
// sensorUID=2 is door sensor
if ( sensorUID == 2 ) {
int sensor_door=-1;
if (sscanf(sensor_data.c_str(), "%d", &sensor_door) == 1 )
{
ESP_LOGD("HC12", "received device1 door");
if (sensor_door==1) {
id(device1_door).publish_state(true);
ESP_LOGD("HC12", "received device1 door - ON");
}
if (sensor_door==0) {
id(device1_door).publish_state(false);
ESP_LOGD("HC12", "received device1 door - OFF");
}
}
}
// sensorUID=3 uptime
if ( sensorUID == 3 ) {
int sensor_uptime=-1;
if (sscanf(sensor_data.c_str(), "%d", &sensor_uptime) == 1 )
{
ESP_LOGD("HC12", "received device1 uptime");
id(device1_uptime).publish_state(sensor_uptime);
}
}
// sensorUID=4 is cpu temp
if ( sensorUID == 4 ) {
float sensor_temp=0;
if (sscanf(sensor_data.c_str(), "%f", &sensor_temp) == 1 )
{
id(device1_cpu_temp).publish_state(sensor_temp);
ESP_LOGD("HC12", "received device1 device cpu temperature");
}
}
// sensorUID=0 info
if ( sensorUID == 0 ) {
int device_info=-1;
if (sscanf(sensor_data.c_str(), "%d", &device_info) == 1 )
{
ESP_LOGD("HC12", "received device info");
if (device_info==1) {
id(device1_device_info).publish_state("boot_complete");
ESP_LOGD("HC12", "received device1 info - boot complete");
}
if (device_info==2) {
id(device1_device_info).publish_state("interval_update");
ESP_LOGD("HC12", "received device1 info - interval update");
}
if (device_info==3) {
id(device1_device_info).publish_state("door_sensor_update");
ESP_LOGD("HC12", "received device1 info - door sensor update");
}
}
}
}
and on properly recognized string, it publishes data to the local “hub” sensors, from where HA reads it through wifi
i think it would work reliably in my scenario with using strings alltogether, instead of numering for ids of devices or sensors - that would help readability of the code, but would probably be more prone for intereferences and increase the length of the transmission itself
This is exactly what I need but I struggle with yaml files. I cant compile the receiver file get errors in the Lambda section any chance you could post the complete ymal file
Yea, no problem
this is simplified version
so if a recognizable transmission is received - a led will flash, and a HUB will answer with the OTA status for clients (client is waiting for an answer some time, and if receives OTA mode - will fire up WiFi and try to connect
one thing to notice - if the HC21 transmitted string was too long - it was forcing my HUB to reboot with an overflow message, i added the
rx_buffer_size: 1024
however this does not seem to help - so just in case, start with short strings to check how does that work for you
substitutions:
device_name: hub-hc12-test
esphome:
name: ${device_name}
friendly_name: ${device_name}
esp32:
board: lolin32
framework:
type: arduino
logger:
api:
encryption:
key: "syk******************G1y0gpf5gi0="
ota:
password: "52b***********64e7"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "*******-Hc12-Test"
password: "ro********R"
captive_portal:
web_server:
port: 80
text_sensor:
- platform: template
name: "Lily_1 wakeup reason"
id: lily_1_wakeup_reason
sensor:
- platform: uptime
name: "uptime"
id: "device_uptime"
update_interval: 1min
entity_category: "diagnostic"
- platform: wifi_signal # Reports the WiFi signal strength/RSSI in dB
name: "WiFi dB"
id: wifi_signal_db
update_interval: 1min
entity_category: "diagnostic"
- platform: copy # Reports the WiFi signal strength in %
source_id: wifi_signal_db
name: "WiFi %"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "%"
entity_category: "diagnostic"
device_class: ""
# HC12 sensors data
- platform: template
name: "Lilly_1 Temperature"
id: "lilly_1_temp"
unit_of_measurement: "°C"
device_class: "temperature" # https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes
state_class: "measurement"
accuracy_decimals: 1
- platform: template
name: "Lilly_1 Humidity"
id: "lilly_1_hum"
unit_of_measurement: "%"
device_class: "humidity"
state_class: "measurement"
accuracy_decimals: 0
- platform: template
name: "Lilly_1 Pressure"
id: "lilly_1_press"
unit_of_measurement: "hPa"
device_class: "pressure"
state_class: "measurement"
accuracy_decimals: 0
light:
- platform: status_led
id: light_status_led
name: "status led"
pin:
number: GPIO22
inverted: true
switch:
- platform: restart
name: "Restart"
- platform: template
name: "OTA announce"
id: switch_ota_announce
optimistic: true
turn_on_action:
then:
- script.execute: transmit_OTA_on
turn_off_action:
then:
- script.execute: transmit_OTA_off
uart:
id: uart_bus
rx_pin: GPIO23
tx_pin: GPIO19
baud_rate: 9600
rx_buffer_size: 1024
debug:
direction: BOTH
dummy_receiver: true
after:
delimiter: ";"
sequence:
- light.turn_on: light_status_led
- lambda: |-
UARTDebug::log_string(direction, bytes);
int device_id = 0;
int wakeup_reason = -1;
String payload_data="";
std::string str(bytes.begin(), bytes.end());
if (sscanf(str.c_str(), "%d:%d:%s", &device_id, &wakeup_reason, &payload_data ) == 3 ) {
ESP_LOGD("HC12", str.c_str() );
String response_payload = String( "0:" + String(device_id) + "!" + String(id(switch_ota_announce).state) + ";" ).c_str(); // respond to the device immidiately
id(transmit_rf)->execute(response_payload.c_str() );
if (device_id == 1 ) {
//if (sscanf(payload_data.c_str(), "%d;", &wakeup_reason ) == 1 ) {
ESP_LOGD("HC12", payload_data.c_str() );
if (wakeup_reason==0) { id(lily_1_wakeup_reason).publish_state("RESET"); }
if (wakeup_reason==0) { id(lily_1_wakeup_reason).publish_state("RESET_POST"); }
if (wakeup_reason==2) { id(lily_1_wakeup_reason).publish_state("PIR"); }
if (wakeup_reason==2) { id(lily_1_wakeup_reason).publish_state("PIR_POST"); }
if (wakeup_reason==4) { id(lily_1_wakeup_reason).publish_state("TIMER"); }
if (wakeup_reason==4) { id(lily_1_wakeup_reason).publish_state("TIMER_POST"); }
float sensor_temp=0;
int sensor_hum=0;
int sensor_press=0;
if (sscanf(payload_data.c_str(), "%f!%d!%d", &sensor_temp, &sensor_hum, &sensor_press ) == 3 ) {
id(lilly_1_temp).publish_state(sensor_temp);
id(lilly_1_hum).publish_state(sensor_hum);
id(lilly_1_press).publish_state(sensor_press);
}
}
}
- delay: 100ms
- light.turn_off: light_status_led
script:
- id: transmit_rf
parameters:
message_payload: std::string
mode: restart
then:
- uart.write:
id: uart_bus
data: !lambda |-
ESP_LOGD("HC12", message_payload.c_str() );
std::string mss = message_payload;
return std::vector<unsigned char>(mss.begin(), mss.end());
- id: transmit_OTA_on
mode: restart
then:
- lambda: |-
String payload = String( "0:0!1;" ).c_str();
id(transmit_rf)->execute(payload.c_str() );
- id: transmit_OTA_off
mode: restart
then:
- lambda: |-
String payload = String( "0:0!0;" ).c_str();
id(transmit_rf)->execute(payload.c_str() );
anyway the important part:
the clients transmits a string
device_id:wakeup_reason:payload_data;
paylaod_data is next split into bme_temperature!bme_humidity (you could make the split all at once if you prefer, for me its a bit more readable this way)
the HUB first splits it to the parts:
“%d:%d:%s”, &device_id, &wakeup_reason, &payload_data
this is the test HUB (receiver) history:
besides BME280 sensor i have attached a PIR sensor
i only differentiate 3 wakeup reasons - RESET, TIMER and PIR
after each wake up - a timer deep sleep will schedule an hour sleep - unless PIR sensor wakes it up
as you can also see in the code - i have 2 statuses for each wake up reason - updating second just after the first one - that way i know when exactly and how often a PIR sensor woke up the device for example:
as you can see i should sleep a little more…
Is it possible to add sensor signal strength?
Yes it is!