refactor protocols
This commit is contained in:
parent
fb3c4e7b9f
commit
5aa901b68b
5 changed files with 240 additions and 366 deletions
|
@ -2,6 +2,7 @@ import re
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from raspyrfm import *
|
from raspyrfm import *
|
||||||
import threading
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
class RcProtocol:
|
class RcProtocol:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -10,6 +11,8 @@ class RcProtocol:
|
||||||
self.__bbuf = 0
|
self.__bbuf = 0
|
||||||
self.__bval = 0
|
self.__bval = 0
|
||||||
self._parser = ArgumentParser()
|
self._parser = ArgumentParser()
|
||||||
|
self._lastdecode = None
|
||||||
|
self._lastdecodetime = 0
|
||||||
|
|
||||||
sympulses = []
|
sympulses = []
|
||||||
for i in self._symbols:
|
for i in self._symbols:
|
||||||
|
@ -88,12 +91,18 @@ class RcProtocol:
|
||||||
break
|
break
|
||||||
|
|
||||||
if not match:
|
if not match:
|
||||||
return None, None
|
return None, None, None
|
||||||
|
|
||||||
|
print("code: ", dec)
|
||||||
if re.match("^" + self._pattern + "$", dec):
|
if re.match("^" + self._pattern + "$", dec):
|
||||||
return dec, int(1.0 * sumpulse / sumstep)
|
rep = True
|
||||||
|
if (self._lastdecode != dec) or (time.time() - self._lastdecodetime > 0.5):
|
||||||
|
self._lastdecode = dec
|
||||||
|
rep = False
|
||||||
|
self._lastdecodetime = time.time()
|
||||||
|
return dec, int(1.0 * sumpulse / sumstep), rep
|
||||||
|
|
||||||
return None, None
|
return None, None, None
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
pass
|
pass
|
||||||
|
@ -123,7 +132,7 @@ class IT32(RcProtocol): #switch1
|
||||||
self._add_symbols(code)
|
self._add_symbols(code)
|
||||||
self._add_pulses([1, 39])
|
self._add_pulses([1, 39])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
def encode(self, args):
|
def encode(self, args):
|
||||||
if hasattr(args, "code") and args.code:
|
if hasattr(args, "code") and args.code:
|
||||||
|
@ -138,7 +147,7 @@ class IT32(RcProtocol): #switch1
|
||||||
return self.__encode(code)
|
return self.__encode(code)
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
return {
|
return {
|
||||||
"protocol": self._name,
|
"protocol": self._name,
|
||||||
|
@ -148,7 +157,7 @@ class IT32(RcProtocol): #switch1
|
||||||
"group": int(code[26:27], 2),
|
"group": int(code[26:27], 2),
|
||||||
"state": int(code[27:28], 2),
|
"state": int(code[27:28], 2),
|
||||||
"unit": int(code[28:32], 2) + 1,
|
"unit": int(code[28:32], 2) + 1,
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
class ITTristate(RcProtocol): #old intertechno systems
|
class ITTristate(RcProtocol): #old intertechno systems
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -170,20 +179,20 @@ class ITTristate(RcProtocol): #old intertechno systems
|
||||||
self._parser.add_argument("-s", "--state", type=int)
|
self._parser.add_argument("-s", "--state", type=int)
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
return {
|
return {
|
||||||
"protocol": self._name,
|
"protocol": self._name,
|
||||||
"code": code,
|
"code": code,
|
||||||
"timebase": tb,
|
"timebase": tb,
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
def __encode(self, code):
|
def __encode(self, code):
|
||||||
self._reset()
|
self._reset()
|
||||||
self._add_symbols(code)
|
self._add_symbols(code)
|
||||||
self._add_pulses([1, 31])
|
self._add_pulses([1, 31])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
def __encode_int(self, ival, digits):
|
def __encode_int(self, ival, digits):
|
||||||
code = ""
|
code = ""
|
||||||
|
@ -222,20 +231,20 @@ class Bistate24(RcProtocol):
|
||||||
self._parser.add_argument("-c", "--code", required=True)
|
self._parser.add_argument("-c", "--code", required=True)
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
return {
|
return {
|
||||||
"protocol": self._name,
|
"protocol": self._name,
|
||||||
"code": code,
|
"code": code,
|
||||||
"timebase": tb,
|
"timebase": tb,
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
def encode(self, args):
|
def encode(self, args):
|
||||||
self._reset()
|
self._reset()
|
||||||
self._add_symbols(args.code)
|
self._add_symbols(args.code)
|
||||||
self._add_pulses([1, 31])
|
self._add_pulses([1, 31])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
class Switch15(Bistate24): #e. g. logilight
|
class Switch15(Bistate24): #e. g. logilight
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -249,7 +258,7 @@ class Switch15(Bistate24): #e. g. logilight
|
||||||
self._parser.add_argument("-s", "--state", type=int, required=True)
|
self._parser.add_argument("-s", "--state", type=int, required=True)
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
state = int(code[20:21])
|
state = int(code[20:21])
|
||||||
unit = int(code[21:24], 2)
|
unit = int(code[21:24], 2)
|
||||||
|
@ -273,7 +282,7 @@ class Switch15(Bistate24): #e. g. logilight
|
||||||
"id": int(code[0:20], 2),
|
"id": int(code[0:20], 2),
|
||||||
"unit": unit,
|
"unit": unit,
|
||||||
"state": state,
|
"state": state,
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
def encode(self, args):
|
def encode(self, args):
|
||||||
self._reset()
|
self._reset()
|
||||||
|
@ -294,7 +303,7 @@ class Switch15(Bistate24): #e. g. logilight
|
||||||
self._add_symbols(sym)
|
self._add_symbols(sym)
|
||||||
self._add_pulses([1, 31])
|
self._add_pulses([1, 31])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, 10 if args.state == 2 else self._repetitions
|
||||||
|
|
||||||
class Emylo(Bistate24):
|
class Emylo(Bistate24):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -307,7 +316,7 @@ class Emylo(Bistate24):
|
||||||
self._parser.add_argument("-k", "--key", required=True)
|
self._parser.add_argument("-k", "--key", required=True)
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
key = int(code[20:24], 2)
|
key = int(code[20:24], 2)
|
||||||
if key == 1:
|
if key == 1:
|
||||||
|
@ -326,7 +335,7 @@ class Emylo(Bistate24):
|
||||||
"timebase": tb,
|
"timebase": tb,
|
||||||
"id": int(code[0:20], 2),
|
"id": int(code[0:20], 2),
|
||||||
"key": key,
|
"key": key,
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
def encode(self, args):
|
def encode(self, args):
|
||||||
self._reset()
|
self._reset()
|
||||||
|
@ -345,7 +354,7 @@ class Emylo(Bistate24):
|
||||||
self._add_symbols(sym)
|
self._add_symbols(sym)
|
||||||
self._add_pulses([1, 31])
|
self._add_pulses([1, 31])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
class FS20(RcProtocol):
|
class FS20(RcProtocol):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -381,10 +390,10 @@ class FS20(RcProtocol):
|
||||||
self.__encode_byte(q & 0xFF)
|
self.__encode_byte(q & 0xFF)
|
||||||
self._add_pulses([1, 100])
|
self._add_pulses([1, 100])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
return {
|
return {
|
||||||
"protocol": self._name,
|
"protocol": self._name,
|
||||||
|
@ -393,7 +402,7 @@ class FS20(RcProtocol):
|
||||||
"housecode": int(code[13:21] + code[22:30] , 2),
|
"housecode": int(code[13:21] + code[22:30] , 2),
|
||||||
"address": int(code[31:39], 2),
|
"address": int(code[31:39], 2),
|
||||||
"cmd": int(code[40:48], 2),
|
"cmd": int(code[40:48], 2),
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
class Voltcraft(RcProtocol):
|
class Voltcraft(RcProtocol):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -411,7 +420,7 @@ class Voltcraft(RcProtocol):
|
||||||
self._parser.add_argument("-s", "--state", type=int, required=True)
|
self._parser.add_argument("-s", "--state", type=int, required=True)
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[1:-1])
|
code, tb, rep = self._decode_symbols(pulsetrain[1:-1])
|
||||||
if code:
|
if code:
|
||||||
return {
|
return {
|
||||||
"protocol": self._name,
|
"protocol": self._name,
|
||||||
|
@ -420,7 +429,7 @@ class Voltcraft(RcProtocol):
|
||||||
"id": int(code[0:12][::-1], 2),
|
"id": int(code[0:12][::-1], 2),
|
||||||
"unit": int(code[12:14][::-1], 2) + 1,
|
"unit": int(code[12:14][::-1], 2) + 1,
|
||||||
"state": int(code[14:17][::-1], 2) #0=off, 1=alloff, 2=on, 3=allon, 5=bright, 7=dim
|
"state": int(code[14:17][::-1], 2) #0=off, 1=alloff, 2=on, 3=allon, 5=bright, 7=dim
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
def encode(self, args):
|
def encode(self, args):
|
||||||
if not (args.state in [0, 2]):
|
if not (args.state in [0, 2]):
|
||||||
|
@ -438,7 +447,7 @@ class Voltcraft(RcProtocol):
|
||||||
self._add_symbols(symbols)
|
self._add_symbols(symbols)
|
||||||
self._add_pulses([132])
|
self._add_pulses([132])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
class PDM32(RcProtocol):
|
class PDM32(RcProtocol):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -454,20 +463,20 @@ class PDM32(RcProtocol):
|
||||||
self._parser.add_argument("-c", "--code")
|
self._parser.add_argument("-c", "--code")
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
return {
|
return {
|
||||||
"protocol": self._name,
|
"protocol": self._name,
|
||||||
"code": code,
|
"code": code,
|
||||||
"timebase": tb,
|
"timebase": tb,
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
def encode(self, args):
|
def encode(self, args):
|
||||||
self._reset()
|
self._reset()
|
||||||
self._add_symbols(args.code)
|
self._add_symbols(args.code)
|
||||||
self._add_pulses([1, 11])
|
self._add_pulses([1, 11])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
class PCPIR(RcProtocol): #pilota casa PIR sensor
|
class PCPIR(RcProtocol): #pilota casa PIR sensor
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -483,68 +492,83 @@ class PCPIR(RcProtocol): #pilota casa PIR sensor
|
||||||
self._parser.add_argument("-c", "--code", required=True)
|
self._parser.add_argument("-c", "--code", required=True)
|
||||||
|
|
||||||
def decode(self, pulsetrain):
|
def decode(self, pulsetrain):
|
||||||
code, tb = self._decode_symbols(pulsetrain[0:-2])
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
if code:
|
if code:
|
||||||
return {
|
return {
|
||||||
"protocol": self._name,
|
"protocol": self._name,
|
||||||
"code": code,
|
"code": code,
|
||||||
"timebase": tb,
|
"timebase": tb,
|
||||||
}
|
}, rep
|
||||||
|
|
||||||
def encode(self, args):
|
def encode(self, args):
|
||||||
self._reset()
|
self._reset()
|
||||||
self._add_symbols(args.code)
|
self._add_symbols(args.code)
|
||||||
self._add_pulses([1, 12])
|
self._add_pulses([1, 12])
|
||||||
self._add_finish()
|
self._add_finish()
|
||||||
return self._ookdata
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
|
class PDM1(RcProtocol):
|
||||||
|
'''
|
||||||
|
PDM1: Pulse Distance Modulation
|
||||||
|
Every bit consists of 2 shortpulses. Long distance between these pulses 2 pulses -> 1, else -> 0
|
||||||
|
Frame: header, payload, footer
|
||||||
|
Used by Intertechno self learning, Hama, ...
|
||||||
|
'''
|
||||||
|
def __init__(self):
|
||||||
|
self._name = "pdm1"
|
||||||
|
self._timebase = 275
|
||||||
|
self._repetitions = 4
|
||||||
|
self._pattern = "[01]*"
|
||||||
|
self._symbols = {
|
||||||
|
'0': [1, 1, 1, 5],
|
||||||
|
'1': [1, 5, 1, 1],
|
||||||
|
}
|
||||||
|
self._header = [1, 11]
|
||||||
|
self._footer = [1, 39]
|
||||||
|
#self._values = [
|
||||||
|
# ("c", "code")
|
||||||
|
#]
|
||||||
|
RcProtocol.__init__(self)
|
||||||
|
self._parser.add_argument("-c", "--code", required=True)
|
||||||
|
|
||||||
|
def decode(self, pulsetrain):
|
||||||
|
print("decoding pwm 1")
|
||||||
|
code, tb, rep = self._decode_symbols(pulsetrain[0:-2])
|
||||||
|
print(code)
|
||||||
|
if code:
|
||||||
|
return {
|
||||||
|
"protocol": self._name,
|
||||||
|
"code": code,
|
||||||
|
"timebase": tb,
|
||||||
|
}, rep
|
||||||
|
|
||||||
|
def encode(self, args):
|
||||||
|
self._reset()
|
||||||
|
self._add_symbols(args.code)
|
||||||
|
self._add_pulses([1, 31])
|
||||||
|
self._add_finish()
|
||||||
|
return self._ookdata, self._timebase, self._repetitions
|
||||||
|
|
||||||
protocols = [
|
protocols = [
|
||||||
IT32(),
|
#IT32(),
|
||||||
Switch15(),
|
#Switch15(),
|
||||||
ITTristate(),
|
#ITTristate(),
|
||||||
Voltcraft(),
|
#Voltcraft(),
|
||||||
FS20(),
|
#FS20(),
|
||||||
Emylo(),
|
#Emylo(),
|
||||||
PDM32(),
|
#PDM32(),
|
||||||
Bistate24(),
|
#Bistate24(),
|
||||||
PCPIR(),
|
#PCPIR(),
|
||||||
|
PDM1(),
|
||||||
]
|
]
|
||||||
|
|
||||||
def encode(protocol, args):
|
RXDATARATE = 20.0 #kbit/s
|
||||||
for p in protocols:
|
class RfmPulseTRX(threading.Thread):
|
||||||
if (protocol):
|
def __init__(self, module, rxcb, frequency):
|
||||||
if p._name == protocol:
|
|
||||||
return (p.encode(p._parser.parse_args(args)), p._timebase, p._repetitions)
|
|
||||||
|
|
||||||
class RCStruct:
|
|
||||||
def __init__(self, **entries):
|
|
||||||
self.__dict__.update(entries)
|
|
||||||
|
|
||||||
def encode_dict(dict):
|
|
||||||
s = RCStruct(**dict)
|
|
||||||
for p in protocols:
|
|
||||||
if p._name == s.protocol:
|
|
||||||
return (p.encode(s), p._timebase, p._repetitions)
|
|
||||||
|
|
||||||
def decode(pulsetrain):
|
|
||||||
dec = None
|
|
||||||
res = []
|
|
||||||
for p in protocols:
|
|
||||||
dec = p.decode(pulsetrain)
|
|
||||||
if dec:
|
|
||||||
res.append(dec)
|
|
||||||
|
|
||||||
if len(res) > 0:
|
|
||||||
return res
|
|
||||||
|
|
||||||
class PulseTRX(threading.Thread):
|
|
||||||
def __init__(self, module):
|
|
||||||
self.__trainbuf = []
|
|
||||||
self.__rfm = RaspyRFM(module, RFM69)
|
self.__rfm = RaspyRFM(module, RFM69)
|
||||||
self.__rfm.set_params(
|
self.__rfm.set_params(
|
||||||
Freq = 433.92, #MHz
|
Freq = frequency, #MHz
|
||||||
Datarate = 20.0, #kbit/s
|
Bandwidth = 200, #kHz
|
||||||
Bandwidth = 300, #kHz
|
|
||||||
SyncPattern = [],
|
SyncPattern = [],
|
||||||
RssiThresh = -105, #dBm
|
RssiThresh = -105, #dBm
|
||||||
ModulationType = rfm69.OOK,
|
ModulationType = rfm69.OOK,
|
||||||
|
@ -553,58 +577,148 @@ class PulseTRX(threading.Thread):
|
||||||
Preamble = 0,
|
Preamble = 0,
|
||||||
TxPower = 13
|
TxPower = 13
|
||||||
)
|
)
|
||||||
|
self.__rxtraincb = rxcb
|
||||||
self.__event = threading.Event()
|
self.__event = threading.Event()
|
||||||
self.__event.set()
|
self.__event.set()
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
self.daemon = True
|
self.daemon = True
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def getEvents(self):
|
|
||||||
if len(self.__trainbuf) > 0:
|
|
||||||
train = self.__trainbuf.pop()
|
|
||||||
for i, v in enumerate(train):
|
|
||||||
train[i] = 50 * v
|
|
||||||
return decode(train)
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
self.__event.wait()
|
self.__event.wait()
|
||||||
rfm.set_params(
|
self.__rfm.set_params(
|
||||||
Datarate = 20.0 #kbit/s
|
Datarate = RXDATARATE #kbit/s
|
||||||
)
|
)
|
||||||
rfm.start_receive(self.__rxcb)
|
self.__rfm.start_receive(self.__rxcb)
|
||||||
|
|
||||||
|
def __rxcb(self, rfm):
|
||||||
def __cb(self, rfm):
|
|
||||||
bit = False
|
bit = False
|
||||||
cnt = 1
|
cnt = 1
|
||||||
train = []
|
train = []
|
||||||
|
bitfifo = 0
|
||||||
while True:
|
while self.__event.isSet():
|
||||||
fifo = rfm.read_fifo_wait(64)
|
fifo = rfm.read_fifo_wait(64)
|
||||||
ba = bytearray()
|
|
||||||
|
|
||||||
for b in fifo:
|
for b in fifo:
|
||||||
mask = 0x80
|
mask = 0x80
|
||||||
while mask != 0:
|
while mask != 0:
|
||||||
if (b & mask) != 0:
|
#bitfifo <<= 1
|
||||||
ba.append(245)
|
#if (b & mask != 0):
|
||||||
else:
|
# bitfifo |= 1
|
||||||
ba.append(10)
|
#v = bitfifo & 0x3
|
||||||
|
#c = 0
|
||||||
|
#while v > 0:
|
||||||
|
# v &= v - 1
|
||||||
|
# c += 1
|
||||||
|
newbit = (b & mask) != 0
|
||||||
|
|
||||||
if ((b & mask) != 0) == bit:
|
if newbit == bit:
|
||||||
cnt += 1
|
cnt += 1
|
||||||
else:
|
else:
|
||||||
if cnt < 3: #<150 us
|
if cnt < 150*RXDATARATE/1000: #<150 us
|
||||||
train *= 0 #clear
|
train *= 0 #clear
|
||||||
elif cnt > 50:
|
elif cnt > 3000*RXDATARATE/1000:
|
||||||
if not bit:
|
if not bit:
|
||||||
train.append(cnt)
|
train.append(cnt)
|
||||||
if len(train) > 20:
|
if len(train) > 20:
|
||||||
self.__trainbuf.append(list(train))
|
self.__rxtraincb(train)
|
||||||
train *= 0 #clear
|
train *= 0 #clear
|
||||||
elif len(train) > 0 or bit:
|
elif len(train) > 0 or bit:
|
||||||
train.append(cnt)
|
train.append(cnt)
|
||||||
cnt = 1
|
cnt = 1
|
||||||
bit = not bit
|
bit = not bit
|
||||||
mask >>= 1
|
mask >>= 1
|
||||||
|
|
||||||
|
def send(self, train, timebase, repetitions):
|
||||||
|
self.__event.clear()
|
||||||
|
self.__rfm.set_params(
|
||||||
|
Datarate = 1000.0 / timebase
|
||||||
|
)
|
||||||
|
self.__event.set()
|
||||||
|
self.__rfm.send(train * repetitions)
|
||||||
|
|
||||||
|
class RCStruct:
|
||||||
|
def __init__(self, **entries):
|
||||||
|
self.__dict__.update(entries)
|
||||||
|
|
||||||
|
class RcTransceiver(threading.Thread):
|
||||||
|
def __init__(self, module, frequency, rxcallback):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.__lock = threading.Lock()
|
||||||
|
self.__event = threading.Event()
|
||||||
|
self.__trainbuf = []
|
||||||
|
self.daemon = True
|
||||||
|
self.start()
|
||||||
|
self.__rxcb = rxcallback
|
||||||
|
self.__rfmtrx = RfmPulseTRX(module, self.__pushPulseTrain, frequency)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
del self.__rfmtrx
|
||||||
|
|
||||||
|
def __pushPulseTrain(self, train):
|
||||||
|
self.__lock.acquire()
|
||||||
|
self.__trainbuf.append(list(train))
|
||||||
|
self.__event.set()
|
||||||
|
self.__lock.release()
|
||||||
|
|
||||||
|
def __decode(self, train):
|
||||||
|
dec = None
|
||||||
|
res = []
|
||||||
|
succ = False
|
||||||
|
for p in protocols:
|
||||||
|
dec = p.decode(train)
|
||||||
|
if dec:
|
||||||
|
succ = True
|
||||||
|
if not dec[1]: #repeated?
|
||||||
|
res.append(dec[0])
|
||||||
|
return res, succ
|
||||||
|
|
||||||
|
def send_dict(self, dict):
|
||||||
|
s = RCStruct(**dict)
|
||||||
|
for p in protocols:
|
||||||
|
if p._name == s.protocol:
|
||||||
|
try:
|
||||||
|
txdata, tb, rep = p.encode(s)
|
||||||
|
if hasattr(s, "timebase"):
|
||||||
|
tb = s.timebase
|
||||||
|
if hasattr(s, "repeats"):
|
||||||
|
rep = s.repeats
|
||||||
|
print("repeats", rep)
|
||||||
|
self.__rfmtrx.send(txdata, tb, rep)
|
||||||
|
except:
|
||||||
|
print("Error in args!")
|
||||||
|
break
|
||||||
|
|
||||||
|
def send_args(self, protocol, args, timebase=None, repeats=None):
|
||||||
|
for p in protocols:
|
||||||
|
if p._name == protocol:
|
||||||
|
try:
|
||||||
|
txdata, tb, rep = p.encode(p._parser.parse_args(args))
|
||||||
|
if timebase:
|
||||||
|
tb = timebase
|
||||||
|
if repeats:
|
||||||
|
rep = repeats
|
||||||
|
self.__rfmtrx.send(txdata, tb, rep)
|
||||||
|
except:
|
||||||
|
print("Error in args!")
|
||||||
|
break
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
self.__event.wait()
|
||||||
|
self.__lock.acquire()
|
||||||
|
train = None
|
||||||
|
if len(self.__trainbuf) > 0:
|
||||||
|
train = self.__trainbuf.pop()
|
||||||
|
else:
|
||||||
|
self.__event.clear()
|
||||||
|
self.__lock.release()
|
||||||
|
if (train != None):
|
||||||
|
for i, v in enumerate(train):
|
||||||
|
train[i] = int(v * 1000 / RXDATARATE) #convert to microseconds
|
||||||
|
dec = self.__decode(train)
|
||||||
|
#dec[0]: array of decoded protocols
|
||||||
|
#dec[1]: true if at least 1 protocol was decoded
|
||||||
|
if (not dec[1]) or (len(dec[0]) > 0):
|
||||||
|
self.__rxcb(dec[0], train)
|
141
apps/rcpulse.py
141
apps/rcpulse.py
|
@ -3,7 +3,6 @@
|
||||||
from raspyrfm import *
|
from raspyrfm import *
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
#import fs20
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
import wave, struct
|
import wave, struct
|
||||||
import threading
|
import threading
|
||||||
|
@ -18,137 +17,29 @@ parser.add_argument("-p", "--protocol", help=u"Protocol for sending")
|
||||||
parser.add_argument("-w", "--write", help=u"write wavefile")
|
parser.add_argument("-w", "--write", help=u"write wavefile")
|
||||||
args, remainargs = parser.parse_known_args()
|
args, remainargs = parser.parse_known_args()
|
||||||
|
|
||||||
txdata = None
|
def rxcb(dec, train):
|
||||||
if len(remainargs) > 0:
|
for p in dec:
|
||||||
txdata = rcprotocols.encode(args.protocol, remainargs)
|
print(p)
|
||||||
|
if len(dec) == 0:
|
||||||
if txdata is None:
|
print(train)
|
||||||
print("invalid code!")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
if not raspyrfm_test(args.module, RFM69):
|
if not raspyrfm_test(args.module, RFM69):
|
||||||
print("Error! RaspyRFM not found")
|
print("Error! RaspyRFM not found")
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
rfm = RaspyRFM(args.module, RFM69)
|
rctrx = rcprotocols.RcTransceiver(args.module, args.frequency, rxcb)
|
||||||
rfm.set_params(
|
|
||||||
Freq = args.frequency, #MHz
|
|
||||||
Datarate = 20.0, #kbit/s
|
|
||||||
Bandwidth = 300, #kHz
|
|
||||||
SyncPattern = [],
|
|
||||||
RssiThresh = -105, #dBm
|
|
||||||
ModulationType = rfm69.OOK,
|
|
||||||
OokThreshType = 1, #peak thresh
|
|
||||||
OokPeakThreshDec = 3,
|
|
||||||
Preamble = 0,
|
|
||||||
TxPower = 13
|
|
||||||
)
|
|
||||||
|
|
||||||
if txdata:
|
if len(remainargs) > 0:
|
||||||
rfm.set_params(
|
rctrx.send_args(args.protocol, remainargs, args.timebase, args.repeats)
|
||||||
SyncPattern = [],
|
del rctrx
|
||||||
Datarate = 1000.0 / (args.timebase if args.timebase else txdata[1])
|
|
||||||
)
|
|
||||||
rep = (args.repeats if args.repeats else txdata[2])
|
|
||||||
rfm.send(txdata[0] * rep)
|
|
||||||
print("Code sent!")
|
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
trainbuf = []
|
state = 1
|
||||||
|
|
||||||
class RxThread(threading.Thread):
|
|
||||||
def __init__(self):
|
|
||||||
self.__event = threading.Event()
|
|
||||||
self.__event.set()
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
|
|
||||||
def __rxcb(self, rfm):
|
|
||||||
bit = False
|
|
||||||
cnt = 1
|
|
||||||
train = []
|
|
||||||
#if args.write:
|
|
||||||
# wf = wave.open(args.write, "wb")
|
|
||||||
# wf.setnchannels(1)
|
|
||||||
# wf.setsampwidth(1)
|
|
||||||
# wf.setframerate(20000)
|
|
||||||
#else:
|
|
||||||
wf = None
|
|
||||||
|
|
||||||
while self.__event.isSet():
|
|
||||||
fifo = rfm.read_fifo_wait(64)
|
|
||||||
ba = bytearray()
|
|
||||||
|
|
||||||
for b in fifo:
|
|
||||||
mask = 0x80
|
|
||||||
while mask != 0:
|
|
||||||
if (b & mask) != 0:
|
|
||||||
ba.append(245)
|
|
||||||
else:
|
|
||||||
ba.append(10)
|
|
||||||
|
|
||||||
if ((b & mask) != 0) == bit:
|
|
||||||
cnt += 1
|
|
||||||
else:
|
|
||||||
if cnt < 3: #<150 us
|
|
||||||
train *= 0 #clear
|
|
||||||
elif cnt > 50:
|
|
||||||
if not bit:
|
|
||||||
train.append(cnt)
|
|
||||||
if len(train) > 20:
|
|
||||||
trainbuf.append(list(train))
|
|
||||||
train *= 0 #clear
|
|
||||||
elif len(train) > 0 or bit:
|
|
||||||
train.append(cnt)
|
|
||||||
cnt = 1
|
|
||||||
bit = not bit
|
|
||||||
mask >>= 1
|
|
||||||
|
|
||||||
if wf:
|
|
||||||
wf.writeframesraw(ba)
|
|
||||||
wf.writeframes('')
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
while True:
|
|
||||||
self.__event.wait()
|
|
||||||
rfm.set_params(
|
|
||||||
Datarate = 20.0 #kbit/s
|
|
||||||
)
|
|
||||||
rfm.start_receive(self.__rxcb)
|
|
||||||
|
|
||||||
def suspend(self):
|
|
||||||
self.__event.clear()
|
|
||||||
|
|
||||||
def resume(self):
|
|
||||||
self.__event.set()
|
|
||||||
|
|
||||||
rxthread = RxThread()
|
|
||||||
rxthread.daemon = True
|
|
||||||
rxthread.start()
|
|
||||||
lasttime = time.time() + 3
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(0.1)
|
time.sleep(10)
|
||||||
if len(trainbuf) > 0:
|
|
||||||
train = trainbuf.pop()
|
|
||||||
for i, v in enumerate(train):
|
|
||||||
train[i] = v * 50
|
|
||||||
|
|
||||||
dec = rcprotocols.decode(train)
|
rctrx.send_dict({"protocol": "ittristate", "house": "A", "unit": 1, "state": state})
|
||||||
if (dec):
|
if (state == 1):
|
||||||
print(dec)
|
state = 0
|
||||||
else:
|
else:
|
||||||
print(train)
|
state = 1
|
||||||
|
|
||||||
if time.time() > lasttime:
|
|
||||||
lasttime = time.time() + 3
|
|
||||||
rxthread.suspend()
|
|
||||||
try:
|
|
||||||
txdata = rcprotocols.encode_dict({"protocol": "emylo", "id": 970046, "key": "A"})
|
|
||||||
rfm.set_params(
|
|
||||||
Datarate = 1000.0 / txdata[1]
|
|
||||||
)
|
|
||||||
rep = txdata[2]
|
|
||||||
rfm.send(txdata[0] * rep)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
rxthread.resume()
|
|
|
@ -9,27 +9,22 @@ from argparse import ArgumentParser
|
||||||
|
|
||||||
parser = ArgumentParser()
|
parser = ArgumentParser()
|
||||||
parser.add_argument("-m", "--module", type=int, metavar="1-4", help=u"RaspyRFM module 1-4", default=1)
|
parser.add_argument("-m", "--module", type=int, metavar="1-4", help=u"RaspyRFM module 1-4", default=1)
|
||||||
parser.add_argument("-o", "--mode", help=u"Mode (rcpulse, lacrosse)", default="rcpulse")
|
parser.add_argument("-f", "--frequency", type=float, help=u"frequency in MHz", default=433.92)
|
||||||
args = parser.parse_known_args()
|
args, remargs = parser.parse_known_args()
|
||||||
|
|
||||||
srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
srvsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
srvsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
srvsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
srvsock.bind(('', 1989))
|
srvsock.bind(('', 1989))
|
||||||
srvsock.listen(5)
|
srvsock.listen(5)
|
||||||
|
|
||||||
rfm = RaspyRFM(1, RFM69)
|
def rxcb(dec, train):
|
||||||
rfm.set_params(
|
pass
|
||||||
Freq = 433.92, #MHz
|
|
||||||
Datarate = 20.0, #kbit/s
|
if not raspyrfm_test(args.module, RFM69):
|
||||||
Bandwidth = 300, #kHz
|
print("Error! RaspyRFM not found")
|
||||||
SyncPattern = [],
|
exit()
|
||||||
RssiThresh = -105, #dBm
|
|
||||||
ModulationType = rfm69.OOK,
|
rctrx = rcprotocols.RcTransceiver(args.module, args.frequency, rxcb)
|
||||||
OokThreshType = 1, #peak thresh
|
|
||||||
OokPeakThreshDec = 3,
|
|
||||||
Preamble = 0,
|
|
||||||
TxPower = 13
|
|
||||||
)
|
|
||||||
|
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
|
|
||||||
|
@ -47,12 +42,8 @@ class clientthread(threading.Thread):
|
||||||
print(chunk)
|
print(chunk)
|
||||||
try:
|
try:
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
|
rctrx.send_dict(json.loads(chunk))
|
||||||
txdata = rcprotocols.encode_dict(json.loads(chunk))
|
txdata = rcprotocols.encode_dict(json.loads(chunk))
|
||||||
rfm.set_params(
|
|
||||||
SyncPattern = [],
|
|
||||||
Datarate = 1000.0 / txdata[1]
|
|
||||||
)
|
|
||||||
rfm.send(txdata[0] * txdata[2])
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
lock.release()
|
lock.release()
|
||||||
|
|
|
@ -338,7 +338,6 @@ class Rfm69(threading.Thread):
|
||||||
elif key == "Datarate":
|
elif key == "Datarate":
|
||||||
rate = int(round(FXOSC / (value * 1000)))
|
rate = int(round(FXOSC / (value * 1000)))
|
||||||
self.__write_reg_word(RegBitrateMsb, rate)
|
self.__write_reg_word(RegBitrateMsb, rate)
|
||||||
print("written datarate")
|
|
||||||
|
|
||||||
elif key == "Deviation":
|
elif key == "Deviation":
|
||||||
dev = int(round(value * 1000 / FSTEP))
|
dev = int(round(value * 1000 / FSTEP))
|
||||||
|
@ -530,9 +529,9 @@ class Rfm69(threading.Thread):
|
||||||
b = self.read_fifo_wait()
|
b = self.read_fifo_wait()
|
||||||
if b != 0:
|
if b != 0:
|
||||||
thresh += 1
|
thresh += 1
|
||||||
break;
|
break
|
||||||
if i == 149:
|
if i == 149:
|
||||||
break;
|
break
|
||||||
|
|
||||||
#restore registers
|
#restore registers
|
||||||
self.__write_reg(RegRssiThresh, rssithresh)
|
self.__write_reg(RegRssiThresh, rssithresh)
|
||||||
|
@ -556,7 +555,7 @@ class Rfm69(threading.Thread):
|
||||||
self.__wait_int()
|
self.__wait_int()
|
||||||
self.__mutex.acquire()
|
self.__mutex.acquire()
|
||||||
if self.__mode == MODE_RX:
|
if self.__mode == MODE_RX:
|
||||||
break;
|
break
|
||||||
|
|
||||||
def start_receive(self, cb):
|
def start_receive(self, cb):
|
||||||
self.__start_rx(0)
|
self.__start_rx(0)
|
||||||
|
|
121
rcpulse.py
121
rcpulse.py
|
@ -1,121 +0,0 @@
|
||||||
#!/usr/bin/env python2.7
|
|
||||||
|
|
||||||
from raspyrfm import *
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
from argparse import ArgumentParser
|
|
||||||
|
|
||||||
parser = ArgumentParser()
|
|
||||||
parser.add_argument("-t", "--timebase", type=int, help=u"timebase in \u03bcs")
|
|
||||||
parser.add_argument("-r", "--repeats", type=int, help=u"number of repetitions")
|
|
||||||
parser.add_argument("code", nargs='*', help="code, e. g. '000000000FFF', 'A 1 2 on' or '10111100011101011111111110001110'")
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
txdata = None
|
|
||||||
if len(args.code) > 0:
|
|
||||||
txdata = None
|
|
||||||
for proto in protos:
|
|
||||||
data = proto.Encode(args.code)
|
|
||||||
if data:
|
|
||||||
txdata = data
|
|
||||||
break
|
|
||||||
|
|
||||||
if txdata is None:
|
|
||||||
print("invalid code!")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
rfm = RaspyRFM(1, RFM69)
|
|
||||||
rfm.set_params(
|
|
||||||
Freq = 868.35, #MHz
|
|
||||||
Datarate = 20.0, #kbit/s
|
|
||||||
Bandwidth = 200, #kHz
|
|
||||||
SyncPattern = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07],
|
|
||||||
RssiThresh = -105, #dBm
|
|
||||||
ModulationType = rfm69.OOK,
|
|
||||||
OokThreshType = 1, #peak thresh
|
|
||||||
OokPeakThreshDec = 3,
|
|
||||||
)
|
|
||||||
|
|
||||||
if txdata:
|
|
||||||
rfm.SetParams(
|
|
||||||
SyncPattern = [],
|
|
||||||
Datarate = 5.0
|
|
||||||
)
|
|
||||||
rep = (args.repeats if args.repeats else txdata[1])
|
|
||||||
rfm.SendPacket(txdata[0] * rep)
|
|
||||||
print("Code sent!")
|
|
||||||
exit()
|
|
||||||
|
|
||||||
def Decode(pulses):
|
|
||||||
if len(pulses) != 118:
|
|
||||||
return;
|
|
||||||
|
|
||||||
b = ""
|
|
||||||
for p in pulses:
|
|
||||||
if (p>=6) and (p<=10):
|
|
||||||
b += "s"
|
|
||||||
elif (p > 10) and (p<15):
|
|
||||||
b += "l"
|
|
||||||
else:
|
|
||||||
b += '?'
|
|
||||||
s = ""
|
|
||||||
while len(b) > 0:
|
|
||||||
if b[:2] == 'ss':
|
|
||||||
s += '0'
|
|
||||||
elif b[:2] == 'll':
|
|
||||||
s += '1'
|
|
||||||
else:
|
|
||||||
s += '?'
|
|
||||||
b = b[2:]
|
|
||||||
print(s)
|
|
||||||
print("SYNC " + s[1:13] + " HC1 " + s[13:22] + " HC2 " + s[22:31] +
|
|
||||||
" ADR " + s[31:40])
|
|
||||||
return
|
|
||||||
for i in range(len(pulses)):
|
|
||||||
pulses[i] *= 50
|
|
||||||
|
|
||||||
dec = None
|
|
||||||
for proto in protos:
|
|
||||||
dec = proto.Decode(pulses)
|
|
||||||
if dec:
|
|
||||||
print(dec)
|
|
||||||
|
|
||||||
if not dec:
|
|
||||||
print("Len " + str(len(pulses)) + ": " + str(pulses))
|
|
||||||
|
|
||||||
while True:
|
|
||||||
data = rfm.receive_packet(400)
|
|
||||||
s = ""
|
|
||||||
|
|
||||||
pulsecount = 3
|
|
||||||
glitchcount = 0
|
|
||||||
bit = True
|
|
||||||
pulses = []
|
|
||||||
|
|
||||||
for d in data[0]:
|
|
||||||
s += format(d, '08b')
|
|
||||||
mask = 0x80
|
|
||||||
while mask > 0:
|
|
||||||
newbit = (d & mask) > 0
|
|
||||||
|
|
||||||
if glitchcount > 0:
|
|
||||||
glitchcount += 1
|
|
||||||
if newbit == bit:
|
|
||||||
pulsecount += glitchcount
|
|
||||||
glitchcount = 0
|
|
||||||
else:
|
|
||||||
if glitchcount == 3:
|
|
||||||
pulses.append(pulsecount)
|
|
||||||
if pulsecount > 50:
|
|
||||||
Decode(pulses)
|
|
||||||
pulses = []
|
|
||||||
bit = newbit
|
|
||||||
pulsecount = 3
|
|
||||||
glitchcount = 0
|
|
||||||
else:
|
|
||||||
if newbit == bit:
|
|
||||||
pulsecount += 1
|
|
||||||
else:
|
|
||||||
glitchcount = 1
|
|
||||||
|
|
||||||
mask >>= 1
|
|
Loading…
Reference in a new issue