What are the options for longer range wireless communication?

Doesn’t take 6 months :wink: You can have something up and running in a few days if you have prior dev experience.

At the most basic level, with only direct routing (no mesh) and without CCA, a transmission packet would look like this:

[0] Sync sequence
[1] Destination node address
[2] Source node address
[3] Packet ID and retry counter
[4] Packet type
[5] Payload length
[6] Payload
[7] Checksum
[8] Packet end identifier

To keep it easy, each data entry can be a single byte. That also keeps the packet small and less likely to be corrupted. The sync sequence at the beginning is a unique bitcode that won’t appear anywhere else in the data stream. This is used by the receiver to determine when a packet starts. The packet ID and retry counts are used by the receiver to determine if the same packet was received multiple times (maybe because the sender didn’t receive the ACK and resent it by mistake) and to sort out duplicates. The retry counter can also be used to create some basic transmission quality metrics and see how reliable your signal is (how many retries the link needs on average until it gets the data through). The checksum is obvious here.

It’s important to keep in mind that you’re dealing with an unreliable transmission mode here. Packets can be corrupted, you can only get partial packets, etc. Your code needs to deal with this.

Say you have a temperature sensor that wants to send the current temperature every 10 minutes. So it starts by packing up its payload (the temperature) and encapsulates it into a packet. It will set its own node ID into the source field. It also sets the destination node address to 0, because the recipient of the message is the master controller node. All other fields are generated accordingly and the entire encapsulated packet is sent as raw data out into the air.

All nodes will receive and decode the packet. But only the node with a matching destination ID will process it further. Nodes that are not the intended recipient will discard it. The recipient node will process it, check the CRC, etc. If all is good, it will send an ACK packet. The structure is exactly the same, only with a special packet type identifying it as an ACK packet without payload. This time the roles are reversed – the source address is 0 (the packet comes from the master controller) and the destination is the ID of the temperature sensor. The latter will receive the ACK packet and can now be sure its temperature data was well received by the recipient and it was not corrupted.

If the original sender node (the temperature sensor) does not receive the ACK packet within a given timeframe, it will try to resend the packet a predefined number of times before it gives up.

On the receiver side, the payload is extracted from the decoded packet, processed and repackaged into an MQTT message to HA. A queue is used for incoming messages to handle heavy traffic situations.

nilux:

nilux:

Do you have a public repo?

Nah, not for this. Honestly, handling support for this would be too time consuming.

nilux:

nilux:

I was looking for a readily implemented communication protocol that a dummy like me could use, but now I’m beginning to understand something, and it’s intriguing.

There are existing libraries that do this (and more), like RadioHead or MySensors. I never really tried them though, I thought it more challenging and fun to build my own.

nilux:

nilux:

If indeed the HC-12 just wirelessly transmits whatever it receives through serial, then shouldn’t that part be easy to implement in ESPHome using the uart_bus?

I suppose ? I never used ESPHome, so I don’t know how it supports UARTs. But yeah, if you only have a point to point link, then it’s just a simple serial connection. It can still be corrupted though, so you should at least add a checksum. You can have multiple independent point to point links on separate channels. Just note that the HC-12 supports a lot of channels that are beyond the unlicensed frequencies of the 433MHz band.