Skip to content

Adding a new remote device and writing the decoder C code

Christian W. Zuckschwerdt edited this page Mar 1, 2023 · 8 revisions

Simple doorbell, remote button, PIR, … devices are best added as flex decoders with a short .conf file. There are already some conf files, mostly you just need to change the timings.

How to use git to create new repositories by forking of rtl_433_tests and rtl_433

Create a github account

Once you have an account you will need to create your own copies of the rtl_433 and rtl_433_tests code repositories. To do this find the fork icon on the top right of the following pages:

https://github.com/merbanan/rtl_433

https://github.com/merbanan/rtl_433_tests

This will create equivalent repositories under your account.

Install git on your home PC

sudo apt-get git

Use "git clone" to download the code to your home PC

git clone https://github.com/YOUR-NAME/rtl_433.git

git clone https://github.com/YOUR-NAME/rtl_433_tests.git

Generally, origin should be your github repo (a fork of merbanan/rtl_433_tests). Typically when you clone the repository locally to do development, you are cloning your fork on github that you have permission to push to. After you push changes to a branch of your github repo, you use github's web interface to create a pull request.

How to record, prepare an push signals to rtl_433_tests

Record

Create a new directory structure in rtl_433_tests/tests/ to store your radio signals

Add signals by creating a directory with the protocol name and then add the gfiles under a directory with 2 number directory name. Also add a readme.md and a picture of the hardware.

E.g tests/prologue/01

using rtl_433 -S unknown record samples to the new directory path.

Prepare

Now add & then commit your radio samples to your local repository

You can propose changes (add it to the Index) using git add .

To record a comment for your changed files use: git commit -m "New device recording for prologue device" Now the file is committed to the HEAD, but not in your remote repository (github) yet.

Push

Your changes are now in the HEAD of your local working copy. To send those changes to your remote repository, execute

git push origin master

Further Notes:

Periodically you will want to synchronise your local repos with https://github.com/merbanan/rtl_433_tests.git

git remote add merbanan https://github.com/merbanan/rtl_433_tests.git

git pull merbanan

git push origin master

How to analyse a recorded signal and create a new device specification

To add a new remote device specification, you will need to implement the callback method declared in r_device, add your source file to src/devices, and your r_device to the rtl_433_devices.h header file. You also need to add the name of your source file to src/CMakeLists.txt, vs15/rtl_433.vcxproj and vs15/rtl_433.vcxproj.filters

Analyse the signal

rtl_433 -A

Is the modulation AM (OOK) or FM (FSK)

Using a program called Audacity http://www.audacityteam.org/ import the signal as raw_data and have a look at the waveform to determine if it using OOK or FSK modulation.

Find out the timings/limits for short and long pulses. Units of _limit data are in microseconds, and values are given by the -A option.

.name           = "Rubicson Temperature Sensor",
.modulation     = OOK_PULSE_PPM_RAW,
.short_limit    = 488+970,      // Gaps:  Short 976µs, Long 1940µs, Sync 4000µs
.long_limit     = 970+2000,     // Pulse: 500µs (Initial pulse in each package is 388µs)
.reset_limit    = 4800,             // Two initial pulses and a gap of 9120µs is filtered out
.json_callback  = &rubicson_callback,
.disabled       = 0,
.demod_arg      = 0,
.fields         = output_fields,

};

Appropriate short, long and reset limits

How to add the decoder and write new code

To add a device to rtl_433 the procedure is as follows:

  • create a .c file in src/devices
  • declare the new decoder in include/rtl_433_devices.h, adding towards the end a line with DECL(protocolname) \
  • add the newly created protocolname.c file to src/CMakeLists.txt, in alphabetical order together with the other protocols

The src/devices/.c file will contain two main things: the decoding function itself and a r_device structure configuring the device and indicating, among other things, the modulation (and therefore the demodulator to use) and a 1st level of encoding.

It's suggested to start from an existing protocol and replicate the code structure. Let's examine for example the Cavius protocol

The Cavius protocol example

In order to better understand the structure, let's start from the bottom

        .name        = "Cavius smoke, heat and water detector",
        .modulation  = FSK_PULSE_PCM,
        .short_width = 206,
        .long_width  = 206,
        .sync_width  = 2700,
        .gap_limit   = 1000,
        .reset_limit = 1000,
        .decode_fn   = &cavius_decode,
        .fields      = output_fields,
};

This is the same data as the flex protocol -X option. Will be used by rtl_433 to properly decode the packet and prepare the structures used by the custom decoder functions

Proceeding from the bottom, we find the output fields from the decoder

static char *output_fields[] = {
        "model",
        "id",
        "battery_ok",
        "net_id",
        "message",
        "text",
        "mic",
        NULL,
};

The goal in writing a decoder is to properly fill all the necessary fields, using the proper formatting.

Going back to the beginning of the file now, we have the main decoding function, which will be called by rtl_433 when a signal with the right format is found

static int cavius_decode(r_device *decoder, bitbuffer_t *bitbuffer)

Then a series of functions are called to start parsing the bitbuffer structure, starting from bitbuffer_search(bitbuffer, 0, 0, preamble, sizeof(preamble) * 8) to find the preamble and the start of the actual packet, then followed by a decoding function like bitbuffer_manchester_decode(bitbuffer, 0, bit_offset, &databits, 11 * 8) or bitbuffer_extract_bytes(bitbuffer, 0, bit_offset, b1, sizeof(b1) * 8). Refer to bitbuffer.h for a list of all decoding functions.

Once you have all your data processed and converted, it's time to format it with

    /* clang-format off */
    data = data_make(
            "model",        "",             DATA_STRING, "Cavius-Security",
            "id",           "Device ID",    DATA_INT,    sender_id,
            "battery_ok",   "Battery",      DATA_INT,    !batt_low,
            "net_id",       "Net ID",       DATA_INT,    net_id,
            "message",      "Message",      DATA_INT,    message,
            "text",         "Description",  DATA_STRING, text,
            "mic",          "Integrity",    DATA_STRING, "CRC",
            NULL);
    /* clang-format on */

Note how the first column is identical to the static char *output_fields[] previously encountered. rtl_433 offers a wide range of formatting functions.

Finally call decoder_output_data(decoder, data); to output the data, and return from the function with return 1. In case of problems, return one of the errors like DECODE_FAIL_MIC, defined in r_device.h

How to upload the new device driver to your forked repository and request a pull request

Generally, origin should be your github repo (a fork of merbanan/rtl_433_tests). Typically when you clone the repo locally to do development, you are cloning your fork on github that you have permission to push to. After you push changes to a branch of your github repo, you use github's web interface to create a pull request.

Tutorials

Decipher a new device and write a decoder

A good helper, in french