Skip to content

Commit

Permalink
Adapt readme to reflect Python port
Browse files Browse the repository at this point in the history
  • Loading branch information
rrooggiieerr committed Jan 24, 2023
1 parent b9092a6 commit 826a525
Showing 1 changed file with 29 additions and 50 deletions.
79 changes: 29 additions & 50 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# rfcontrolpy

rfcontrolpy is a Python library and port of the node.js [rfcontroljs](https://github.com/pimatic/rfcontroljs)
rfcontrolpy is a Python library and port of the node.js [rfcontrolpy](https://github.com/rrooggiieerr/rfcontrolpy)
module for parsing and constructing 433mhz On-Off Keying (OOK) signals for various devices,
switches and weather stations.

It works together with the [RFControl](https://github.com/pimatic/RFControl) Arduino library
It works together with the [RFControl](https://github.com/rrooggiieerr/RFControl) Arduino library
for receiving the signals.

The Python port now contains a working contoller and a dozen of protocols. Not all protocols are
ported yet due to low demand or lack of hardware.
ported yet due to low demand or lack of hardware.

You can find a list of all supported protocols [here](protocols.md).

Expand All @@ -24,9 +24,9 @@ and waits for rf signal.
> longer footer pulse in between. They differ by the pulse lengths used to encode the data and footer
> and the pulse count.
[RFControl](https://github.com/pimatic/RFControl) running on the arduino detects the start of a
[RFControl](https://github.com/rrooggiieerr/RFControl) running on the Arduino detects the start of a
signal by its longer footer pulse and verifies it one time by comparing it with the next signal.
It it unaware of the specific protocol, it just uses the stated fact above. Also we are
It is unaware of the specific protocol, it just uses the stated fact above. Also we are
not interested in it if the pulse was a high or low pulse (presence or absence of a carrier wave),
because the information is decoded in the pulse lengths.

Expand Down Expand Up @@ -54,7 +54,7 @@ pulses: 01010101011001100101010101100110011001100101011002
```

To make the representation unique, we choose the buckets in ascending order (respectively we are
sorting it after receiving from the arduino).
sorting it after receiving from the Arduino).

We call the sorted buckets **pulse lengths**, the compressed timings **pulse sequence** and the
length of the pulse sequence (inclusive footer) **pulse count**.
Expand All @@ -72,13 +72,13 @@ parsed almost the same way. First the pulse squence must be converted to a binar
In almost all cases there exist a mapping from pulse sequences to a binary `0` and `1`. In this
example the pulse sequence `0110` represents a binary `0` and `0101` maps to a binary `1`:

```CoffeeScript
pulsesToBinaryMapping = {
'0110': '0' #binary 0
'0101': '1' #binary 1
'02': '' #footer
```Python
pulses2binary_mapping = {
["0110": "0"], # Binary 0
["0101": "1"], # Binary 1
["02": ""] # Footer
}
binary = helper.map(pulses, pulsesToBinaryMapping)
binary = helpers.pulses2binary(pulses, pulses2binary_mapping)
```

The binary reprsentation now looks like this:
Expand All @@ -89,11 +89,11 @@ The binary reprsentation now looks like this:

As last step the protocol dependent information must be extracted from the binary representation:

```CoffeeScript
result = {
houseCode: helper.binaryToNumber(binary, 0, 5)
unitCode: helper.binaryToNumber(binary, 6, 10)
state: helper.binaryToBoolean(binary, 12)
```Python
decoded = {
"id": int(binary[:6], 2),
"unit": int(binary[6:11], 2),
"state": binary[12] == "1"
}
```

Expand All @@ -105,51 +105,30 @@ RFControl is more sensitive than needed for most protocols.
So we get sometimes, depending of the accuracy of the sender/remote, different bucket counts.

This is by design, to catch up further protocols that maybe need a higher sensitivity. The specific
protocol has not to deal with this issue, because `rfcontroljs` auto merges similar buckets before
protocol has not to deal with this issue, because `rfcontrolpy` auto merges similar buckets before
calling the `decodePulses` function of each protocol.

The algorithm is the following:

1. Record the (maybe to many) buckets and compressed pulses with [RFControl](https://github.com/pimatic/RFControl) (arduino / c++)
2. Sort the buckets in `rfcontroljs` [`prepareCompressedPulses`](https://github.com/pimatic/rfcontroljs/blob/f39db799ae1fc86cda74c33a01c27da40eb3c9e8/src/controller.coffee#L68)
3. Try to find a matching protocol in rfcontroljs [`decodePulses`](https://github.com/pimatic/rfcontroljs/blob/f39db799ae1fc86cda74c33a01c27da40eb3c9e8/src/controller.coffee#L118)
4. If we have more than 3 buckets and two of the buckets are similar (`b1*2 < b2`) we merge them to just one bucket by averaging and adapting the pulses in rfcontroljs [`fixPulses`](https://github.com/pimatic/rfcontroljs/blob/f39db799ae1fc86cda74c33a01c27da40eb3c9e8/src/controller.coffee#L89)
1. Record the (maybe to many) buckets and compressed pulses with [RFControl](https://github.com/pimatic/RFControl) (Arduino / c++)
2. Sort the buckets in `rfcontrolpy` `prepare_compressed_pulses`
3. Try to find a matching protocol in rfcontrolpy `decode_pulses`
4. If we have more than 3 buckets and two of the buckets are similar (`b1*2 < b2`) we merge them to just one bucket by averaging and adapting the pulses in rfcontrolpy `fix_pulses`
5. Go to step 3

Adding a new Protocol
--------------------

## Preparation

1. Fork the rfcontroljs repository and clone your fork into a local directory.
2. run `npm install` inside the cloned directory, so that all dependencies get installed.
3. We are using [gulp](http://gulpjs.com/) for automating tests and automatic coffee-script compilation. So best to install it global: `npm install --global gulp`
4. You should be able to run the tests with `gulp test`.
5. Running just `gulp` let it compile all files and whats for changes. So always keep in running while editing coffee-files.
1. Fork the rfcontrolpy repository and clone your fork into a local directory.
2. We are using [unittest](https://docs.python.org/3/library/unittest.html) for automating tests.
3. You should be able to run the tests with `python3 -m unittest discover`.
5. Running `python3 -m build` let it compile all files and whats for changes.

## Protocol development

1. Create a new protocol file (like the other) in `src/protocols`.
2. Add its name in the `src/controller.coffee` file to [the protocol list](https://github.com/pimatic/rfcontroljs/blob/master/src/controller.coffee#L2).
3. Add a test case to the `#decodePulses()` test case list in `test/lib-controller.coffee` with the data from the arduino ([like this one](https://github.com/pimatic/rfcontroljs/blob/master/test/lib-controller.coffee#L65-L74)). For the `pulseLengths`: strip the zero's at the end and sort them in ascending order, also adapt the `pulse` to the changed sorting. [1]
1. Create a new protocol file (like the others) in `rfcontrol/protocols/`.
2. Add its name in the `rfcontrol/controller.py` file to the `protocols` list.
3. Add a test case in `tests/protocols` with the data from the Arduino.
4. Adapt the protocol file, so that the test get passed.

[1] You can also use this script to convert the output to a valid test input:

```coffee
controller = require './index.js'
result = controller.prepareCompressedPulses('255 2904 1388 771 11346 0 0 0 0100020002020000020002020000020002000202000200020002000200000202000200020000020002000200020002020002000002000200000002000200020002020002000200020034')
console.log result
result2 = controller.fixPulses(result.pulseLengths, result.pulses)
console.log result2
```
sample output:

```
coffee convert.coffee
{ pulseLengths: [ 255, 771, 1388, 2904, 11346 ],
pulses: '0300020002020000020002020000020002000202000200020002000200000202000200020000020002000200020002020002000002000200000002000200020002020002000200020014' }
{ pulseLengths: [ 255, 1079, 2904, 11346 ],
pulses: '0200010001010000010001010000010001000101000100010001000100000101000100010000010001000100010001010001000001000100000001000100010001010001000100010013' }
```
The second line should be used for protocol developing.

0 comments on commit 826a525

Please sign in to comment.