Mystery loop

Status
Not open for further replies.

ibwev

Member
When I power an RF Transmitter attached to an aduino, I am successfully sending text messages via an RF Receiver connected to a Raspberry Pi that has a GSM module attached to it. The RF sniffing code on the Raspberry Pi waits for a transmission from the RF Transmitter before sending a text. However, once the sniffing code receives the first signal, it doesn't stop sending text messages even after the transmitter has been powered off. If I comment out the line
Code:
sendSMS1.sms()
the code works as expected. In other words, when I power off the transmitter and have the above line commented out, the sniffing program does not enter the loop at
Code:
while rx.ready():
. However, when I uncomment
Code:
sendSMS1.sms()
, run the program, and turn the transmitter on to send one text and immediately power it off , it continuously loops this section (line 369 - 382 of vw.py).
Code:
 if (letter[len(letter) - 1]) == "L": #capture lastletter of list
                print("The letter is L")
                print(letter + "before send")
                sendSMS1.sms()    #send the text
                i += 1
                l = list(letter)  #strings are immutable, convert to a list
                del(l[len(letter) - 1]) #delete the last letter of the list
                letter = "".join(l)  #assign the list of chars to the string letter
                print(letter)
                print(i)

Somehow, when the transmitter is cycled on and off one time, the char "L" is re-appended to the string even though it is successfully removed after sending the text. I assume I have broken some sort of importing rule when I call
Code:
 sendSMS1.sms()
but I have tried numerous modifications and can't seem to figure it out. Any help solving this problem would be much appreciated.

Text Code (sendSMS1.py)
Code:
import os
import serial
from time import sleep, time
from string import replace
from globalParVar import *
from agsm2_064_hw_control import *
from agsm_Serial_Lib import *
from agsm_Basic_Lib import *
from agsm_SMS_Lib import *





def sms():    #when importing this module, the desired code must be in a definition
    message="Hi!\r\nThis message has been sent from the a-gsm v2.064 shield connected with my RPi board." 
    destinationNumber="3185184930"#usually phone number with International prefix eg. +40 for Romania - in some networks you must use domestic numbers
    usePoweringControl = 1#change it to 0 if you do not want to control powerUP/powerDown the a-gsm board. In this case, please be sure the a-gsm board is powered UP(..see a-gsm_kickstart_v_x-yz.pdf) before run this utility  

    print "Light example - just send a SMS to a destination number"
    sleep(1)

    if not os.getuid() == 0:
       print("please use root privileges! try: \"sudo python yourPythonFileName.py\"")
       exit(0)

    if destinationNumber=="":
       print("No destination number has been set for your SMS!")
       print("Edit the file and set the destinationNumber in line 35\r\n")
       exit(0)

# set SERIAL/USB communication section start
# bellow chose value bw [SER] Serial /dev/ttyAMA0 or [USB] /dev/ttyUSB0
# if module USB port maps to other port as /dev/ttyUSB1, just edit the moduleName_Serial_lib.py...
    serialCommunicationVia = SERIALCON      # OVERRIDE the default value loaded from globalParVar.py. here I use via SERIAL communication
    setSerialCom(serialCommunicationVia)    # set the current communication option
    startSerialCom()                        # open serial communication bw. RPi and a-gsm shield
# set SERIAL/USB communication section end

# set HARDWARE CONTROL setup & POWER ON section start        
    if usePoweringControl==1:
       hwControlSetup()                    # setup the RPi I/O ports

    sleep(2)#some delay...

    if usePoweringControl==1:
       poweron()

    sleep(1)
# set HARDWARE CONTROL setup & POWER ON section end        

# set MODEM STARTUP SETUP section start        
    setupMODEM()
# set MODEM STARTUP SETUP section end        


# MAIN PROGRAM section start        
    print "try to send a SMS...."

#check AT command pdf for proper 129/145 parameter/number format usage
    res = sendSMS(destinationNumber, "129", message)#domestic format numbers
#res = sendSMS(destinationNumber, "145", message)#international format numbers
    if res==0:
        print "SMS has been sent with succes"
# MAIN PROGRAM section end        

# stop SERIAL COMMUNICATION section start        
    stopSerialCom()                             # close modem communication
# stop SERIAL COMMUNICATION section end        

# HARDWARE CONTROL release & POWER OFF section start        
    if usePoweringControl==1:
       poweroff()                              #shutdown modem

    if usePoweringControl==1:
       hwControlRelease()                      # free GPIO
# HARDWARE CONTROL release & POWER OFF section end        


    print("\r\n\r\nThat's all folks!\r\n")

Sniffing Code (vw.py)
Code:
#!/usr/bin/env python
"""
This module provides a 313MHz/434MHz radio interface compatible
with the Virtual Wire library used on Arduinos.

It has been tested between a Pi, TI Launchpad, and Arduino Pro Mini.
"""
# 2014-08-14
# vw.py

import time
import pigpio
import sendSMS1

MAX_MESSAGE_BYTES=77

MIN_BPS=50
MAX_BPS=10000

_HEADER=[0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x38, 0x2c]

_CTL=3

_SYMBOL=[
   0x0d, 0x0e, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, 
   0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x32, 0x34]


def _sym2nibble(symbol):
   for nibble in range(16):
      if symbol == _SYMBOL[nibble]:
         return nibble
   return 0

def _crc_ccitt_update(crc, data):

   data = data ^ (crc & 0xFF);

   data = (data ^ (data << 4)) & 0xFF;

   return (
             (((data << 8) & 0xFFFF) | (crc >> 8)) ^
              ((data >> 4) & 0x00FF) ^ ((data << 3) & 0xFFFF)
          )

class tx():

   def __init__(self, pi, txgpio, bps=2000):
      """
      Instantiate a transmitter with the Pi, the transmit gpio,
      and the bits per second (bps).  The bps defaults to 2000.
      The bps is constrained to be within MIN_BPS to MAX_BPS.
      """
      self.pi = pi

      self.txbit = (1<<txgpio)

      if bps < MIN_BPS:
         bps = MIN_BPS
      elif bps > MAX_BPS:
         bps = MAX_BPS

      self.mics = int(1000000 / bps)

      self.wave_id = None

      pi.wave_add_new()

      pi.set_mode(txgpio, pigpio.OUTPUT)


   def _nibble(self, nibble):

      for i in range(6):
         if nibble & (1<<i):
            self.wf.append(pigpio.pulse(self.txbit, 0, self.mics))
         else:
            self.wf.append(pigpio.pulse(0, self.txbit, self.mics))

   def _byte(self, crc, byte):
      self._nibble(_SYMBOL[byte>>4])
      self._nibble(_SYMBOL[byte&0x0F])
      return _crc_ccitt_update(crc, byte)

   def put(self, data):
      """
      Transmit a message.  If the message is more than
      MAX_MESSAGE_BYTES in size it is discarded.  If a message
      is currently being transmitted it is aborted and replaced
      with the new message.  True is returned if message
      transmission has successfully started.  False indicates
      an error.
      """
      if len(data) > MAX_MESSAGE_BYTES:
         return False

      self.wf = []

      self.cancel()

      for i in _HEADER:
         self._nibble(i)

      crc = self._byte(0xFFFF, len(data)+_CTL)

      for i in data:

         if type(i) == type(""):
            v = ord(i)
         else:
            v = i

         crc = self._byte(crc, v)

      crc = ~crc

      self._byte(0, crc&0xFF)
      self._byte(0, crc>>8)

      self.pi.wave_add_generic(self.wf)

      self.wave_id = self.pi.wave_create()

      if self.wave_id >= 0:
         self.pi.wave_send_once(self.wave_id)
         return True
      else:
         return False


   def ready(self):
      """
      Returns True if a new message may be transmitted.
      """
      return not self.pi.wave_tx_busy()

   def cancel(self):
      """
      Cancels the wireless transmitter, aborting any message
      in progress.
      """
      if self.wave_id is not None:
         self.pi.wave_tx_stop()
         self.pi.wave_delete(self.wave_id)
         self.pi.wave_add_new()

      self.wave_id = None

class rx():

   def __init__(self, pi, rxgpio, bps=2000):
      """
      Instantiate a receiver with the Pi, the receive gpio, and
      the bits per second (bps).  The bps defaults to 2000.
      The bps is constrained to be within MIN_BPS to MAX_BPS.
      """
      self.pi = pi
      self.rxgpio = rxgpio

      self.messages = []
      self.bad_CRC = 0

      if bps < MIN_BPS:
         bps = MIN_BPS
      elif bps > MAX_BPS:
         bps = MAX_BPS

      slack = 0.20
      self.mics = int(1000000 / bps)
      slack_mics = int(slack * self.mics)
      self.min_mics = self.mics - slack_mics       # Shortest legal edge.
      self.max_mics = (self.mics + slack_mics) * 4 # Longest legal edge.

      self.timeout =  8 * self.mics / 1000 # 8 bits time in ms.
      if self.timeout < 8:
         self.timeout = 8

      self.last_tick = None
      self.good = 0
      self.bits = 0
      self.token = 0
      self.in_message = False
      self.message = [0]*(MAX_MESSAGE_BYTES+_CTL)
      self.message_len = 0
      self.byte = 0

      pi.set_mode(rxgpio, pigpio.INPUT)

      self.cb = pi.callback(rxgpio, pigpio.EITHER_EDGE, self._cb)

   def _calc_crc(self):

      crc = 0xFFFF
      for i in range(self.message_length):
         crc = _crc_ccitt_update(crc, self.message[i])
      return crc

   def _insert(self, bits, level):

      for i in range(bits):

         self.token >>= 1

         if level == 0:
            self.token |= 0x800

         if self.in_message:

            self.bits += 1

            if self.bits >= 12: # Complete token.

               byte = (
                  _sym2nibble(self.token & 0x3f) << 4 |
                  _sym2nibble(self.token >> 6))

               if self.byte == 0:
                  self.message_length = byte

                  if byte > (MAX_MESSAGE_BYTES+_CTL):
                     self.in_message = False # Abort message.
                     return

               self.message[self.byte] = byte

               self.byte += 1
               self.bits = 0

               if self.byte >= self.message_length:
                  self.in_message = False
                  self.pi.set_watchdog(self.rxgpio, 0)

                  crc = self._calc_crc()

                  if crc == 0xF0B8: # Valid CRC.
                     self.messages.append(
                        self.message[1:self.message_length-2])
                  else:
                     self.bad_CRC += 1

         else:
            if self.token == 0xB38: # Start message token.
               self.in_message = True
               self.pi.set_watchdog(self.rxgpio, self.timeout)
               self.bits = 0
               self.byte = 0

   def _cb(self, gpio, level, tick):

      if self.last_tick is not None:

         if level == pigpio.TIMEOUT:

            self.pi.set_watchdog(self.rxgpio, 0) # Switch watchdog off.

            if self.in_message:
               self._insert(4, not self.last_level)

            self.good = 0
            self.in_message = False

         else:

            edge = pigpio.tickDiff(self.last_tick, tick)

            if edge < self.min_mics:

               self.good = 0
               self.in_message = False

            elif edge > self.max_mics:

               if self.in_message:
                  self._insert(4, level)

               self.good = 0
               self.in_message = False

            else:

               self.good += 1

               if self.good > 8: 

                  bitlen = (100 * edge) / self.mics

                  if   bitlen < 140:
                     bits = 1
                  elif bitlen < 240:
                     bits = 2
                  elif bitlen < 340:
                     bits = 3
                  else:
                     bits = 4

                  self._insert(bits, level)

      self.last_tick = tick
      self.last_level = level

   def get(self):
      """
      Returns the next unread message, or None if none is avaiable.
      """
      if len(self.messages):
         return self.messages.pop(0)
      else:
         return None

   def ready(self):
      """
      Returns True if there is a message available to be read.
      """
      return len(self.messages)

   def cancel(self):
      """
      Cancels the wireless receiver.
      """
      if self.cb is not None:
         self.cb.cancel()
         self.pi.set_watchdog(self.rxgpio, 0)
      self.cb = None

if __name__ == "__main__":

   import time

   import pigpio

   import vw

   RX=27
   TX=25

   BPS=900

   pi = pigpio.pi() # Connect to local Pi.

   rx = vw.rx(pi, RX, BPS) # Specify Pi, rx gpio, and baud.
   tx = vw.tx(pi, TX, BPS) # Specify Pi, tx gpio, and baud.

   msg = 0

   start = time.time()

   while (time.time()-start) < 300:

 #     msg += 1

 #     while not tx.ready():
#         time.sleep(0.1)

#      time.sleep(0.2)

 #     tx.put([48, 49, 65, ((msg>>6)&0x3F)+32, (msg&0x3F)+32])

#      while not tx.ready():
#         time.sleep(0.1)

 #     time.sleep(0.2)

#      tx.put("Hello World #{}!".format(msg))

      i = 0   
      while rx.ready():
         print("immediately after while before join")
    letter = ("".join(chr (c) for c in rx.get())) #retrieve what was sent first 2 or 3 characters are preambles 
    if (letter[len(letter) - 1]) == "L": #capture lastletter of list
        print("The letter is L")
        print(letter + "before send")
        sendSMS1.sms()    #send the text
        #time.sleep(60)  this does not help. Line does not execute until previous is finished
#when executing sendSMS1.sms() this loop completes once the text is sent
#I unplug the battery but code does not exit while loop and it somehow restores the string to remember the L
#the code works as expected if I comment out the sendSMS1 command
        i += 1
        l = list(letter)  #strings are immutable, convert to a list
        del(l[len(letter) - 1]) #delete the last letter of the list
        letter = "".join(l)  #assign the list of chars to the string letter
        print(letter)
        print(i)
    else:
        print("failed")

   rx.cancel()
   tx.cancel()

   pi.stop()
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…