Python Forum

Full Version: help coding for decode filtering
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have original code like this below
        if line[15:20] == 'Rx RF':

            # decode RF message. format is:
            #   02/13 23:54:28 Rx RF HouseUnit: B1 Func: On
            line_list = line.split(' ')
            house_code = line_list[5];
            house_func = line_list[7]

            return house_code, {'func': house_func}, 'button'
Like in description, if input "02/13 23:54:28 Rx RF HouseUnit: B1 Func: On"
this code will decode :
house_code = B1
house_func = On

Now I have 2 lines input :
02/13 23:54:28 Rx PL HouseUnit: A1
02/13 23:54:28 Rx PL House: A Func: On

I want to modify the code so that will have result :
house_code = A1
house_func = On

Anybody can help me?
I would suggest you to use regular expressions to parse such strings.

Try this:

import re
rf_full_pat = re.compile(r'^\s?(?P<date>\d\d/\d\d)\s+(?P<time>\d\d\:\d\d\:\d\d)\s+(?P<band1>[a-zA-Z]+)\s+(?P<band2>[a-zA-Z]+)\s+(?P<unittype>[a-zA-Z]+\:)\s+(?P<unit>\w+)\s+([a-zA-Z]+\:)\s+(?P<func>[a-zA-Z]+)\s?$')
rf_pat_pat = re.compile(r'^\s?(?P<date>\d\d/\d\d)\s+(?P<time>\d\d\:\d\d\:\d\d)\s+(?P<band1>[a-zA-Z]+)\s+(?P<band2>[a-zA-Z]+)\s+(?P<unittype>[a-zA-Z]+\:)\s+(?P<unit>\w+)\s?$')
test_full = "02/13 23:54:28 Rx RF HouseUnit: B1 Func: On"
test_pat = "02/13 23:54:28 Rx PL HouseUnit: A1"

def parse_rf(astring):
    return rf_full_pat.match(astring) or rf_pat_pat.match(astring)
>>> print(parse_rf(test_full).groupdict())
Output:
{'func': 'On', 'band2': 'RF', 'unittype': 'HouseUnit:', 'band1': 'Rx', 'unit': 'B1', 'time': '23:54:28', 'date': '02/13'}
>>> print(parse_rf(test_pat).groupdict()) 
Output:
{'band2': 'PL', 'unittype': 'HouseUnit:', 'band1': 'Rx', 'unit': 'A1', 'time': '23:54:28', 'date': '02/13'}
Now, you can easily access named properties....
Thank you for your suggestion, however your code cannot be applied,
since input can be 1 line (original code) and can be 2 lines (need to modify code)
Please see below for original code

    def parse_mochad_line(self, line):
        """
        Parse a raw line of output from mochad
        """
        # bail out unless it's an incoming RFSEC message
        if line[15:23] == 'Rx RFSEC':

            # decode message. format is either:
            #   09/22 15:39:07 Rx RFSEC Addr: 21:26:80 Func: Contact_alert_min_DS10A
            #     ~ or ~
            #   09/22 15:39:07 Rx RFSEC Addr: 0x80 Func: Motion_alert_SP554A            
            line_list = line.split(' ')
            addr = line_list[5]
            func = line_list[7]

            func_dict = self.decode_func(func)

            return addr, {'func': func_dict}, 'security'

        elif line[15:20] == 'Rx RF':

            # decode RF message. format is:
            #   02/13 23:54:28 Rx RF HouseUnit: B1 Func: On
            line_list = line.split(' ')
            house_code = line_list[5];
            house_func = line_list[7]

            return house_code, {'func': house_func}, 'button'

        return '', ''
so I want to extend the code so that can accept 2 lines, something like below.
I think I will need to save variable filtered from #1 line input and
call that variable while #2 line input being processed.
But I have no idea how to do this???

        elif line[15:20] == 'Rx PL':

            # decode RF message. input has 2 lines, format is:
            #   02/13 23:54:28 Rx PL HouseUnit: A1
            #   02/13 23:54:28 Rx PL House: A Func: On
            line_list = line.split(' ')
            if line[21:27] == 'HouseU':   #filtering #1 line input for 'HouseUnit'=A1
                house_code = line_list[5]    
                #but this variable 'house_code' has to be saved somewhere
                #so that can be called when the next line input being processed
            elif line[21:27] == 'House:':   #filtering #2 line input for 'Func'=On
                house_func = line_list[7]
                house_code = ????   
                #here need to call variable 'HouseUnit'=A1 which already being saved
                #while filtering #1 line input
If your function accepts input line by line, you may use function-level caching. I will show you how to use mutable default value to this end

Let's start by splitting the line unconditionally
def parse_mochad_line(self, line, _house_unit=[]):
    elements = line.split()
    classifier = ''.join(elements[2:4])
    if classifier == 'RxRFSEC':
        ......
    elif classifier == 'RxRF':
        .....
    elif classifier == 'RxPL':
        if not house_unit:
            _house_unit.append(...)
         else:
            ......
            _house_unit.clear()
Pay attention - you cannot assign _house_unit, because that will ruin caching mechanism