Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Com things add pandwarf support #132

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e657721
Docker: Add configs and script to access the rfcat device using docker
CharlieBailly Jan 31, 2022
8d90b21
Docker: Now unpluging and replugging usb does not break access to the…
CharlieBailly Jan 31, 2022
ad43e4f
RfCat: Implement a first version of PandwaRF and PandwaRF Rogue
CharlieBailly Feb 7, 2022
31e2234
RfCat: Add PandwaRF example scripts
CharlieBailly Feb 7, 2022
fb11769
RfCat: Fix specan
CharlieBailly Feb 7, 2022
b76c600
USB Device List: Add the PandwaRF and PandwaRF Rogue product ids and …
CharlieBailly Feb 7, 2022
b069590
USB non-root: Add PandwaRF vendor/device id to udev rules
CharlieBailly Feb 7, 2022
a4badec
RfCat: Update bruteforce method and example script
CharlieBailly Feb 7, 2022
43eea21
RfCat: Add bruteforce legacy with example script
CharlieBailly Feb 7, 2022
7d2a37b
Doc: Update Readme on how to install and use rfcat (with/without docker)
CharlieBailly Feb 8, 2022
f938577
RfCat: Minor fixes
CharlieBailly Feb 8, 2022
cc2550d
Docker: Make it work on windows
CharlieBailly Feb 8, 2022
4e3274a
RfCat: Add example script to interact with Kaiju and PandwaRF
CharlieBailly Feb 8, 2022
f46e2f6
RfCat: Add another example script to generate and send rolling code
CharlieBailly Feb 8, 2022
a7e9891
Docker: Move dependencies to requirements.txt
CharlieBailly Feb 8, 2022
7da9857
Move example scripts
CharlieBailly Feb 9, 2022
a9338c0
RfCat: Update init message
CharlieBailly Feb 9, 2022
9eae4bc
Update scripts to execute in Python 3 by default (#122)
argilo Apr 16, 2022
d7e1550
Work around a suspected SDCC bug (#123)
argilo Apr 17, 2022
dcc348a
Fixes bug caused by future import statement not being at the top (#124)
jimilinuxguy Apr 20, 2022
581ce04
description_file
atlas0fd00m Apr 17, 2022
f9632c3
working on bits.py
atlas0fd00m Apr 21, 2022
9e70c36
lots of bits.py improvements and unittests
atlas0fd00m Apr 21, 2022
4f0bba5
Fix Python 3 issues in rfcat_bootloader (#125)
argilo Apr 22, 2022
db60441
fix a few Python3 migration oversights in bootloader and intelhex
atlas0fd00m Aug 11, 2022
a03781f
touch up installer to allow for automated install of Pyside2 by choos…
atlas0fd00m Aug 11, 2022
6a472e1
rfcat_bootloader Py3 lingering bug
atlas0fd00m Dec 20, 2022
246aaa4
touch version upgrade
atlas0fd00m Dec 20, 2022
93484f3
Merge branch 'master' into ComThings-add_pandwarf_support
atlas0fd00m Dec 28, 2022
31fa5f2
Update rfcat
atlas0fd00m Nov 2, 2023
e5b7341
Update rfcat
atlas0fd00m Nov 2, 2023
8303352
Update README.md
atlas0fd00m Nov 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM python:3.9.10

WORKDIR /pandwarf/rfcat
COPY . .
RUN apt update && apt install -y usbutils ffmpeg && pip install -r requirements.txt
RUN python setup.py install

CMD [ "bash" ]
83 changes: 67 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,74 @@
Welcome to the official RfCat project! Enabling powerful RF tools such as `PandwaRF` / `PandwaRF Rogue`, `Yard Stick One`, and original Chronos and TI EMK dongles (and more)

## How to install RfCat python

There are multiple ways to install rfcat, including a docker way, but for now, if you are using docker, you won't be able to use the `rfcat -s` feature (the Spectrum Analyser) since it require a GUI (Graphical User Interface).

### On Linux

- (Recommended) Install using docker and our custom image by simply running `./run_rfcat_docker.sh`
- Install using the [legacy install](#installing-client)

### On Windows

On windows you can use rfcat with `WSL 2` and the `Ubuntu distribution for WSL 2`. You can :
- (Recommended) Install using `Docker Desktop` by simply running `run_rfcat_docker.bat`
- Install using the [legacy install](#installing-client) of rfcat inside `WSL 2`.

In both cases, after installation, you will need to follow this [guide](https://devblogs.microsoft.com/commandline/connecting-usb-devices-to-wsl/) to expose your PandwaRF / Yard Stick One USB Dongle to the `WSL 2 / Docker instance`. The guide is working on `Windows 10` even if it says you need `Windows 11`.

## How to use RfCat python without root permissions

(You don't need to do this if you are using the docker method)

You may have tried to run `rfcat -r` and saw a `Permission Denied` error, and then simply did `sudo rfcat -r` to make it work, but you can avoid the `sudo` by allowing user access to the RfCat USB Dongles by doing the following:

```bash
sudo cp etc/udev/rules.d/20-rfcat.rules /etc/udev/rules.d
sudo udevadm control --reload-rules
# Then you may need to reboot to apply changes
```

## How to use RfCat python

After having followed the above guide on how to install the rfcat python client, you can simply type `rfcat -r` to interact with the Dongle. You can also create scripts to use the Dongle, and some example script for the `PandwaRF` are provided in the [examples](./examples/) folder.
You can also check the [legacy Using rfcat](#using-rfcat) for additional info.




# Legacy Readme

Welcome to the rfcat project

## Table of Contents

* [Goals](#goals)
* [Requirements](#requirements)
* [Other requirements](#other-requirements)
* [Build requirements](#build-requirements)
* [Development](#development)
* ["Gotchas"](#gotchas)
* [Installing on hardware](#installing-on-hardware)
* [Allowing non-root dongle access](#allowing-non-root-dongle-access)
* [Supported dongles](#supported-dongles)
* [Your build environment](#your-build-environment)
* [Installing with bootloader](#installing-with-bootloader)
* [To install](#to-install)
* [Installing client](#installing-client)
* [Using RfCat](#using-rfcat)
* [Cool Projects Using RfCat](#external-projects)
* [Epilogue](#epilogue)
- [Legacy Readme](#legacy-readme)
- [Table of Contents](#table-of-contents)
- [GOALS](#goals)
- [REQUIREMENTS](#requirements)
- [Other requirements](#other-requirements)
- [Build requirements](#build-requirements)
- [DEVELOPMENT](#development)
- [Gotchas](#gotchas)
- [INSTALLING ON HARDWARE](#installing-on-hardware)
- [allowing non-root dongle access](#allowing-non-root-dongle-access)
- [supported dongles](#supported-dongles)
- [GoodFET](#goodfet)
- [Chronos Dongle](#chronos-dongle)
- [EMK Dongle](#emk-dongle)
- [YARD Stick One](#yard-stick-one)
- [INSTALLING WITH BOOTLOADER](#installing-with-bootloader)
- [Steps required for all firmware installs and updates](#steps-required-for-all-firmware-installs-and-updates)
- [Steps for bootloader + firmware installs via hardware debugger](#steps-for-bootloader--firmware-installs-via-hardware-debugger)
- [Steps for firmware updates via USB port](#steps-for-firmware-updates-via-usb-port)
- [Installing client](#installing-client)
- [Dependencies](#dependencies)
- [Installation](#installation)
- [Installation with pip](#installation-with-pip)
- [Using rfcat](#using-rfcat)
- [External Projects](#external-projects)
- [Epilogue](#epilogue)

## GOALS

Expand Down
9 changes: 9 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: "3.3"

services:
rfcat_image:
build: .
volumes:
- /dev/bus/usb:/dev/bus/usb
privileged: true

5 changes: 5 additions & 0 deletions etc/udev/rules.d/20-rfcat.rules
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}==
SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="604a", MODE:="0660", SYMLINK+="RFCAT_BL_D", ENV{ID_MM_DEVICE_IGNORE}="1", GROUP="dialout"
SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="605c", MODE:="0660", SYMLINK+="RFCAT_BL_YS1", ENV{ID_MM_DEVICE_IGNORE}="1", GROUP="dialout"
SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="ecc0", MODE:="0660", SYMLINK+="RFCAT_BL_SRF", ENV{ID_MM_DEVICE_IGNORE}="1", GROUP="dialout"

# PandwaRF devices

SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="60fe", MODE:="0660", SYMLINK+="RFCAT%n", GROUP="dialout"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d50", ATTRS{idProduct}=="60ff", MODE:="0660", SYMLINK+="RFCAT%n", GROUP="dialout"
55 changes: 55 additions & 0 deletions examples/kaiju_analysis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import json
from rflib.chipcon_gollum import *
import time, requests

if __name__ == "__main__":
d = PandwaRF()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this required? or will RfCat() work as well?
one thing i don't want is for RfCat to be arbitrarily fractured.

FREQ = 433_920_000
DATARATE = 10_000
# Your token can be found on https://rolling.pandwarf.com/profile-user
# It is the 'API token'
KAIJU_API_TOKEN = "YOUR_KAIJU_API_TOKEN_HERE"

d.setModeIDLE()
d.rxSetup(FREQ, MOD_ASK_OOK, DATARATE)
d.setAmpMode(RF_RX_POWER_AMPLIFIER_ACTION_ON)
d.setModeRX()
print("Please send some data...")
time.sleep(5)
data, _ = d.RFrecv()
print(f"Data received : {data.hex()}")
d.setModeIDLE()
print("Analysing data with Kaiju...")

base_url = "https://rolling.pandwarf.com/api/v1"
s = requests.Session()
s.headers.update({
'Authorization': f'Token {KAIJU_API_TOKEN}'
})

payload = {
"rawHexStream": data.hex()
}
payload = json.dumps(payload)
response = s.post(f"{base_url}/analyze/detailed", data=payload)

result = response.json()
if "progress" not in result.keys():
print(json.dumps(result, indent=2))
d.setModeIDLE()
exit()
# Now polling server every 1 seconds until processing is finished
progress = result["progress"]
taskId = result["id"]
while progress != 100:
r = s.get(f"{base_url}/task/{taskId}")
result = r.json()
progress = result["progress"]
print(f"Progress: {progress}/100")
time.sleep(1)

print("Processing done, now retrieving the result :")
r = s.get(f"{base_url}/remote/{taskId}")
result = r.json()
remoteData = result["remoteData"]
print(json.dumps(remoteData, indent=2))
74 changes: 74 additions & 0 deletions examples/kaiju_generate_rolling_code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import json
from rflib.chipcon_gollum import *
import time, requests

if __name__ == "__main__":
d = PandwaRF()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question?

FREQ = 433_920_000
DATARATE = 2_500
# Your token can be found on https://rolling.pandwarf.com/profile-user
# It is the 'API token'
KAIJU_API_TOKEN = "YOUR_KAIJU_API_TOKEN_HERE"
REMOTE_INFO = {
"rollingCodeRequest": {
"type": "Gate Opener",
"brand": "MHouse",
"model": "GTX",
"serialNumberHex": "0x041170E",
"syncCounter": 1440,
"button": 1,
"seed": "",
"numCodesRequested": 2
}
}
# We will generate 2 rolling codes and send them using the PandwaRF
base_url = "https://rolling.pandwarf.com/api/v1"
s = requests.Session()
s.headers.update({
'Authorization': f'Token {KAIJU_API_TOKEN}'
})

payload = json.dumps(REMOTE_INFO)
print("Asking Kaiju for rolling codes")
response = s.post(f"{base_url}/generate/param", data=payload)
result = response.json()
if "progress" not in result.keys():
print(json.dumps(result, indent=2))
d.setModeIDLE()
exit()
# Now polling server every 1 seconds until processing is finished
progress = result["progress"]
taskId = result["id"]
while progress != 100:
r = s.get(f"{base_url}/task/{taskId}")
result = r.json()
progress = result["progress"]
print(f"Progress: {progress}/100")
time.sleep(1)

print("Processing done, now retrieving the rolling codes :")
r = s.get(f"{base_url}/remote/{taskId}")
result = r.json()
rollingCodes = result["remoteData"]["rollingCodes"]

print("Preparing PandwaRF for TX")
d.setModeIDLE()
d.txSetup(FREQ, MOD_ASK_OOK, DATARATE)
d.setAmpMode(RF_TX_POWER_AMPLIFIER_ACTION_ON)
d.setModeTX()

for rollingCode in rollingCodes:
syncCounter = rollingCode["syncCounter"]
button = rollingCode["button"]
dataHex = rollingCode["dataHex"]
fullMsgHex = rollingCode["fullMsgHex"]
data = dataHex
if not data:
data = fullMsgHex

data = bytes.fromhex(data)
print(f"Sending rolling code {syncCounter} of button {button}")
d.RFxmit(data)
time.sleep(2)

d.setModeIDLE()
72 changes: 72 additions & 0 deletions examples/kaiju_generate_rolling_code_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import json
from rflib.chipcon_gollum import *
import time, requests

if __name__ == "__main__":
d = PandwaRF()
FREQ = 433_920_000
DATARATE = 2_500
# Your token can be found on https://rolling.pandwarf.com/profile-user
# It is the 'API token'
KAIJU_API_TOKEN = "YOUR_KAIJU_API_TOKEN_HERE"
ROLLING_INFO = {
"numCodesRequested": 2,
"rxTxConfig": {
"rawBitStream": "10101010101010101010101000000000001101001001001001001001101101101001001001101001001101101001101101101001101101101001101001001101101101001001001101101101101001001001101001101101101001101101101101101001101101101101101101001101101101"
}
}
# We will generate 2 rolling codes and send them using the PandwaRF
base_url = "https://rolling.pandwarf.com/api/v1"
s = requests.Session()
s.headers.update({
'Authorization': f'Token {KAIJU_API_TOKEN}'
})

payload = json.dumps(ROLLING_INFO)
print("Asking Kaiju for rolling codes")
response = s.post(f"{base_url}/generate/capture", data=payload)
result = response.json()
if "progress" not in result.keys():
print(json.dumps(result, indent=2))
d.setModeIDLE()
exit()
# Now polling server every 1 seconds until processing is finished
progress = result["progress"]
taskId = result["id"]
while progress != 100:
r = s.get(f"{base_url}/task/{taskId}")
result = r.json()
progress = result["progress"]
print(f"Progress: {progress}/100")
time.sleep(1)

print("Processing done, now retrieving the rolling codes :")
r = s.get(f"{base_url}/remote/{taskId}")
result = r.json()

rollingCodes = result["remoteData"]["rollingCodes"]

print("Preparing PandwaRF for TX")
d.setModeIDLE()
d.txSetup(FREQ, MOD_ASK_OOK, DATARATE)
d.setAmpMode(RF_TX_POWER_AMPLIFIER_ACTION_ON)
d.setModeTX()

for rollingCode in rollingCodes:
syncCounter = rollingCode["syncCounter"]
button = rollingCode["button"]
dataHex = rollingCode["dataHex"]
fullMsgHex = rollingCode["fullMsgHex"]
data = dataHex
if not data:
data = fullMsgHex

data = bytes.fromhex(data)
print(f"Sending rolling code {syncCounter} of button {button}")
d.RFxmit(data)
time.sleep(2)

if rollingCodes == []:
print("Unable to generate rolling code")

d.setModeIDLE()
32 changes: 32 additions & 0 deletions examples/simple_bruteforce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from rflib.chipcon_gollum import *

if __name__ == "__main__":
# This bruteforce is only available on PandwaRF Rogue
# See bruteforce legacy for the PandwaRF (non Rogue)
d = PandwaRFRogue()
d.setModeIDLE()
FREQ = 433_920_000
DATARATE = 24_536
MOD = MOD_ASK_OOK
codeLength = 12
startValue = 3190
stopValue = 3300
repeat = 6
delayMs = 30

symbolLength = 3
encSymbolZero = 0xFF0000
encSymbolOne = 0xFF00FF
encSymbolTwo = 0x000000
encSymbolThree = 0x000000
syncWordSize = 40
syncWord = 0
tailWordSize = 8
tailWord = 0xFF00000000000000
functionSize = 12
functionMask = 0xFFFFFFFFFFFFFFFFFFFF0000
functionValue= 0x000000000000000000000001

d.doBruteForce(FREQ, MOD, DATARATE, startValue, stopValue, codeLength, repeat, delayMs, symbolLength, encSymbolZero, encSymbolOne, encSymbolTwo, encSymbolThree, syncWordSize, syncWord, tailWordSize, tailWord, functionSize, functionMask, functionValue)

d.setModeIDLE()
30 changes: 30 additions & 0 deletions examples/simple_bruteforce_legacy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from rflib.chipcon_gollum import *

if __name__ == "__main__":
# If you have a PandwaRF Rogue, it is better to use the
# other version of bruteforce (non-legacy)
d = PandwaRF()
d.setModeIDLE()
FREQ = 433_890_000
DATARATE = 5_320
MOD = MOD_ASK_OOK
codeLength = 8
startValue = 0
stopValue = 6560
repeat = 10
delayMs = 0x64

encSymbolZero = 0x8E
encSymbolOne = 0xEE
encSymbolTwo = 0xE8
encSymbolThree = 0x00
syncWordSize = 2
syncWord = 0x0008

functionSize = 8
functionMask = 0xFFFFFF0000FFFFFF
functionValue= 0x000000EEE8000000

d.doBruteForceLegacy(FREQ, MOD, DATARATE, startValue, stopValue, codeLength, repeat, delayMs, encSymbolZero, encSymbolOne, encSymbolTwo, encSymbolThree, syncWordSize, syncWord, functionSize, functionMask, functionValue)

d.setModeIDLE()
8 changes: 8 additions & 0 deletions examples/simple_datarate_measurement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from rflib.chipcon_gollum import *

if __name__ == "__main__":
d = PandwaRF()
d.setModeIDLE()
FREQ = 433920000
d.doDataRateDetect(FREQ, MOD_ASK_OOK)
d.setModeIDLE()
Loading