From 7aa238d0299d4cfc14c13c89431b68bb213d3e99 Mon Sep 17 00:00:00 2001 From: Stefan Seegel Date: Wed, 22 Jan 2020 22:09:15 +0100 Subject: [PATCH] clean up & project reorganisation installable pythonmodule --- .gitignore | 3 + README.md | 67 ++-- RaspyRFM/__init__.py | 1 + RaspyRFM/raspyrfm.py | 558 ++++++++++++++++++++++++++++++++ apps/bistate24.py | 62 ++++ apps/connair.py | 63 ++++ apps/it32.py | 48 +++ lacrosse.py => apps/lacrosse.py | 13 +- apps/rcpulse.py | 106 ++++++ sensors.py => apps/sensors.py | 0 apps/tristate.py | 91 ++++++ culemu.py | 9 +- hamarx.py | 77 ----- intertechno.py | 91 ------ it32.py | 10 - logilightrx.py | 53 --- logilighttx.py | 37 --- rcs1000.py | 63 ---- setup.py | 18 ++ xx2262.py | 48 --- 20 files changed, 1000 insertions(+), 418 deletions(-) create mode 100644 RaspyRFM/__init__.py create mode 100644 RaspyRFM/raspyrfm.py create mode 100755 apps/bistate24.py create mode 100755 apps/connair.py create mode 100644 apps/it32.py rename lacrosse.py => apps/lacrosse.py (80%) create mode 100755 apps/rcpulse.py rename sensors.py => apps/sensors.py (100%) create mode 100755 apps/tristate.py delete mode 100755 hamarx.py delete mode 100755 intertechno.py delete mode 100644 it32.py delete mode 100755 logilightrx.py delete mode 100755 logilighttx.py delete mode 100755 rcs1000.py create mode 100755 setup.py delete mode 100755 xx2262.py diff --git a/.gitignore b/.gitignore index 0d20b64..08dc9de 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ *.pyc +/dist/ +/build/ +/*.egg-info diff --git a/README.md b/README.md index 18dc959..a0e995c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,39 @@ -# Python files for RaspyRFM +# Python module & examples for RaspyRFM +![RaspyRFM](img/raspberry-rfm69-ii_6_z4.jpg?raw=true "RasyRFM") + +#Installation +```sh +sudo su +apt-get install git-core python-dev +apt-get install python-pip + +cd #folder in which setup.py is located +pip install -e . +``` + +#Using python module and set parameters +```python +import RasyRFM +rfm = RaspyRFM.RaspyRFM() +rfm.SetParams( + Freq = 868.300, #MHz center frequency + ModulationType = rfm69.FSK, #modulation + Datarate = 9.992, #kbit/s baudrate + Deviation = 19.042, #kHz frequency deviation + SyncPattern = [0xc6, 0x26, 0xc6, 0x26], #syncword + Bandwidth = 100, #kHz bandwidth + RssiThresh = -105, #dBm RSSI threshold + TXPower = 13, #dBm + Preamble = 2, #bytes +) +``` ## connair.py -emulate a gateway for controlling RC socket. Compatible to "Brennenstuhl Brematic", Intertechno "ITGW-433", "ConnAir" +emulate a gateway for controlling RC sockets via the app power-switch. Compatible to "Brennenstuhl Brematic", Intertechno "ITGW-433", "ConnAir" see https://power-switch.eu/ ## emoncms.py -receive lacrosse-sensors and post them to the open energy monitor, see https://openenergymonitor.org/ +receive lacrosse-sensors with the RaspyRFM and post them to the open energy monitor, see https://openenergymonitor.org/ ## fs20tx.py controlling FS20 RX sockets @@ -16,19 +44,20 @@ sudo ./fs20tx
## intertechno.py controlling remote control sockets ```sh -intertechno on|off -intertechno <12 symbols tristate code> -intertechno <26 bit address> <1 goup bit> <4 bit unit> on|off -intertechno <32 bit code> +rcpulse on|off #control old intertechno sockets +rcpulse <12 symbols tristate code> #control old intertechno sockets +rcpulse <26 bit address 0|1> <1 goup bit 0|1> <4 bit unit 0|1> on|off #control intertechno self learning +rcpulse <32 bit code 0|1> #control intertechno and compatible (HAMA, REV) +rcpulse <5 DIP 0|1> on|off #control Brennenstuhl RC1000 usage example: -intertechno A 1 1 on -intertechno 0000FFFF0FFF -interttechno 11110000111100001111000010 0 1110 on -interttechno 11110000111100001111000010010000 +./rcpulse A 1 1 on +./rcpulse 0000FFFF0FFF +./rcpulse 11110000111100001111000010 0 1110 on +./rcpulse 11110000111100001111000010010000 ``` ## lacrosse.py -receiving temperature sensors +receiving lacrosse temperature sensors IT29-T, IT35-T, ... ```sh sudo ./lacrosse.py RFM69 found on CS 1 @@ -44,19 +73,5 @@ La crosse {'batlo': False, 'AFC': 308, 'init': False, 'T': (19.5, 'C'), 'RSSI': La crosse {'batlo': False, 'AFC': 376, 'init': False, 'T': (19.7, 'C'), 'RSSI': -103, 'RH': (57, '%'), 'ID': '24'} ``` -## rcs1000.py -controll Brennenstuhl RC1000 RC sockets -```sh -sudo ./rcs1000.py <5xDIPSWITCH> on|off -``` - -## rfm69.py -interfacing the RFM69 - -# Installation - * [Install GPIO](http://sourceforge.net/projects/raspberry-gpio-python/) -Version has to be >= 0.5.4 - * [Install SPI for Python](http://www.100randomtasks.com/simple-spi-on-raspberry-pi) - ## Product [Module RaspbyRFM Seegel Systeme](http://www.seegel-systeme.de/produkt/raspyrfm-ii/) diff --git a/RaspyRFM/__init__.py b/RaspyRFM/__init__.py new file mode 100644 index 0000000..0cfa381 --- /dev/null +++ b/RaspyRFM/__init__.py @@ -0,0 +1 @@ +from .raspyrfm import * diff --git a/RaspyRFM/raspyrfm.py b/RaspyRFM/raspyrfm.py new file mode 100644 index 0000000..4e8160a --- /dev/null +++ b/RaspyRFM/raspyrfm.py @@ -0,0 +1,558 @@ +import RPi.GPIO as GPIO +import spidev +import threading +import time + +FXOSC = 32E6 +FSTEP = FXOSC / (1<<19) + +#------ 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 +#-------------------------------------------------# + +# 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 # +#-------------------------------------------------# + +# RaspyRFM twin module with 12-pin connector +# Connect to pins 15-26 on raspberry pi +#-------------------------------------------------# +# Raspi | Raspi | Raspi | RFM69 | RFM12 | PCB con # +# Name | GPIO | Pin | Name | Name | Pin # +#-------------------------------------------------# +# - | 22 | 15 | DIO2_2| | 1 # +# - | 23 | 16 | DIO2_1| | 2 # +# 3V3 | - | 17 | 3.3V | VDD | 3 # +# - | 24 | 18 | DIO0_2| FFIT | 4 # +# MOSI | 10 | 19 | MOSI | SDI | 5 # +# GND | - | 20 | GND | GND | 6 # +# MISO | 9 | 21 | MISO | SDO | 7 # +# - | 25 | 22 | DIO0_1| nIRQ | 8 # +# SCKL | 11 | 23 | SCK | SCK | 9 # +# CE0 | 8 | 24 | NSS1 | nSEL | 10 # +# CE1 | 7 | 26 | NSS2 | nFFS | 12 # +#-------------------------------------------------# + +#RFM69 registers +#common registers +RegFifo = 0x00 +RegOpMode = 0x01 +RegDataModul = 0x02 +RegBitrateMsb = 0x03 +RegBitrateLsb = 0x04 +RegFdevMsb = 0x05 +RegFdevLsb = 0x06 +RegFrfMsb = 0x07 +RegFrfMid = 0x08 +RegFrfLsb = 0x09 +RegOsc1 = 0x0A +RegAfcCtrl = 0x0B +RegListen1 = 0x0D +RegListen2 = 0x0E +RegListen3 = 0x0F +RegVersion = 0x10 +#TX registers +RegPaLevel = 0x11 +RegPaRamp = 0x12 +RegOcp = 0x13 +#RX registers +RegLna = 0x18 +RegRxBw = 0x19 +RegAfcBw = 0x1A +RegOokPeak = 0x1B +RegOokAvg = 0x1C +RegOokFix = 0x1D +RegAfcFei = 0x1E +RegAfcMsb = 0x1F +RegAfcLsb = 0x20 +RegFeiMsb = 0x21 +RegFeiLsb = 0x22 +RegRssiConfig = 0x23 +RegRssiValue = 0x24 +#IRQ & pin mapping registers +RegDioMapping1 = 0x25 +RegDioMapping2 = 0x26 +RegIrqFlags1 = 0x27 +RegIrqFlags2 = 0x28 +RegRssiThresh = 0x29 +RegRxTimeout1 = 0x2A +RegRxTimeout2 = 0x2B +#packet engine registers +RegPreambleMsb = 0x2C +RegPreambleLsb = 0x2D +RegSyncConfig = 0x2E +RegSyncValue1 = 0x2F +RegPacketConfig1 = 0x37 +RegPayloadLength = 0x38 +RegNodeAdrs = 0x39 +RegBroadcastAdrs = 0x3A +RegAutoModes = 0x3B +RegFifoThresh = 0x3C +RegPacketConfig2 = 0x3D +RegTemp1 = 0x4E +RegTemp2 = 0x4F +RegTestLna = 0x58 +RegTestDagc = 0x6F +RegTestAfc = 0x71 + +InterPacketRxDelay = 4 #Bitposition +RestartRx = 2 +AutoRxRestartOn = 1 +AesOn = 0 + +#Modulation type +OOK = 1 +FSK = 0 + +#DcFree +DcFree_None = 0 +DcFree_Manchester = 1 +DcFree_Whitening = 2 + +#RFM69 modes +MODE_SLEEP = 0 +MODE_STDBY = 1 +MODE_FS = 2 +MODE_TX = 3 +MODE_RX = 4 + +#DIO packet mode +DIO0_PM_CRC = 0 +DIO0_PM_PAYLOAD = 1 +DIO0_PM_SYNC = 2 +DIO0_PM_RSSI = 3 +DIO0_PM_SENT = 0 +DIO0_PM_TXDONE = 1 +DIO0_PM_PLLLOCK = 3 + +class RaspyRFM(threading.Thread): + @staticmethod + def Test(cs): + spi = spidev.SpiDev() + spi.open(0, cs) + spi.max_speed_hz = 5000 + #Testing presence of module + err = False + for i in range(0, 8): + spi.xfer2([(RegSyncValue1 + i) | 0x80, 0x55]) + test = spi.xfer2([(RegSyncValue1 + i), 0x00])[1] + if test != 0x55: + err = True + break + temp = spi.xfer2([(RegSyncValue1 + i) | 0x80, 0xAA]) + test = spi.xfer2([(RegSyncValue1 + i), 0x00])[1] + if test != 0xAA: + err = True + break + spi.close() + return not err + + + def __init__(self, cs = 0, gpio_int = 25): + if not self.Test(cs): + print("ERROR! RFM69 not found") + return + + self.__event = threading.Event() + self.__spi = spidev.SpiDev() + self.__spi.open(0, cs) + self.__spi.max_speed_hz=int(5E6) + self.__gpio_int = gpio_int + self.__mutex = threading.Lock() + self.__syncsize = 4 + self.__fifothresh = 32 + + print("RFM69 found on CS " + str(cs)) + GPIO.setmode(GPIO.BCM) + GPIO.setup(gpio_int, GPIO.IN) + GPIO.add_event_detect(gpio_int, GPIO.RISING, callback=self.__RfmIrq) + + self.__SetMode(MODE_STDBY) + config = {} + + #SET DEFAULTS + config[RegOpMode] = 0x04 + config[RegDataModul] = 0x00 + config[RegBitrateMsb] = 0x1A + config[RegBitrateMsb + 1] = 0x0B + config[RegFdevMsb] = 0x00 + config[RegFdevMsb + 1] = 0x52 + config[RegFrfMsb] = 0xE4 + config[RegFrfMsb + 1] = 0xC0 + config[RegFrfMsb + 2] = 0x00 + config[RegOsc1] = 0x41 + config[RegAfcCtrl] = 0x00 + config[0x0C] = 0x02 # reserved + config[RegListen1] = 0x92 + config[RegListen2] = 0xF5 + config[RegListen3] = 0x20 + config[RegVersion] = 0x24 + config[RegPaLevel] = 0x9F + config[RegPaRamp] = 0x09 + config[RegOcp] = 0x1A + config[0x17] = 0x9B # reserved + config[RegLna] = 0x88 + config[RegRxBw] = 0x55 + config[RegAfcBw] = 0x8B + config[RegOokPeak] = 0x40 + config[RegOokAvg] = 0x80 + config[RegOokFix] = 0x06 + config[RegAfcFei] = 0x00 + config[RegAfcMsb] = 0x00 + config[RegAfcLsb] = 0x00 + config[RegFeiMsb] = 0x00 + config[RegFeiLsb] = 0x00 + config[RegRssiConfig] = 0x02 + config[RegDioMapping1] = 0x00 + config[RegDioMapping2] = 0x05 + config[RegIrqFlags1] = 0x80 + config[RegIrqFlags2] = 0x10 + config[RegRssiThresh] = 0xE4 + config[RegRxTimeout1] = 0x00 + config[RegRxTimeout2] = 0x00 + config[RegPreambleMsb] = 0x00 + config[RegPreambleLsb] = 0x00 + config[RegSyncConfig] = 0x98 + config[RegPacketConfig1] = 0x10 + config[RegPayloadLength] = 0x40 + config[RegNodeAdrs] = 0x00 + config[RegBroadcastAdrs] = 0x00 + config[RegAutoModes] = 0 + config[RegFifoThresh] = 0x8F + config[RegPacketConfig2] = 0x02 + config[RegTemp1] = 0x01 + config[RegTemp2] = 0x00 + config[RegTestLna] = 0x1B + config[RegTestDagc] = 0x30 #low beta 0 + config[RegTestAfc] = 0x00 + + config[RegPacketConfig1] = 0x00 #Fixed length, CRC off, no adr + + for key in config: + self.__WriteReg(key, config[key]) + + self.ModeStandBy() + threading.Thread.__init__(self) + print("Init complete.") + + def run(self): + while True: + time.sleep(0.5) + + def __RfmIrq(self, ch): + self.__event.set() + + def __WriteReg(self, reg, val): + temp = self.__spi.xfer2([(reg & 0x7F) | 0x80, val & 0xFF]) + + def __WriteRegWord(self, reg, val): + self.__WriteReg(reg, (val >> 8) & 0xFF) + self.__WriteReg(reg + 1, val & 0xFF) + + def __SetReg(self, reg, mask, val): + temp = self.ReadReg(reg) & (~mask) + temp |= val & mask + self.__WriteReg(reg, temp) + + def __SetDioMapping(self, dio, mapping): + if ((dio >= 0) and (dio <=3)): + self.__SetReg(RegDioMapping1, 0xC0 >> (dio * 2), mapping << (6 - dio * 2)) + elif (dio == 5): + self.__SetReg(RegDioMapping2, 0x03 << 4, mapping << 4) + + def __SetMode(self, mode): + self.__WriteReg(RegOpMode, mode << 2) + self.__mode = mode + while ((self.ReadReg(RegIrqFlags1) & (1<<7)) == 0): + pass + + def ReadReg(self, reg): + temp = self.__spi.xfer2([reg & 0x7F, 0x00]) + return temp[1] + + def ReadFifoBurst(self, len): + temp = self.__spi.xfer2([0x00] + [0x00] * len) + return temp[1:] + + def WriteFifoBurst(self, data): + self.__spi.xfer2([0x80] + list(data)) + + def ReadRegWord(self, reg): + temp = self.__spi.xfer2([reg & 0x7F, 0x00, 0x00]) + return (temp[1] << 8) | (temp[2]) + + def ReadRssiValue(self): + return self.ReadReg(RegRssiValue) + + def ModeStandBy(self): + self.__SetMode(MODE_STDBY) + + def SetParams(self, **params): + self.__mutex.acquire() + self.__event.set() + for key in params: + value = params[key] + if key == "Freq": + fword = int(round(value * 1E6 / FSTEP)) + self.__WriteReg(RegFrfMsb, fword >> 16) + self.__WriteReg(RegFrfMid, fword >> 8) + self.__WriteReg(RegFrfLsb, fword) + + elif key == "TXPower": + pwr = int(value + 18) + self.__WriteReg(RegPaLevel, 0x80 | (pwr & 0x1F)) + + elif key == "Datarate": + rate = int(round(FXOSC / (value * 1000))) + self.__WriteRegWord(RegBitrateMsb, rate) + + elif key == "Deviation": + dev = int(round(value * 1000 / FSTEP)) + self.__WriteRegWord(RegFdevMsb, dev) + + elif key == "ModulationType": + self.__SetReg(RegDataModul, 0x18, value << 3) + + elif key == "ModulationsShaping": + self.__SetReg(RegDataModul, 0x03, value) + + elif key == "SyncPattern": + conf = 0 + self.__syncsize = len(value) + if (len(value)) > 0: + conf = ((len(value) - 1) & 0x07) << 3 + conf |= 1<<7 + else: + conf = 1<<6 + self.__WriteReg(RegSyncConfig, conf) + for i, d in enumerate(value): + self.__WriteReg(RegSyncValue1 + i, d) + + elif key == "Bandwidth": + RxBw = FXOSC / value / 1000 / 4 + e = 0 + while (RxBw > 32) and (e < 7): + e += 1 + RxBw /= 2 + RxBw = RxBw / 4 - 4 + RxBw = max(RxBw, 0) + m = int(RxBw) + self.__SetReg(RegRxBw, 0x1F, m<<3 | e) + + elif key == "AfcBandwidth": + RxBw = FXOSC / value / 1000 / 4 + e = 0 + while (RxBw > 32) and (e < 7): + e += 1 + RxBw /= 2 + RxBw = RxBw / 4 - 4 + RxBw = max(RxBw, 0) + m = int(RxBw) + self.__SetReg(RegAfcBw, 0x1F, m<<3 | e) + + elif key == "Preamble": + self.__WriteRegWord(RegPreambleMsb, value) + + elif key == "LnaGain": + self.__SetReg(RegLna, 0x07, value) + + elif key == "RssiThresh": + th = -(value * 2) + self.__WriteReg(RegRssiThresh, th) + + elif key == "Dagc": + self.__WriteReg(RegDagc, value) + + elif key == "AfcFei": + self.__WriteReg(RegAfcFei, value) + + elif key == "Callback": + self.__Callback = value + + elif key == "DcFree": + self.__SetReg(RegPacketConfig1, 3<<5, value<<5) + + elif key == "OokThreshType": + self.__SetReg(RegOokPeak, 3<<6, value<<6) + + elif key == "OokFixedThresh": + self.__WriteReg(RegOokFix, value) + + elif key == "OokPeakThreshDec": + self.__SetReg(RegOokPeak, 7<<0, value) + + else: + print("Unrecognized option >>" + key + "<<") + + self.ModeStandBy(); + self.__mutex.release() + + def __WaitInt(self): + self.__event.clear() + if GPIO.input(self.__gpio_int): + return + while not self.__event.wait(0.5): + if GPIO.input(self.__gpio_int): + break + + def WhitenHope(self, data): + lfsr = 0x3fe + for i, d in enumerate(data): + data[i] = data[i] ^ ((lfsr >> 2) & 0xFF) + #roll LFSR + for j in range(8): + if ((lfsr >> 5) ^ lfsr) & 0x10 != 0: + lfsr |= 1<<0 + lfsr <<= 1 + lfsr &= 0x3ff + + def WhitenTI(self, data): + lfsr = 0x1ff + for i, d in enumerate(data): + data[i] = data[i] ^ (lfsr & 0xFF) + for i in range(8): + if ((lfsr >> 5) ^ lfsr) & 0x01 != 0: + lfsr |= 1<<9 + lfsr >>= 1 + + def SendPacket(self, data): + self.__mutex.acquire() + self.__event.set() + self.ModeStandBy() + + #flush FIFO + status = self.ReadReg(RegIrqFlags2) + while (status & 0x40 == 0x40): + self.ReadReg(RegFifo) + status = self.ReadReg(RegIrqFlags2) + + self.__WriteReg(RegPayloadLength, 0) #unlimited length + self.__WriteReg(RegFifoThresh, 0x80 | self.__fifothresh) #start TX with 1st byte in FIFO + self.__SetDioMapping(0, DIO0_PM_SENT) #DIO0 -> PacketSent + self.__SetMode(MODE_TX) + + l = min(len(data), 64) + while True: + self.WriteFifoBurst(data[:l]) + data = data[l:] + if len(data) == 0: + break + while True: + status = self.ReadReg(RegIrqFlags2) + if (status & (1<<5)) == 0: #below fifothresh + l = min(len(data), self.__fifothresh) + break + if (status & (1<<7)) == 0: #space for at least 1 bytearray + l = 1 + break + + self.__WaitInt() + self.ModeStandBy() + self.__mutex.release() + + def ReadFifoWait(self, length): + ret = [] + while length > 0: + flags = self.ReadReg(RegIrqFlags2) + if ((flags & (1<<5)) != 0) and (length >= 32): #FIFO level? + ret += self.ReadFifoBurst(self.__fifothresh) + length -= self.__fifothresh + if (flags & (1<<6)) != 0: #FIFO not empty? + ret.append(self.ReadReg(RegFifo)) + length -= 1 + return ret + + def GetNoiseFloor(self): + self.__mutex.acquire() + #save values + rssithresh = self.ReadReg(RegRssiThresh) + ookthresh = self.ReadReg(RegOokFix) + sync = self.ReadReg(RegSyncConfig) + + self.__WriteReg(RegRssiThresh, 240) + self.__WriteReg(RegSyncConfig, 1<<6) #no sync, always fill FIFO + self.__WriteReg(RegPayloadLength, 0) #unlimited length + self.__SetMode(MODE_RX) + thresh = 40 + while True: + self.__WriteReg(RegOokFix, thresh) + for i in range(150): + b = self.ReadFifoWait() + if b != 0: + thresh += 1 + break; + if i == 149: + break; + + #restore registers + self.__WriteReg(RegRssiThresh, rssithresh) + self.__WriteReg(RegOokFix, ookthresh) + self.__WriteReg(RegSyncConfig, sync) + self.ModeStandBy() + self.__mutex.release() + return thresh + + def __StartRx(self): + self.__SetDioMapping(2, 1) #DIO2 -> DATA + self.__mutex.acquire() + while True: + self.__WriteReg(RegPayloadLength, 0) #unlimited length + self.__WriteReg(RegFifoThresh, self.__fifothresh) + if self.__syncsize > 0: + self.__SetDioMapping(0, DIO0_PM_SYNC) #DIO0 -> SyncAddress + else: + self.__SetDioMapping(0, DIO0_PM_RSSI) #DIO0 -> RSSI + self.__SetMode(MODE_RX) + self.__mutex.release() + self.__WaitInt() + self.__mutex.acquire() + if self.__mode == MODE_RX: + break; + + def StartRx(self, cb): + self.__StartRx() + cb() + self.ModeStandBy() + self.__mutex.release() + + def ReceivePacket(self, length): + self.__StartRx() + result = self.ReadFifoWait(length) + + rssi = -self.ReadReg(RegRssiValue) / 2 + afc = self.ReadReg(RegAfcMsb) << 8 + afc = afc | self.ReadReg(RegAfcLsb) + + if afc >= 0x8000: + afc = afc - 0x10000 + + self.ModeStandBy() + self.__mutex.release() + return (result, rssi, afc) diff --git a/apps/bistate24.py b/apps/bistate24.py new file mode 100755 index 0000000..a6c9e46 --- /dev/null +++ b/apps/bistate24.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python2.7 + +import re + +def Decode(pulses): + if len(pulses) != 50: + return + + sym = "" + s = 0 + for p in pulses: + if (p >= 200) and (p <= 450): + sym += 's' + s += p + elif (p >= 600) and (p <= 1350): + sym += 'l' + s += p + else: + sym += '?' + + code = "" + for i in range(24): + if sym[:2] == 'sl': + code += "0" + elif sym[:2] == "ls": + code += "1" + else: + return + sym = sym[2:] + + return ("bistate24", code, int(round(s / (24.0 * 4 + 1)))) + +def Encode(args): + code = ' '.join(args) + if re.match("^[01]{24}$", code): + data = [] + d = 0 + pos = 4 + for c in code: + d |= (0x8 if c == '0' else 0xe) << pos + if pos == 0: + data.append(d) + d = 0 + pos = 4 + else: + pos = 0 + + data += [0x80, 0x00, 0x00, 0x00] + return (data, 5, 330) + + elif re.match("^([01]{20}) ([A])$", code): + g = re.match("^([01]{20}) ([ABCD])$", code).groups() + bits = g[0] + if g[1] == 'A': + bits += '0001' + elif g[1] == 'B': + bits += '0010' + elif g[1] == 'C': + bits += '0100' + elif g[1] == 'D': + bits += '1000' + return Encode([bits]) diff --git a/apps/connair.py b/apps/connair.py new file mode 100755 index 0000000..67e70c7 --- /dev/null +++ b/apps/connair.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python2.7 + +import socket +import RaspyRFM +import sys + +UDP_IP = "0.0.0.0" +UDP_PORT = 49880 +HELLO_MESSAGE = "HCGW:VC:Seegel Systeme;MC:RaspyRFM;FW:1.00;IP:0.0.0.0;;" + +sock = socket.socket(socket.AF_INET, # Internet + socket.SOCK_DGRAM) # UDP +sock.bind((UDP_IP, UDP_PORT)) + +rfm = RaspyRFM.RaspyRFM() +rfm.SetParams( + Freq = 433.92, + TXPower = 13, + ModulationType = rfm69.OOK, + SyncPattern = [], + ) + +print("Listening...") +while True: + data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes + print("received message from " + addr[0] + ': ' + str(data)) + print(sock) + msg = str(data).split(":") + + if msg[0] == "SEARCH HCGW": + print("Hello message") + sock.sendto(HELLO_MESSAGE, addr) + + if msg[0] == "TXP": + msg[1] = msg[1].replace(";", "") + cmd = msg[1].split(",") + rep = int(cmd[2]) + pauselen = int(cmd[3]) + steplen = int(cmd[4]) + numpulse = int(cmd[5]) + pulsedata = cmd[6:] + pulsedata[numpulse * 2 - 1] = int(pulsedata[numpulse * 2 - 1]) + pauselen / steplen + + bindata = [] + bit = True + numbit = 0 + bitleft = 0 + for i in range(numpulse * 2): + for bits in range(int(pulsedata[i])): + if bitleft == 0: + bitleft = 8 + bindata.append(0x00) + + bindata[len(bindata) - 1] <<= 1 + if bit: + bindata[len(bindata) - 1] |= 0x01 + bitleft -= 1 + bit = not bit + for i in range(bitleft): + bindata[len(bindata) - 1] <<= 1 + + rfm.SetParams(Datarate = 1000.0 / steplen) + rfm.SendPacket(bindata * rep) diff --git a/apps/it32.py b/apps/it32.py new file mode 100644 index 0000000..abe5d64 --- /dev/null +++ b/apps/it32.py @@ -0,0 +1,48 @@ +import re + +def Decode(pulses): + if len(pulses) != 130: + return + + sym = "" + s = 0 + for p in pulses: + if (p >= 150) and (p <= 500): + s += p + sym += 's' + elif (p >= 1000) and (p <= 1500): + s += p + sym += 'l' + else: + sym += '?' + + it = "" + temp = sym + for i in range(32): + if temp[:4] == 'sssl': + it += "0" + elif temp[:4] == "slss": + it += "1" + else: + return + temp = temp[4:] + return("it32", it, int(round(s / (32.0 * 8 + 1)))) + +def Encode(args): + code = ' '.join(args) + if re.match("^[01]{32}$", code): + data = [0x08, 0x00] #sync + for c in args[0]: + if c == '0': + data.append(0xA0) + elif c == '1': + data.append(0x82) + data += [0x80, 0x00, 0x00, 0x00, 0x00] + return (data, 6, 275) + + elif re.match("^[01]{26} ([0][1-9]|[1-9]|[1][0-6]) (on|off)$", code): + g = re.match("^([01]{26}) ([0][1-9]|[1-9]|[1][0-6]) (on|off)$", code).groups() + bits = g[0] + '0' + bits += '1' if g[2] == 'on' else '0' + bits += "{0:04b}".format(int(g[1]) - 1) + return Encode([bits]) \ No newline at end of file diff --git a/lacrosse.py b/apps/lacrosse.py similarity index 80% rename from lacrosse.py rename to apps/lacrosse.py index 82b0b92..909fcd1 100755 --- a/lacrosse.py +++ b/apps/lacrosse.py @@ -1,19 +1,18 @@ #!/usr/bin/env python2.7 -from rfm69 import Rfm69 -import rfm69 +import RaspyRFM import sensors from sensors import rawsensor import sys import time import threading -if Rfm69.Test(1): +if RaspyRFM.RaspyRFM.Test(1): print("Found RaspyRFM twin") - rfm = Rfm69(1, 24) #when using the RaspyRFM twin -elif Rfm69.Test(0): + rfm = RaspyRFM.RaspyRFM(1, 24) #when using the RaspyRFM twin +elif RaspyRFM.RaspyRFM.Test(0): print("Found RaspyRFM single") - rfm = Rfm69() #when using a single single 868 MHz RaspyRFM + rfm = RaspyRFM.RaspyRFM() #when using a single single 868 MHz RaspyRFM else: print("No RFM69 module found!") exit() @@ -21,7 +20,7 @@ else: rfm.SetParams( Freq = 868.30, #MHz center frequency Datarate = 9.579, #kbit/s baudrate - ModulationType = rfm69.FSK, #modulation + ModulationType = RaspyRFM.FSK, #modulation Deviation = 30, #kHz frequency deviation SyncPattern = [0x2d, 0xd4], #syncword Bandwidth = 150, #kHz bandwidth diff --git a/apps/rcpulse.py b/apps/rcpulse.py new file mode 100755 index 0000000..e051fe0 --- /dev/null +++ b/apps/rcpulse.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python2.7 + +import RaspyRFM +import sys +import time +import it32 +import tristate +import bistate24 +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() + +protos = [ + it32, + tristate, + bistate24, +] + +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.RaspyRFM() +rfm.SetParams( + Freq = 433.92, #MHz + Datarate = 20.0, #kbit/s + Bandwidth = 200, #kHz + SyncPattern = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F], + RssiThresh = -105, #dBm + ModulationType = RaspyRFM.OOK, + OokThreshType = 1, #peak thresh + OokPeakThreshDec = 3, +) + +if txdata: + rfm.SetParams( + SyncPattern = [], + Datarate = 1000.0 / (args.timebase if args.timebase else txdata[2]) + ) + rep = (args.repeats if args.repeats else txdata[1]) + rfm.SendPacket(txdata[0] * rep) + print("Code sent!") + exit() + +def Decode(pulses): + 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.ReceivePacket(260) + s = "" + + pulsecount = 7 + 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 diff --git a/sensors.py b/apps/sensors.py similarity index 100% rename from sensors.py rename to apps/sensors.py diff --git a/apps/tristate.py b/apps/tristate.py new file mode 100755 index 0000000..a9fd9e9 --- /dev/null +++ b/apps/tristate.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python2.7 + +import re + +def Decode(pulses): + if len(pulses) != 50: + return + + sym = "" + s = 0 + for p in pulses: + if (p >= 200) and (p <= 450): + sym += 's' + s += p + elif (p >= 600) and (p <= 1350): + sym += 'l' + s += p + else: + sym += '?' + + code = "" + temp = sym + for i in range(12): + if temp[:4] == 'slsl': + code += "0" + elif temp[:4] == "lsls": + code += "1" + elif temp[:4] == "slls": + code += "f" + else: + return + temp = temp[4:] + + return ("tristate", code, int(round(s / (12.0 * 8 + 1)))) + +def encodeBits(val, num): + result = '' + for i in range(num): + if (val & 0x01): + result += 'F' + else: + result += '0' + val >>= 1 + return result + +def Encode(args): + code = ' '.join(args) + if re.match("^[01Ff]{12}$", code): + data = [] + for c in code: + if c == '0': + data.append(0x88) + elif c == '1': + data.append(0xEE) + elif c in ['F', 'f']: + data.append(0x8E) + data += [0x80, 0x00, 0x00, 0x00] #sync + + return (data, 5, 360) + + elif re.match('^[A-P] [1-4] [1-4] (on|off)$', code): + g = re.match('^([A-P]) ([1-4]) ([1-4]) (on|off)$', code).groups() + tristate = "" + tristate += encodeBits(ord(g[0]) - ord('A'), 4) #housecode + tristate += encodeBits(ord(g[2]) - 1, 2) #channel + tristate += encodeBits(ord(g[1]) - 1, 2) #group + tristate += "0F" + tristate += 'FF' if g[3] == 'on' else 'F0' + return Encode([tristate]) + + elif re.match('^([01]{5}) ([1-4]) (on|off)$', code): #Brennenstuhl + g = re.match('^([01]{5}) ([1-4]) (on|off)$', code).groups() + tristate = "" + for c in g[0]: + tristate += '0' if c == '1' else 'F' + for i in range(4): + tristate += '0' if int(g[1]) - 1 == i else 'F' + tristate += 'F' + tristate += '0F' if g[2] == 'on' else 'F0' + return Encode([tristate]) + + elif re.match('^[1-4] [1-4] (on|off)$', code): + g = re.match('^([1-4]) ([1-4]) (on|off)$', code).groups() + tristate = "" + for i in range(4): + tristate += "0" if int(g[0]) - 1 == i else "F" + for i in range(4): + tristate += "0" if int(g[1]) - 1 == i else "F" + tristate += "FFF" + tristate += 'F' if g[2] == 'on' else '0' + return Encode([tristate]) \ No newline at end of file diff --git a/culemu.py b/culemu.py index 89684d4..2a07bc0 100755 --- a/culemu.py +++ b/culemu.py @@ -67,7 +67,7 @@ class Connection(threading.Thread): lines = str.splitlines(data) for line in lines: - #print("FROM FHEM: " + line) + print("FROM FHEM: " + line) if line == 'V': self.sendHost("V 1.0 CULEMU") @@ -146,12 +146,9 @@ cul.start() class RxThread(threading.Thread): def __init__(self, rfm): self.__rfm = rfm - rfm.SetParams( - CallbackSync = self.__callback - ) threading.Thread.__init__(self) - def __callback(self): + def callback(self): lfsr = 0x1ff frame = rfm.ReadFifoWait(1) len = frame[0] ^ 0xFF #invert due to whitening @@ -192,4 +189,4 @@ rxthread.daemon = True rxthread.start() while True: - data = rfm.ReceivePacket(0) + data = rfm.StartRx(rxthread.callback) diff --git a/hamarx.py b/hamarx.py deleted file mode 100755 index dc1a10d..0000000 --- a/hamarx.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 - -from rfm69 import Rfm69 -import rfm69 -import sys -import time -#import types -#import os - -rfm = Rfm69() -rfm.SetParams( - Freq = 433.944, - Datarate = 4.0, #1 / 250E-06 / 1000, - Bandwidth = 24000, - SyncPattern = [0x00, 0x08, 0x00], - RssiThresh = -80, - ModulationType = rfm69.OOK - ) - -def staff(byte): - res = 0 - res |= (byte & 1<<7) >> 4 - res |= (byte & 1<<5) >> 3 - res |= (byte & 1<<3) >> 2 - res |= (byte & 1<<1) >> 1 - return res - -def decode(bindata): - netdata = [0x00, 0x00, 0x00, 0x00] - for i in range(0, 64, 2): - if (bindata[i / 8] >> (i % 8)) & 0x01 == (bindata[i / 8] >> (i % 8 + 1)) & 0x01: - print "Error", i, hex(bindata[i / 8]), hex(bindata[i / 8] >> (i % 8)) - for i in range(4): - netdata[i] = staff(bindata[i * 2]) << 4 | staff(bindata[i * 2 + 1]) - - print "decode: ", - for i in range(4): - print "{0:{fill}2x}".format(netdata[i], fill='0'), - print "" - -while True: - data = rfm.ReceivePacket(60) - zcount = 0 - bindata = [] - binval = 0 - binmask = 0x80 - for d in data[0]: - rawmask = 0x80 - while (rawmask > 0) and (len(bindata) < 8): - if (d & rawmask) > 0: - if zcount == 1: - binval |= binmask - binmask >>= 1 - - if zcount == 5: - binmask >>= 1 - - if zcount == 11: - print "Received pause" - - if zcount == 41: - print "SYNC" - - zcount = 0 - else: - zcount += 1 - rawmask >>= 1 - - if binmask == 0: - bindata.append(binval) - binmask = 0x80 - binval = 0 - - if len(bindata) == 8: - decode(bindata) - break; - diff --git a/intertechno.py b/intertechno.py deleted file mode 100755 index 500ea04..0000000 --- a/intertechno.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python2.7 - -import rfm69 -from rfm69 import Rfm69 -import xx2262 -import it32 -import sys -import re - -def encodeBits(val, num, pol, inv): - result = '' - for i in range(num): - if (val & 0x01) ^ inv: - result += 'F' - else: - result += pol - val >>= 1 - return result - -def usage(): - print "usage:" - print "intertechno on|off" #12-digit code 12 * ['0' | '1' | 'f'] - print "intertechno <12 symbols tristate code>" - print "intertechno <26 bit address> <1 goup bit> <4 bit unit> on|off" - print "intertechno <32 bit code>" - print "Examples:" - print "intertechno A 1 1 on" - print "intertechno 0000FFFF0FFF" - print "intertechno 11110000111100001111000010 0 1110 on" - print "intertechno 11110000111100001111000010010000" - sys.exit(1) - -if __name__ == "__main__": - import sys - cmd = "" - data = None - for i in range(1, len(sys.argv)): - cmd += " " + sys.argv[i] - cmd = cmd.strip() - - if re.match('^[01]{32}$', cmd) is not None: - data = it32.MakeFrame(cmd, 5) - datarate = 4 - - if re.match('^[01]{26} [01] [01]{4} (on|off)$', cmd) is not None: - tmp = cmd[0:26] + cmd[27] - if cmd[-2:] == 'on': - tmp += '1' - else: - tmp += '0' - tmp += cmd[29:33] - data = it32.MakeFrame(tmp, 5) - datarate = 1/275E-6/1000 - - if re.match('^[A-P] [1-4] [1-4] (on|off)$', cmd) is not None: - housecode = ord(cmd[0]) - ord('A') - itstr = '' - itstr += encodeBits(housecode, 4, '0', False) - - ch = ord(cmd[4]) - 1 - itstr += encodeBits(ch, 2, '0', False) - - group = ord(cmd[2]) - 1 - itstr += encodeBits(group, 2, '0', False) - - itstr += '0F' - - if cmd[-2:] == 'on': - itstr += 'FF' - else: - itstr += 'F0' - - data = xx2262.MakeFrame(itstr, 5) - datarate = 2.66666666 - - if re.match('^[01Ff]{12}$', cmd) is not None: - data = xx2262.MakeFrame(cmd, 5) - datarate = 2.66666666 - -if data is not None: - rfm = Rfm69() - rfm.SetParams( - Freq = 433.92, - Datarate = datarate, #2.666666, - TXPower = 13, - ModulationType = rfm69.OOK, - SyncPattern = [] - ) - rfm.SendPacket(data) -else: - usage() diff --git a/it32.py b/it32.py deleted file mode 100644 index b453b3e..0000000 --- a/it32.py +++ /dev/null @@ -1,10 +0,0 @@ - -def MakeFrame(code, rep): - data = [0x08, 0x00] #sync - for c in code: - if c == '0': - data.append(0xA0) - elif c == '1': - data.append(0x82) - data += [0x80, 0x00, 0x00, 0x00, 0x00] - return data * rep diff --git a/logilightrx.py b/logilightrx.py deleted file mode 100755 index 357f253..0000000 --- a/logilightrx.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python2.7 - -from rfm69 import Rfm69 -import rfm69 -import sys -import time -#import types -#import os - -rfm = Rfm69() -rfm.SetParams( - Freq = 433.92, - Datarate = 1 / 275E-06 / 1000, - Bandwidth = 4000, - SyncPattern = [0x80, 0x00, 0x00, 0x00], - RssiThresh = -80, - ModulationType = rfm69.OOK - ) - -def Decode(bitpos, data): - frame = 0 #space for decoded logilink frame - for i in range(bitpos, bitpos + 24 * 4, 4): - bitpattern = (data[i / 8] << 8) | (data[i / 8 + 1]) - bitpattern <<= i % 8 - bitpattern &= 0xF000 - frame <<= 1 - if bitpattern == 0xe000: - frame |= 1 - elif bitpattern == 0x8000: - pass - else: - return - systemcode = frame >> 4 - onoff = (frame >> 3) & 0x01 - ch = frame & 0x07 - return systemcode, onoff, ch - -while True: - data = rfm.ReceivePacket(60) - zcount = 0 - binstr = "" - bitcount = 0 - #print "received raw data:", data[0] - sync = 0 - for bit in range(len(data[0]) * 8): - sync <<= 1 - sync |= ((data[0][bit / 8] >> (7 - (bit % 8)))) & 0x01 - sync &= 0xFFFFFFFF - if sync == 0x80000000: #sync found in frame - if (bit >= 24 * 4 + 32 - 1): #logilinkframe has 24 bit, 1 logilink-bit = 4 raw-bits; + 32 raw bits sync - res = Decode(bit - 24 * 4 - 32 + 1, data[0]) - if res is not None: - print "Systemcode", res[0], "onoff", res[1], "ch", res[2] diff --git a/logilighttx.py b/logilighttx.py deleted file mode 100755 index 45fb7ea..0000000 --- a/logilighttx.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python2.7 - -from rfm69 import Rfm69 -import rfm69 -import sys - -if len(sys.argv) != 5: - print "usage: logiloghttx.py " - print "Example: logilighttx.py 65565 7 1 4" - sys.exit(1) - -rfm = Rfm69() -rfm.SetParams( - Freq = 433.92, - Datarate = 2.666666, - TXPower = 13, - ModulationType = rfm69.OOK, - SyncPattern = [] - ) - -#Frame generation -def MakeFrame(systemcode, onoff, channel, rep): - data = systemcode << 4 | onoff << 3 | channel - frame = [0x00] * 12 - for i in range(24): - if (data & (0x800000>>i)): - nibble = 0xE0 - else: - nibble = 0x80 - frame[i / 2] |= nibble >> (4 * (i % 2)) - - frame += [0x80, 0x00, 0x00, 0x00] #sync - - return frame * rep - -data = MakeFrame(int(sys.argv[1]), int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4])) -rfm.SendPacket(data) diff --git a/rcs1000.py b/rcs1000.py deleted file mode 100755 index 244e711..0000000 --- a/rcs1000.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python2.7 - -import xx2262 -import sys -import re -import rfm69 -from rfm69 import Rfm69 - -def usage(): - print "usage:", sys.argv[0], "<5xDIPSWITCH> on|off" - print "Example:", sys.argv[0], "brennenstuhl 00101 2 on" - sys.exit(1) - -if len(sys.argv) != 4: - usage() - -str = '' - -if re.match('[01]{5}$', sys.argv[1]) is None: - print "Invalid dipswitches" - usage() - -for c in sys.argv[1]: - if c == '1': - str += '0' - else: - str += 'F' - -if re.match('[1-4]$', sys.argv[2]) is None: - print "Invalid channel" - usage() - -ch = ord(sys.argv[2][0]) - ord('1') -for i in range(4): - if i == ch: - str += '0' - else: - str += 'F' - -str += 'FF' - -if sys.argv[3] == 'on': - str += 'F' -else: - str += '0' - -print "Sending", str - -data = xx2262.MakeFrame(str, 8) - -if not Rfm69.Test(0): - print "RFM69 not found!" - exit() - -rfm = Rfm69() -rfm.SetParams( - Freq = 433.92, - Datarate = 2.666666, - TXPower = 13, - ModulationType = rfm69.OOK, - SyncPattern = [] -) -rfm.SendPacket(data) diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..4c656a5 --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python2.7 +import setuptools + +setuptools.setup( + name="RaspyRFM", + version="1.1", + author="S. Seegel", + author_email="post@seegel-systeme.de", + description="Package for interfacing the RaspyRFM module", + packages=["RaspyRFM"], + license="MIT", + zip_safe=False, + install_requires=[ + "spidev", + "RPi.GPIO" + ] +) + diff --git a/xx2262.py b/xx2262.py deleted file mode 100755 index 14320db..0000000 --- a/xx2262.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python2.7 - -from rfm69 import Rfm69 -import rfm69 -import re - -#Frame generation -def MakeFrame(code, rep): - data = [0x80, 0x00, 0x00, 0x00] #sync - b = 0; - data = [] - for c in code: - if c == '0': - data.append(0x88) - elif c == '1': - data.append(0xEE) - elif c == 'F' or c == 'f': - data.append(0x8E) - data += [0x80, 0x00, 0x00, 0x00] #sync - - return data * rep - -def usage(): - print "usage: xx2262.py " #12-digit code 12 * ['0' | '1' | 'f'] - print "Example: sudo ./intertechno.py 0FF0F0F00FF0" - sys.exit(1) - -if __name__ == "__main__": - import sys - if len(sys.argv) != 2: - usage() - - if re.match('[01fF]{12}$', sys.argv[1]) is None: - print "Invalid code" - usage() - - data = MakeFrame(sys.argv[1], 5) - - rfm = Rfm69() - rfm.SetParams( - Freq = 433.92, - Datarate = 2.666666, - TXPower = 13, - ModulationType = rfm69.OOK, - SyncPattern = [] - ) - - rfm.SendPacket(data)