1

I have a program that is aiming to take inputs from sensors and then act upon inputs from these sensors from some pre-defined rules that are stored and called within a class. I am having problems passing the variables that the sensors are defined as into the rules class. Where I get errors of 'Rules object has not attribute .rules_temperature. My code is below:

class myInterfaceKit():
    __interfaceKit = None

    def __init__(self ):       
        try:
            self.__interfaceKit = InterfaceKit()    
        except RuntimeError as e:
            print("Runtime Exception: %s" % e.details)
            print("Exiting....")
            exit(1)

    def open(self):
        try:
            self.__interfaceKit.openPhidget()
        except PhidgetException as e:
            print("Phidget Exception %i: %s" % (e.code, e.details))

    def getInterfaceKit(self):
        return self.__interfaceKit

    def getSensor(self, sensor):
        return self.__interfaceKit.getSensorValue(sensor)


class sensors():

    __sound = 0
    __temperature = 0
    __light = 0
    __motion = 0

    __dbName = ""
    __interfaceKit = None
    __connection = None
    __rules = None

    def __init__(self, theInterfaceKit, dbName):
        self.__sound = 0
        self.__temperature=0
        self.__light=0
        self.__motion=0
        self.__timeStamp=time.time()
        self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
        self.__dbName = dbName
        self.__interfaceKit = theInterfaceKit
        self.__connection = sqlite3.connect('testing1.db', check_same_thread=False) ######


    def interfaceKitAttached(self, e):
        attached = e.device
        print("InterfaceKit %i Attached!" % (attached.getSerialNum()))

        self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(0, 5)
        self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(1, 35)
        self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(2, 60)
        self.__interfaceKit.getInterfaceKit().setSensorChangeTrigger(3, 200)

    def sensorInputs(self, e):

        temperature = (self.__interfaceKit.getSensor(0)*0.2222 - 61.111)
        sound =  (16.801 * math.log((self.__interfaceKit.getSensor(1))+ 9.872))
        light = (self.__interfaceKit.getSensor(2))
        motion = (self.__interfaceKit.getSensor(3)) 

        # check temperature has changed - if yes, save and update
        if temperature != self.__temperature:
            self.__timeStamp=time.time()
            self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
            self.__temperature = temperature
            print("Temperature is: %i:" % self.__temperature)

            self.writeToDatabase( 'temperature', self.__temperature, self.__strTimeStamp)


         #check sound has changed - if yes, save and update
        if sound != self.__sound:
            self.__timeStamp=time.time()
            self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
            self.__sound = sound
            print("Sound is: %i " % self.__sound)
            self.writeToDatabase( 'sound', self.__sound, self.__strTimeStamp )

         #check light has changed - if yes, save and update
        if light != self.__light:
            self.__timeStamp=time.time()
            self.__strTimeStamp=datetime.datetime.fromtimestamp(self.__timeStamp).strftime('%Y-%m-%d %H:%M:%S')
            self.__light = light
            print("Light is: %i " % self.__light)
            self.writeToDatabase( 'light', self.__light, self.__strTimeStamp )


        if motion != self.__motion:
            self.__motion = motion
            print ("motion is %i" % self.__motion)


    def openDatabase(self):
        cursor = self.__connection.cursor()
        cursor.execute("CREATE TABLE " + self.__dbName + " (sensor text, value text, time_stamp text)")

    def writeToDatabase(self, sensorType, data, time):
        cursor = self.__connection.cursor()
        cursor.execute("INSERT INTO " + self.__dbName + " VALUES (?, ?, ?)", (sensorType, data, time))
        self.__connection.commit()

    def closeDatabase():
        self.__connection.close()

    def start(self):
        try:
            self.__interfaceKit.getInterfaceKit().setOnAttachHandler(self.interfaceKitAttached)
            self.__interfaceKit.getInterfaceKit().setOnSensorChangeHandler(self.sensorInputs)
            self.openDatabase()
        except PhidgetException as e:
            print("Phidget Exception %i: %s" % (e.code, e.details))
            print("Exiting....")
            exit(1)

This is where the problem lies:::

class Rules(sensors):

    __tempLower=0
    __tempUpper=0


    def __init__(self):
        self.__tempLower=28
        self.__tempUpper=30
        self.__temperature

    def tempRule(self, sensors): ##Temperature rule
        if self.__temperature == self.__tempLower:
            print("testing")


phidgetInterface = myInterfaceKit()
phidgetInterface.open()

theSensors = sensors(phidgetInterface, "event156")
theSensors.start()

theRule = Rules()
theRule.tempRule()

chr = sys.stdin.read(1)

edit, error message:

Traceback (most recent call last): File "H:\Project\Student\Prototype 1\eventProto.py", line 159, in theRule = Rules()

File "H:\Project\Student\Prototype 1\eventProto.py", line 146, in init self.__temperature AttributeError: 'Rules' object has no attribute 'Rules_temperature'

2 Answers2

2

Private members (starting with __) cannot be accessed by subclasses. (Well, they can be accessed using some hackery, but should not). (see here)

In your case, __temperature is a private member of the base class sensors, but you're accessing it from the subclass Rules.

Replace the double underscore prefix with a single underscore (__temperature -> _temperature), and you're good to go.

Community
  • 1
  • 1
shx2
  • 61,779
  • 13
  • 130
  • 153
-1

Double underscore members are considered private, you have to prepend those with class name that defined said member.

Use these magic private members like this:

class sensors:
    __temp = 42

assert sensors()._sensors__temp == 42

class Rules(sensors):
    def test(self):
        assert self._sensors__temp == 42

Rules().test()
Dima Tisnek
  • 11,241
  • 4
  • 68
  • 120
  • 1
    [PEP-8](http://legacy.python.org/dev/peps/pep-0008/#method-names-and-instance-variables) says: "Generally, double leading underscores should be used only to avoid name conflicts with attributes in classes designed to be subclassed." – Matthias Apr 05 '14 at 11:43