Skip to content

Commit 8d5c0e7

Browse files
committed
feat: add Chacon 54662 support
1 parent 9f0b62e commit 8d5c0e7

File tree

6 files changed

+102
-1
lines changed

6 files changed

+102
-1
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Remote Control REST API
22

3-
REST API to use an RF 433 MHz transmitter as a remote control. It currently only supports the Chacon DIO 1.0 protocol.
3+
REST API to use an RF 433 MHz transmitter as a remote control. It currently only supports the Chacon DIO 1.0 and Chacon 54662 protocols.
44

55
It has only been tested on an ODROID-C4 board and uses an ODROID-specific WiringPi version. It should be easy to adapt it for other boards (e.g. Raspberry Pi).
66

app/chacon54662/__init__.py

Whitespace-only changes.

app/chacon54662/cli.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import argparse
2+
3+
import odroid_wiringpi as wiringpi
4+
5+
from .protocol import transmit
6+
7+
8+
def parse_args():
9+
parser = argparse.ArgumentParser(description="Chacon 54662 remote control")
10+
parser.add_argument("-g", "--gpio", help="GPIO WiringPi pin number (default: 0)", type=int, choices=range(0, 30), metavar="[0-29]", default=0)
11+
parser.add_argument("-w", "--word", help="24-bit code word", type=int, required=True)
12+
parser.add_argument("-r", "--repeat", help="Number of times to repeat the message (default: 1)", type=int, default=1)
13+
return parser.parse_args()
14+
15+
16+
def main():
17+
args = parse_args()
18+
19+
if wiringpi.wiringPiSetup() == -1:
20+
raise Exception("Failed to initialize WiringPi")
21+
wiringpi.pinMode(args.gpio, wiringpi.OUTPUT)
22+
23+
for _ in range(args.repeat):
24+
transmit(args.gpio, args.word)
25+
26+
27+
if __name__ == "__main__":
28+
main()

app/chacon54662/protocol.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import odroid_wiringpi as wiringpi
2+
3+
TIME_HIGH_LOCK = 290
4+
TIME_LOW_LOCK = 2400
5+
6+
TIME_HIGH_0 = 1070
7+
TIME_LOW_0 = 470
8+
9+
TIME_HIGH_1 = 290
10+
TIME_LOW_1 = 1250
11+
12+
13+
def sendBit(pin: int, b: bool):
14+
if b:
15+
wiringpi.digitalWrite(pin, wiringpi.HIGH)
16+
wiringpi.delayMicroseconds(TIME_HIGH_1)
17+
wiringpi.digitalWrite(pin, wiringpi.LOW)
18+
wiringpi.delayMicroseconds(TIME_LOW_1)
19+
else:
20+
wiringpi.digitalWrite(pin, wiringpi.HIGH)
21+
wiringpi.delayMicroseconds(TIME_HIGH_0)
22+
wiringpi.digitalWrite(pin, wiringpi.LOW)
23+
wiringpi.delayMicroseconds(TIME_LOW_0)
24+
25+
26+
def sendWord(pin: int, word: int, bits: int):
27+
for bit in reversed(range(bits)):
28+
if word & (1 << bit):
29+
sendBit(pin, True)
30+
else:
31+
sendBit(pin, False)
32+
33+
34+
def transmit(pin: int, word: int):
35+
for _ in range(4):
36+
# Code word (24 bits)
37+
sendWord(pin, word, 24)
38+
39+
# End lock
40+
wiringpi.digitalWrite(pin, wiringpi.HIGH)
41+
wiringpi.delayMicroseconds(TIME_HIGH_LOCK)
42+
wiringpi.digitalWrite(pin, wiringpi.LOW)
43+
wiringpi.delayMicroseconds(TIME_LOW_LOCK)
44+
45+
# Delay before next transmission
46+
wiringpi.delay(10)

app/chacon54662/routes.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from fastapi import APIRouter, Body, Path, Query, Request
2+
3+
from .protocol import transmit
4+
5+
router = APIRouter(prefix="/chacon54662", tags=["chacon54662"])
6+
7+
8+
@router.get("/state/{stateKey}", summary="Get button state")
9+
async def get_state(request: Request, stateKey: str = Path(pattern="[a-z0-9-]")):
10+
"""Get the current state for a given stateKey"""
11+
if stateKey in request.app.state.chacon54662:
12+
return request.app.state.chacon54662[stateKey]
13+
else:
14+
return 0
15+
16+
17+
@router.put("/word", summary="Send 24-bit code word")
18+
async def put_word(request: Request, word: str = Body(pattern="[01]{24}"), repeat: int = 3,
19+
stateKey: str = Query(default=None, pattern="[a-z0-9-]"), stateValue: int = Query(default=None, ge=0, le=1)):
20+
"""Send a 24-bit code word and optionally save state in a given stateKey"""
21+
if stateKey is not None and stateValue is not None:
22+
request.app.state.chacon54662[stateKey] = stateValue
23+
for _ in range(repeat):
24+
transmit(request.app.state.gpio, int(word, 2))

app/server.py

+3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import odroid_wiringpi as wiringpi
88
import uvicorn
9+
from chacon54662.routes import router as chacon54662_router
910
from chacondio10.routes import router as chacondio10_router
1011
from fastapi import FastAPI
1112
from fastapi.responses import RedirectResponse
@@ -22,8 +23,10 @@ async def lifespan(app: FastAPI):
2223
yield
2324

2425
app = FastAPI(title="Remote Control REST API", description="REST API to use an RF 433 MHz transmitter as a remote control", version="1.0", lifespan=lifespan)
26+
app.include_router(chacon54662_router)
2527
app.include_router(chacondio10_router)
2628
app.state.gpio = 0
29+
app.state.chacon54662 = {}
2730
app.state.chacondio10 = {}
2831

2932

0 commit comments

Comments
 (0)