0

I've got a weird problem here. It hurts my brain thinking about it. I've got a Django project with multiple apps. Today I added another app.

(views.py)

from %app_name%.%class_file% import %class_name%

def api(request):
    t                        = %class_name%()
    data                     = {}
    data['listOtherDevices'] = t.listOtherDevices
    logger                   = logging.getLogger(__name__)
    logger.error(len(t.listOtherDevices))
    return JsonResponse(data)

The imported class fills the 'listOtherDevices'-array via __init__ perfectly fine when I run it inside a console. When I do so, there are exactly 3 elements inside this array (as there are 3 devices in my LAN the class could find). So when I visit the url (development server -> manage.py runserver) linked to this method I can see a JSON with exactly 3 entries. So far so good but now comes the weird part. When I refresh the url in my browser or visit it one more time, there are more than 3 entries. The scheme is like this:

opened url 1 time:    3 entries
opened url 2 times:   9 entries  (+  6)
opened url 3 times:  18 entries  (+  9)
opened url 4 times:  30 entries  (+ 12)
opened url 5 times:  45 entries  (+ 15)
opened url 6 times:  63 entries  (+ 18)

I can see a pattern there but I cannot understand why this happends.

sudo sysdig -c spy_users

tells me, that the class is gathering information exactly 3 times using

subprocess.check_output

The responded JSON is syntactically OK. Seems like the class would 'find' 9, or 18 devices.

Please help me, because as I said earlier: this makes my brain hurt :)

import json
import subprocess

class tradfri:

tradfriIPv4                 = 'blablabla'
tradfriUser                 = 'blablabla'
tradfriPassword             = 'blablabla'
pathToCoap                  = '/blablabla/coap-client'
listDevices                     = []
listGroups                  = []
listDevicesDetails          = []
listGroupsDetails           = []
listLightbulbs              = []
listOtherDevices            = []

def __init__(self):
    self.getDevices()
    self.getGroups()
    self.getArrayLightbulbs()
    self.getArrayOtherDevices()

def getDevices(self):
    method              = 'get'
    stdoutdata      = subprocess.check_output(  self.pathToCoap 
                                                                        + ' -m ' + method
                                                                        + ' -u "' + self.tradfriUser + '"'
                                                                        + ' -k "' + self.tradfriPassword + '"'
                                                                        + ' coaps://' + self.tradfriIPv4 + ':5684/15001'
                                                                        +  " | awk 'NR==4'",
                                                                        shell=True).decode("utf-8") 
    self.listDevices    = json.loads(stdoutdata)

    for ID in self.listDevices:
        stdoutdata  = subprocess.check_output(  self.pathToCoap 
                                                                        + ' -m ' + method
                                                                        + ' -u "' + self.tradfriUser + '"'
                                                                        + ' -k "' + self.tradfriPassword + '"'
                                                                        + ' coaps://' + self.tradfriIPv4 + ':5684/15001/' + str(ID)
                                                                        +  " | awk 'NR==4'",
                                                                        shell=True).decode("utf-8")
        self.listDevicesDetails.append(json.loads(stdoutdata))

def getGroups(self):
    method              = 'get'
    stdoutdata      = subprocess.check_output(  self.pathToCoap 
                                                                        + ' -m ' + method
                                                                        + ' -u "' + self.tradfriUser + '"'
                                                                        + ' -k "' + self.tradfriPassword + '"'
                                                                        + ' coaps://' + self.tradfriIPv4 + ':5684/15004'
                                                                        +  " | awk 'NR==4'",
                                                                        shell=True).decode("utf-8") 
    self.listGroups     = json.loads(stdoutdata)

    for ID in self.listGroups:
        stdoutdata      = subprocess.check_output(  self.pathToCoap 
                                                                            + ' -m ' + method
                                                                            + ' -u "' + self.tradfriUser + '"'
                                                                            + ' -k "' + self.tradfriPassword + '"'
                                                                            + ' coaps://' + self.tradfriIPv4 + ':5684/15004/' + str(ID)
                                                                            +  " | awk 'NR==4'",
                                                                            shell=True).decode("utf-8") 
        raw = json.loads(stdoutdata)

        tmpMembers = []
        for id in raw['9018']['15002']['9003']:
            tmpMembers.append( { 'ID': str( id ), 'name': self.getDeviceNameByID(id) } )

        self.listGroupsDetails.append(  {   'ID': str( raw['9003'] ),
                                                            'name': raw['9001'],
                                                            'isGroupOn': False,
                                                            'members': tmpMembers } )

def getArrayLightbulbs(self):
    for item in self.listDevicesDetails:
        if item['3']['6'] == 1: # is lightbulb
            id                      = item['9003']
            name                    = item['9001']
            groupID             = self.getGroupIDByID(id)
            groupName           = self.getGroupNameByID(id)
            manufacturer        = item['3']['0']
            description         = item['3']['1']
            isReachable         = True
            isBulbOn                = False
            isDimmable          = False
            isWhiteSpectrum = False
            isColorSpectrum     = False
            brightnessOfBulb    = ''
            currentColor            = ''

            #isReachable
            if len(item['3311'][0]) == 1:
                isReachable = False;
            else:
                #isBulbOn
                if item['3311'][0]['5850'] == 1:
                    isBulbOn = True
                #dimmable & brightnessOfBulb
                if '5851' in item['3311'][0]:
                    brightnessOfBulb = str( item['3311'][0]['5851'] )
                    isDimmable = True
                #currentColor
                if '5706' in item['3311'][0]:
                    currentColor = item['3311'][0]['5706']

            #isWhiteSpectrum
            if ' WS ' in description:
                isWhiteSpectrum = True
            #isColorSpectrum
            if ' CWS ' in description:
                isWhiteSpectrum = True  
                isColorSpectrum = True

            self.listLightbulbs.append( {   'ID':                       str( id ), 
                                                        'Name':                     name,
                                                        'groupID':              str( groupID ),
                                                        'groupName' :           groupName, 
                                                        'manufacturer':         manufacturer,
                                                        'description' :             description,
                                                        'isReachable':          isReachable,
                                                        'isBulbOn':                 isBulbOn,
                                                        'isDimmable':           isDimmable,
                                                        'isWhiteSpectrum':  isWhiteSpectrum,
                                                        'isColorSpectrum':  isColorSpectrum,
                                                        'brightnessOfBulb':     brightnessOfBulb,
                                                        'currentColor':             currentColor    } )

def getArrayOtherDevices(self):
    for device in self.listDevicesDetails:
        if device['3']['6'] == 3:
            self.listOtherDevices.append( { 'ID':                   str( device['9003'] ), 
                                                            'Name':                 device['9001'],
                                                            'groupID':          str( self.getGroupIDByID(str( device['9003']) ) ),
                                                            'groupName':        self.getGroupNameByID(str( device['9003']) ), 
                                                            'manufacturer':     device['3']['0'],
                                                            'description':      device['3']['1']    } )

def getDeviceNameByID(self, id):
    name = ''
    for key in self.listDevicesDetails:
        if key['9003'] == id:
            name = key['9001']
    return name

def getGroupIDByID(self, id):
    groupID = ''
    for group in self.listGroupsDetails:
        for member in group['members']:
            if member['ID'] == id:
                groupID = group['ID']
    return groupID

def getGroupNameByID(self, id):
    groupName = ''
    for group in self.listGroupsDetails:
        for member in group['members']:
            if member['ID'] == id:
                groupName = group['name']
    return groupName

1 Answers1

0

You use class wide attributes to save the data. Whenever you create a new instance of tradfri your methods work on the same class wide attribute listOtherDevices. Note that the class lives in memory until you restart the server. Therefore the amount of values increases with each request, as you append values to your list.

You should use attributes which are available per instance. In python this is achieved by initializing the attributes inside of __init__(). It might look like that:

class tradfri:

    def __init__(self):
        self.tradfriIPv4                 = 'blablabla'
        self.tradfriUser                 = 'blablabla'
        self.tradfriPassword             = 'blablabla'
        self.pathToCoap                  = '/blablabla/coap-client'
        self.listDevices                 = []
        self.listGroups                  = []
        self.listDevicesDetails          = []
        self.listGroupsDetails           = []
        self.listLightbulbs              = []
        self.listOtherDevices            = []
        self.getDevices()
        self.getGroups()
        self.getArrayLightbulbs()
        self.getArrayOtherDevices()

Read python class attribute for more details. The official documentation on that topic are also worth reading.

dahrens
  • 3,879
  • 1
  • 20
  • 38