diff --git a/apps/lacrosse.py b/apps/lacrosse.py index 932afe5..71751ef 100755 --- a/apps/lacrosse.py +++ b/apps/lacrosse.py @@ -34,7 +34,7 @@ class BaudChanger(threading.Thread): def run(self): while True: - time.sleep(15) + time.sleep(15) if self.baud: dr = 9.579 else: @@ -47,9 +47,8 @@ baudChanger = BaudChanger() baudChanger.daemon = True baudChanger.start() -print "Waiting for sensors..." while 1: - data = rfm.receive_packet(5) + data = rfm.receive(5) if data == None: continue diff --git a/influx.py b/apps/lacrossegw.py similarity index 93% rename from influx.py rename to apps/lacrossegw.py index fab6cf7..75371e5 100755 --- a/influx.py +++ b/apps/lacrossegw.py @@ -1,7 +1,6 @@ #!/usr/bin/env python2.7 -from rfm69 import Rfm69 -import rfm69 +from raspyrfm import * import sensors from sensors import rawsensor import sys @@ -25,12 +24,12 @@ nodes = { "f8": "Musikzimmer" } -if Rfm69.Test(1): +if raspyrfm_test(2, RFM69): print("Found RaspyRFM twin") - rfm = Rfm69(1, 24) #when using the RaspyRFM twin -elif Rfm69.Test(0): + rfm = RaspyRFM(2, RFM69) #when using the RaspyRFM twin +elif raspyrfm_test(1, RFM69): print("Found RaspyRFM single") - rfm = Rfm69() #when using a single single 868 MHz RaspyRFM + rfm = RaspyRFM(1, RFM69) #when using a single single 868 MHz RaspyRFM else: print("No RFM69 module found!") exit() @@ -50,14 +49,14 @@ try: except: print("mqtt init error") -rfm.SetParams( +rfm.set_params( Freq = 868.300, #MHz center frequency Datarate = 9.579, #kbit/s baudrate ModulationType = rfm69.FSK, #modulation Deviation = 30, #kHz frequency deviation OBW = 69.6/77.2 kHz, h = 6.3/3.5 SyncPattern = [0x2d, 0xd4], #syncword Bandwidth = 100, #kHz bandwidth - #AfcBandwidth = 150, + #AfcBandwidth = 150, #AfcFei = 0x0E, RssiThresh = -100, #-100 dB RSSI threshold ) @@ -103,7 +102,7 @@ def writeInflux(payload): print "Waiting for sensors..." cache = {} while 1: - rxObj = rfm.ReceivePacket(7) + rxObj = rfm.receive(7) try: sensorObj = rawsensor.CreateSensor(rxObj) diff --git a/apps/rcprotocols.py b/apps/rcprotocols.py new file mode 100644 index 0000000..ad7013b --- /dev/null +++ b/apps/rcprotocols.py @@ -0,0 +1,482 @@ +import re +from argparse import ArgumentParser + +class RcProtocol: + def __init__(self): + self.__numbits = 0 + self._ookdata = bytearray() + self.__bbuf = 0 + self.__bval = 0 + self._parser = ArgumentParser() + + sympulses = [] + for i in self._symbols: + sympulses += self._symbols[i] + sympulses.sort(reverse=True) + i = 0 + while i 0): + self.__bval ^= 1 + self._add_pulses([8 - self.__numbits]) + + def _add_symbols(self, symbols): + print(symbols) + for s in symbols: + sym = self._symbols[s] + for pulse in sym: + self._add_pulses([pulse]) + + def _match_symbol(self, pulsetrain, symbol): + if len(pulsetrain) != len(symbol): + return False + + sumpulse = 0 + sumstep = 0 + for i, v in enumerate(symbol): + if not (self._minwidth <= 1.0 * pulsetrain[i] / v <= self._maxwidth): + return + sumpulse += pulsetrain[i] + sumstep += v + return (sumpulse, sumstep) + + def _decode_symbols(self, pulsetrain): + #match symbols + dec = "" + pos = 0 + sumpulse = 0 + sumstep = 0 + while pos < len(pulsetrain): + match = None + for s in self._symbols: + slen = len(self._symbols[s]) + match = self._match_symbol(pulsetrain[pos:pos+slen], self._symbols[s]) + if match: + dec += s + pos += slen + sumpulse += match[0] + sumstep += match[1] + break + + if not match: + return None, None + + if re.match("^" + self._pattern + "$", dec): + return dec, int(1.0 * sumpulse / sumstep) + + return None, None + + def decode(self, pulsetrain): + pass + + def encode(self, args): + pass + +class IT32(RcProtocol): #switch1 + def __init__(self): + self._name = "it32" + self._timebase = 250 + self._repetitions = 4 + self._pattern = "[01]{32}" + self._symbols = { + '0': [1, 1, 1, 5], + '1': [1, 5, 1, 1], + } + RcProtocol.__init__(self) + self._parser.add_argument("-c", "--code") + self._parser.add_argument("-i", "--id", type=int, required=True) + self._parser.add_argument("-u", "--unit", type=int, required=True) + self._parser.add_argument("-s", "--state", type=int, required=True) + + def __encode(self, code): + self._reset() + self._add_pulses([1, 11]) + self._add_symbols(code) + self._add_pulses([1, 39]) + self._add_finish() + return self._ookdata + + def encode(self, args): + if args.code: + if re.match("^[01]{32}$", args.code): + return self.__encode(args.code) + + code = "" + code += "{:026b}".format(args.id) + code += "0" #group + code += "1" if args.state != 0 else "0" + code += "{:04b}".format(args.unit - 1) + return self.__encode(code) + + def decode(self, pulsetrain): + code, tb = self._decode_symbols(pulsetrain[0:-2]) + if code: + return { + "protocol": self._name, + "code": code, + "timebase": tb, + "id": int(code[0:26], 2), + "group": int(code[26:27], 2), + "state": int(code[27:28], 2), + "unit": int(code[28:32], 2) + 1, + } + +class ITTristate(RcProtocol): #old intertechno systems + def __init__(self): + self._name = "ittristate" + self._timebase = 300 + self._repetitions = 4 + self._pattern = "[01f]{12}" + self._symbols = { + '0': [1, 4, 1, 4], + '1': [4, 1, 4, 1], + 'f': [1, 4, 4, 1], + } + RcProtocol.__init__(self) + self._parser.add_argument("-c", "--code") + self._parser.add_argument("-o", "--house") + self._parser.add_argument("-g", "--group", type=int) + self._parser.add_argument("-u", "--unit", type=int) + self._parser.add_argument("-s", "--state", type=int) + + def decode(self, pulsetrain): + code, tb = self._decode_symbols(pulsetrain[0:-2]) + if code: + return { + "protocol": self._name, + "code": code, + "timebase": tb, + } + + def __encode(self, code): + self._reset() + self._add_symbols(code) + self._add_pulses([1, 31]) + self._add_finish() + return self._ookdata + + def __encode_int(self, ival, digits): + code = "" + for i in range(digits): + code += "f" if (ival & 0x01) > 0 else "0" + ival >>= 1 + return code + + def encode(self, args): + if args.code: + if re.match("^[01Ff]{12}$", args.code): + return self.__encode(args.code) + + code = "" + code += self.__encode_int(ord(args.house[0]) - ord('A'), 4) + if args.group: + code += self.__encode_int(args.group - 1, 2) + code += self.__encode_int(args.unit - 1, 2) + else: + code += self.__encode_int(args.unit - 1, 4) + code += "0f" + code += "ff" if args.state > 0 else "f0" + return self.__encode(code) + + +class Switch15(RcProtocol): #e. g. logilight + def __init__(self): + self._name = "switch15" + self._timebase = 300 + self._repetitions = 4 + self._pattern = "[01]{24}" + self._symbols = { + '1': [3, 1], + '0': [1, 3], + } + RcProtocol.__init__(self) + self._parser.add_argument("-i", "--id", type=int, required=True) + self._parser.add_argument("-u", "--unit", type=int, required=True) + self._parser.add_argument("-s", "--state", type=int, required=True) + + def decode(self, pulsetrain): + code, tb = self._decode_symbols(pulsetrain[0:-2]) + if code: + state = int(code[20:21]) + unit = int(code[21:24], 2) + all = False + if unit == 7: + unit = 1 + elif unit == 3: + unit = 2 + elif unit == 5: + unit = 3 + elif unit == 6: + unit = 4 + else: + unit = 0 + state = not state + + return { + "protocol": self._name, + "code": code, + "timebase": tb, + "id": int(code[0:20], 2), + "unit": unit, + "state": state, + } + + def encode(self, args): + sym = '{:020b}'.format(args.id) + + if args.unit == 1: + unit = 7 + elif args.unit == 2: + unit = 3 + elif args.unit == 3: + unit = 5 + elif args.unit == 4: + unit = 6 + else: + raise Exception("invalid unit") + sym += '1' if args.state > 0 else '0' + sym += '{:03b}'.format(unit) + self._add_symbols(sym) + self._add_pulses([1, 31]) + self._add_finish() + return self._ookdata + +class Emylo(Switch15): #e. g. logilight + def __init__(self): + Switch15.__init__(self) + self._name = "emylo" + + def decode(self, pulsetrain): + code, tb = self._decode_symbols(pulsetrain[0:-2]) + if code: + key = int(code[20:24], 2) + if key == 1: + key = 'A' + elif key == 2: + key = 'B' + elif key == 4: + key = 'C' + elif key == 8: + key = 'D' + else: + return + + return { + "protocol": self._name, + "code": code, + "timebase": tb, + "id": int(code[0:20], 2), + "key": key, + } + +class FS20(RcProtocol): + def __init__(self): + self._name = "fs20" + self._timebase = 200 + self._repetitions = 4 + self._pattern = "0000000000001[01]{45}" + self._symbols = { + '0': [2, 2], + '1': [3, 3], + } + RcProtocol.__init__(self) + self._parser.add_argument("-o", "--house", type=int, required=True) + self._parser.add_argument("-a", "--address", type=int, required=True) + self._parser.add_argument("-d", "--cmd", type=int, required=True) + + def __encode_byte(self, b): + self._add_symbols('{:08b}'.format(b)) + par = 0 + while b: + par ^= 1 + b &= b-1 + self._add_symbols('1' if par != 0 else '0') + + def encode(self, args): + self._reset() + self._add_symbols("0000000000001") + self.__encode_byte(args.house >> 8) + self.__encode_byte(args.house & 0xFF) + self.__encode_byte(args.address) + self.__encode_byte(args.cmd) + q = 0x06 + (args.house >> 8) + (args.house & 0xFF) + args.address + args.cmd + self.__encode_byte(q & 0xFF) + self._add_pulses([1, 100]) + self._add_finish() + return self._ookdata + + def decode(self, pulsetrain): + code, tb = self._decode_symbols(pulsetrain[0:-2]) + if code: + return { + "protocol": self._name, + "code": code, + "timebase": tb, + "housecode": int(code[13:21] + code[22:30] , 2), + "address": int(code[31:39], 2), + "cmd": int(code[40:48], 2), + } + +class Voltcraft(RcProtocol): + def __init__(self): + self._name = "voltcraft" + self._timebase = 600 + self._repetitions = 4 + self._pattern = "[01]{20}" + self._symbols = { + '0': [1, 2], + '1': [2, 1], + } + RcProtocol.__init__(self) + self._parser.add_argument("-i", "--id", type=int, required=True) + self._parser.add_argument("-u", "--unit", type=int, required=True) + self._parser.add_argument("-s", "--state", type=int, required=True) + + def decode(self, pulsetrain): + code, tb = self._decode_symbols(pulsetrain[1:-1]) + if code: + return { + "protocol": self._name, + "code": code, + "timebase": tb, + "id": int(code[0:12][::-1], 2), + "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 + } + + def encode(self, args): + if not (args.state in [0, 2]): + unit = 3 + else: + unit = args.unit -1 + symbols = "{:012b}".format(args.id)[::-1] + symbols += "{:02b}".format(unit)[::-1] + symbols += "{:03b}".format(args.state)[::-1] + symbols += "0" + symbols += "1" if (symbols[12] == "1") ^ (symbols[14] == "1") ^ (symbols[16] == "1") else "0" + symbols += "1" if (symbols[13] == "1") ^ (symbols[15] == "1") ^ (symbols[17] == "1") else "0" + self._reset() + self._add_pulses([1]) + self._add_symbols(symbols) + self._add_pulses([132]) + self._add_finish() + return self._ookdata + +class Test(RcProtocol): + def __init__(self): + self._name = "test" + self._timebase = 600 + self._repetitions = 4 + self._pattern = "[01]{32}" + self._symbols = { + '1': [1, 2], + '0': [2, 1], + } + RcProtocol.__init__(self) + self._parser.add_argument("-i", "--id", type=int, required=True) + self._parser.add_argument("-u", "--unit", type=int, required=True) + self._parser.add_argument("-s", "--state", type=int, required=True) + + def decode(self, pulsetrain): + code, tb = self._decode_symbols(pulsetrain[0:-2]) + if code: + print(code) + return code + state = int(code[20:21]) + unit = int(code[21:24], 2) + all = False + if unit == 7: + unit = 1 + elif unit == 3: + unit = 2 + elif unit == 5: + unit = 3 + elif unit == 6: + unit = 4 + else: + unit = 0 + state = not state + + return { + "protocol": self._name, + "code": code, + "timebase": tb, + "id": int(code[0:20], 2), + "unit": unit, + "state": state, + } + + def encode(self, args): + sym = '{:020b}'.format(args.id) + + if args.unit == 1: + unit = 7 + elif args.unit == 2: + unit = 3 + elif args.unit == 3: + unit = 5 + elif args.unit == 4: + unit = 6 + else: + raise Exception("invalid unit") + sym += '1' if args.state > 0 else '0' + sym += '{:03b}'.format(unit) + self._add_symbols(sym) + self._add_pulses([1, 31]) + self._add_finish() + return self._ookdata + +protocols = [ + IT32(), + Switch15(), + ITTristate(), + Voltcraft(), + FS20(), + Emylo(), + Test(), +] + +def encode(protocol, args): + for p in protocols: + if (protocol): + if p._name == protocol: + return (p.encode(p._parser.parse_args(args)), p._timebase, p._repetitions) + +def decode(pulsetrain): + dec = None + for p in protocols: + dec = p.decode(pulsetrain) + if dec: + print(dec) + + if not dec: + print(len(pulsetrain), pulsetrain) + \ No newline at end of file diff --git a/apps/rcpulse.py b/apps/rcpulse.py index 23a1223..5e91f97 100755 --- a/apps/rcpulse.py +++ b/apps/rcpulse.py @@ -9,42 +9,36 @@ import bistate24 import fs20 from argparse import ArgumentParser import wave, struct +import threading +import rcprotocols 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("-m", "--module", type=int, metavar="1-4", help=u"RaspyRFM module 1-4", default=1) parser.add_argument("-f", "--frequency", type=float, help=u"frequency in MHz", default=433.92) +parser.add_argument("-p", "--protocol", help=u"Protocol for sending") parser.add_argument("-w", "--write", help=u"write wavefile") -parser.add_argument("code", nargs='*', help="code, e. g. '000000000FFF', 'A 1 2 on' or '10111100011101011111111110001110'") -args = parser.parse_args() - -protos = [ - it32, - tristate, - bistate24, - fs20, -] +args, remainargs = parser.parse_known_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 len(remainargs) > 0: + txdata = rcprotocols.encode(args.protocol, remainargs) if txdata is None: print("invalid code!") exit() +if not raspyrfm_test(args.module, RFM69): + print("Error! RaspyRFM not found") + exit() + rfm = RaspyRFM(args.module, RFM69) rfm.set_params( Freq = args.frequency, #MHz Datarate = 20.0, #kbit/s - Bandwidth = 200, #kHz - SyncPattern = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F], + Bandwidth = 300, #kHz + SyncPattern = [], RssiThresh = -105, #dBm ModulationType = rfm69.OOK, OokThreshType = 1, #peak thresh @@ -53,163 +47,79 @@ rfm.set_params( TxPower = 13 ) -wf = wave.open("out.wav", "wb") -def rxcb(): - while True: - d = rfm.read_fifo_wait(64) - ba = bytearray() - for s in d: - mask = 0x80 - while mask > 0: - if (s & mask) > 0: - ba.append(255) - else: - ba.append(0) - mask >>= 1 - wf.writeframesraw(ba) - -if args.write: - wf.setnchannels(1) - wf.setsampwidth(1) - wf.setframerate(20000) - - rfm.set_params( - SyncPattern = [], - OokThreshType = 0, #fix thresh - OokFixedThresh = 85, - ) - rfm.start_rx(rxcb) - - wf.writeframes('') - wf.close() - print("WRITE!") - exit() - -rfm.set_params( - SyncPattern = [], - Datarate = 1.63, -) -i=[ - "01010011110011111110000111111111", - "01011101110011111110000111111111", - "01100011110011111110000111111111", - "01101101110011111110000111111111", -] -do=[] -b=0 -db=0 -def addpulse(h, l): - global do, b, db - for i in range(h): - db <<= 1 - db |= 1 - b += 1 - - if b == 8: - do.append(db) - db = 0 - b = 0 - - for i in range(l): - db <<= 1 - b += 1 - - if b == 8: - do.append(db) - db = 0 - b = 0 - -for c in i[args.timebase]: - if c == '0': - addpulse(2, 1) - else: - addpulse(1, 2) -addpulse(1, 17) -#print(do, b) -rfm.send_packet(do * 3) -exit() - -rfm.set_params( - Datarate = 20.0, #kbit/s - SyncPattern = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F], -) - if txdata: rfm.set_params( SyncPattern = [], - Datarate = 1000.0 / (args.timebase if args.timebase else txdata[2]) + Datarate = 1000.0 / (args.timebase if args.timebase else txdata[1]) ) - rep = (args.repeats if args.repeats else txdata[1]) - rfm.send_packet(txdata[0] * rep) + rep = (args.repeats if args.repeats else txdata[2]) + rfm.send(txdata[0] * rep) print("Code sent!") exit() -def Decode(pulses): - for i in range(len(pulses)): - pulses[i] *= 50 +trainbuf = [] - dec = None - for proto in protos: - dec = proto.Decode(pulses) - if dec: - print(dec) - - s = "" - if len(pulses) == 66: - for p in pulses: - if (p>900): - s += "l" - else: - s += "s" - b = "" - while len(s) > 0: - if s[:2] == "sl": - b += "1" - elif s[:2] == "ls": - b += "0" +class RxThread(threading.Thread): + def __init__(self): + 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: - b += "?" - s = s[2:] - #print(b) - - #print(len(pulses), pulses) + wf = None - #if not dec: - # print("Len " + str(len(pulses)) + ": " + str(pulses)) + while True: + 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): + rfm.start_receive(self.__rxcb) + +rxthread = RxThread() +rxthread.daemon = True +rxthread.start() while True: - data = rfm.receive_packet(260) - s = "" + time.sleep(0.1) + if len(trainbuf) > 0: + train = trainbuf.pop() + for i, v in enumerate(train): + train[i] = v * 50 - pulsecount = 4 - 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 + rcprotocols.decode(train) diff --git a/raspyrfm/rfm69.py b/raspyrfm/rfm69.py index dca47ac..7e5084b 100644 --- a/raspyrfm/rfm69.py +++ b/raspyrfm/rfm69.py @@ -6,40 +6,40 @@ import time FXOSC = 32E6 FSTEP = FXOSC / (1<<19) -#------ Raspberry RFM Module connection ----- +# Raspberry RFM Module connection # RaspyRFM single module # Connect to pins 17-26 on raspberry pi -#-------------------------------------------------# -# Raspi | Raspi | Raspi | RFM69 | RFM12 | PCB con # -# Name | GPIO | Pin | Name | Name | Pin # -#-------------------------------------------------# -# 3V3 | - | 17 | 3.3V | VDD | 1 # -# - | 24 | 18 | DIO1 | FFIT | 2 # only when PCB jumper closed -# MOSI | 10 | 19 | MOSI | SDI | 3 # -# GND | - | 20 | GND | GND | 4 # -# MISO | 9 | 21 | MISO | SDO | 5 # -# - | 25 | 22 | DIO0 | nIRQ | 6 # -# SCKL | 11 | 23 | SCK | SCK | 7 # -# CE0 | 8 | 24 | NSS | nSEL | 8 # -# CE1 | 7 | 26 | DIO2 | nFFS | 10 # only when PCB jumper closed -#-------------------------------------------------# +#--------------------------------# +#Raspi|Raspi|Raspi|RFM69|RaspyRFM# +#Name |GPIO |Pin |Name |PCB Pin # +#--------------------------------# +#3V3 | - | 17 |3.3V | 1 # +# - | 24 | 18 |DIO1 | 2 # only when PCB jumper closed +#MOSI | 10 | 19 |MOSI | 3 # +#GND | - | 20 |GND | 4 # +#MISO | 9 | 21 |MISO | 5 # +# - | 25 | 22 |DIO0 | 6 # +#SCKL | 11 | 23 |SCK | 7 # +#CE0 | 8 | 24 |NSS | 8 # +#CE1 | 7 | 26 |DIO2 | 10 # only when PCB jumper closed +#--------------------------------# # RaspyRFM twin module with 10-pin connector # Connect to pins 17-26 on raspberry pi -#-------------------------------------------------# -# Raspi | Raspi | Raspi | RFM69 | RFM12 | PCB con # -# Name | GPIO | Pin | Name | Name | Pin # -#-------------------------------------------------# -# 3V3 | - | 17 | 3.3V | VDD | 1 # -# - | 24 | 18 | DIO0_2| FFIT | 2 # -# MOSI | 10 | 19 | MOSI | SDI | 3 # -# GND | - | 20 | GND | GND | 4 # -# MISO | 9 | 21 | MISO | SDO | 5 # -# - | 25 | 22 | DIO0_1| nIRQ | 6 # -# SCKL | 11 | 23 | SCK | SCK | 7 # -# CE0 | 8 | 24 | NSS1 | nSEL | 8 # -# CE1 | 7 | 26 | NSS2 | nFFS | 10 # -#-------------------------------------------------# +#---------------------------------# +#Raspi|Raspi|Raspi|RFM69 |RaspyRFM# +#Name |GPIO |Pin |Name |PCB Pin # +#---------------------------------# +#3V3 | - | 17 |3.3V | 1 # +# - | 24 | 18 |DIO0_2| 2 # +#MOSI | 10 | 19 |MOSI | 3 # +#GND | - | 20 |GND | 4 # +#MISO | 9 | 21 |MISO | 5 # +# - | 25 | 22 |DIO0_1| 6 # +#SCKL | 11 | 23 |SCK | 7 # +#CE0 | 8 | 24 |NSS1 | 8 # +#CE1 | 7 | 26 |NSS2 | 10 # +#---------------------------------# # RaspyRFM twin module with 12-pin connector # Connect to pins 15-26 on raspberry pi @@ -441,7 +441,7 @@ class Rfm69(threading.Thread): lfsr |= 1<<9 lfsr >>= 1 - def send_packet(self, data): + def send(self, data): self.__mutex.acquire() self.__event.set() self.mode_standby() @@ -534,13 +534,13 @@ class Rfm69(threading.Thread): if self.__mode == MODE_RX: break; - def start_rx(self, cb): + def start_receive(self, cb): self.__start_rx() - cb() + cb(self) self.mode_standby() self.__mutex.release() - def receive_packet(self, length): + def receive(self, length): self.__start_rx() result = self.read_fifo_wait(length) diff --git a/rcpulse.py b/rcpulse.py new file mode 100755 index 0000000..c7e908a --- /dev/null +++ b/rcpulse.py @@ -0,0 +1,121 @@ +#!/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