dhhagan / py-opc

Python wrapper for the Alphasense OPC-N2 built around py-spidev
MIT License
30 stars 26 forks source link

AttributeError: 'OPC' object has no attribute 'on' #51

Closed DonnaVakalis closed 6 years ago

DonnaVakalis commented 6 years ago

Hi,

I am using python 3.5 and OPC firmware 18.2 on an Rpi3.

I am getting the following error when I hit the line alpha.on(): AttributeError: 'OPC' object has no attribute 'on'

Can you help me see where I'm going wrong? I suspect I may be making a "newby" mistake as I am indeed a newby :) Thanks!

/// ///////// Here is the entire terminal output (and following below is my script): ///////// /// Opc and USBISS loaded... The module ID is 7 The firmware version is 0x7 The current operating mode is 0x92 The serial number is b'00029581' Initializing USB-ISS in SPI mode with 146 spi_mode and 11 sck_divisor Alpha assigned A--OK so far... Traceback (most recent call last): File "./TestPythonScript.py", line 26, in alpha.on() AttributeError: 'OPC' object has no attribute 'on'

/// ///////// Here is my python script: ///////// /// import opc import usbiss print("Opc and USBISS loaded...")

Open a SPI connection

spi = usbiss.USBISS("/dev/ttyACM0", 'spi', spi_mode = 2, freq = 500000)

try:

alpha = opc.OPCN2(spi)

alpha = opc.OPC(spi, firmware=(18,2))

except Exception as e: print ("Startup Error: {}".format(e))

print("Alpha assigned A--OK so far...")

Turn on the OPC

alpha.on()

Read the histogram and print to console

for key, value in alpha.histogram().items(): print ("Key: {}\tValue: {}".format(key, value))

Shut down the opc

alpha.off()

DancingQuanta commented 6 years ago

You are almost there! Please use the following line

alpha = opc.OPCN2(spi, firmware=(18,2))

instead of

alpha = opc.OPC(spi, firmware=(18,2))

Is there a reason why you commented out the line?

#alpha = opc.OPCN2(spi)

The class OPC is a base class and so is unusble. You need to use OPCN2 if you are using OPC-N2 or OPCN1 if you are using OPC-N1 model.

@dhhagan: Would it be more helpful if the base class OPC be renamed to _OPC?

DonnaVakalis commented 6 years ago

Thank you @DancingQuanta for the fix and the encouragement. Much appreciated. That did it. To answer your question, the commented out line didn't work for me (firmware error messages); but as I edited the code I left it in place as a reminder to self of the instructions version of the code. And I copied the line "alpha = opc.OPC(spi, firmware=(18,2))" from the /dev branch to set the firmware manually without understanding what I was doing).

Right now I'm getting new errors Traceback: File "./TestPythonScript.py", line 29, in for key, value in alpha.histogram().items(): AttributeError: 'NoneType' object has no attribute 'items'

But I will work on them myself first to see if I can't spot my errors before bothering the issues section again. Thanks again!

DancingQuanta commented 6 years ago

I love to help! Especially Alphasense is a bit fiddlely.

Your latest error sounds like the library was expecting something but got nothing. So clearly there is no check for NoneType or gives no feedback on what went wrong in histogram function.

If you are stuck, let us know! If you found a solution, do write about it here so someone may benefit from it! Also your original issue is solved so please close this issue.

dhhagan commented 6 years ago

@DancingQuanta That sounds great. You want to do it and send a PR? If not, I can do it in the near future.

Hi @DonnaVakalis: Welcome to py-opc! It looks like @DancingQuanta sent you on the right path. The only way a None can be sent back is if the data transfer was incomplete. Let me know if this still bugs you and one of us can certainly lend our help. What are you using py-opc for? I'm trying to compile a list of all of the organizations/groups using it. Thanks!

DonnaVakalis commented 6 years ago

Thank you both @dhhagan and @DancingQuanta.

My short term goal for using py-opc is to add a time stamp to the OPC-N2 readings, and to upload the timestamped readings online (to save having to wait between site visits to collect data on as-of-now hypothetical deployments).

My broader goal is to build my capacity for working with sensors so that I can (eventually) contribute to the community of indoor air quality and indoor environmental data-tracking in buildings.

DancingQuanta commented 6 years ago

Can I suggest AirPi which use a Raspberry Pi to aggregate data from a number of sensors. I have made a fork of AirPi to allow for multiple serial devices including Alphasense OPCN2 via USBISS. I think I forgot to upload this fork online in a year or two....

DonnaVakalis commented 6 years ago

Thank you! I will check it out today. I am looking at the script run_opcn2_usbiss.py and finding it to be a really helpful examples. I am really really grateful to have this example available to study, because for a newby like me it allows me to sift through how you approach things and learn incrementally by copying/tweaking...

Here are some things I noticed in the code, but I'm not sure about my interpretation:

1) in the alpha.pm() code, the column is titled 'PM2.5' e.g., data['PM2.5'] = self._calculate_float(resp[4:8]) but the the script uses 'PM25' e.g., LF.write(','.join([dt, data['PM1'], data['PM25'], data['PM10']]))

2) in the same script, run_opcn2_usbiss.py, there is a definition of COLUMNS but call using columns, e.g., COLUMNS = ['DATETIME', 'PM1', 'PM25', 'PM10'] with open(LOGFILE, 'w') as LF: LF.write(','.join(columns))

Aside:

Running the run_opcn2_usbiss.py example as-is resulted in these two error messages, respectively:

File "opc_t0.py", line 46, in LF.write(','.join(columns)) NameError: name 'columns' is not defined

File "opc_t0.py", line 53, in LF.write(','.join([dt, data['PM1'], data['PM25'], data['PM10']])) KeyError: 'PM25'

Changes and error re: expected string but got a float...

So I've adapted your example with the tiny exception of changing 25 to 2.5 and columns to COLUMNS... and run the whole things...

and run into the error "TypeError: sequence item 1: expected str instance, float found"

Here is the traceback:

File "opc_t1.py", line 56, in LF.write(','.join([dt, data['PM1'],data['PM2.5'], data['PM10']])) TypeError: sequence item 1: expected str instance, float found

Here is the script:

import opc import usbiss import argparse import sys import os from time import sleep import datetime

SAMPLE_INT = 5.0 LOGFILE = os.path.join("/home/dmv/Public/Outputs", "TestRun.csv".format(datetime.datetime.utcnow().strftime("%Y%m%d")))

COLUMNS = ['DATETIME', 'PM1', 'PM2.5', 'PM10']

parser = argparse.ArgumentParser( description = 'Log data from the OPC-N2')

parser.add_argument('--int', help = 'Define the log interval in seconds')

if name == 'main':

Parse the args

args = parser.parse_args()

if args.int:
    SAMPLE_INT = int

# Set up the instance
spi = usbiss.USBISS("/dev/ttyACM0", 'spi', spi_mode = 2, freq = 500000)

try:
    alpha = opc.OPCN2(spi, firmware=(18,2))
except Exception as e:
    print ("Startup Error: Could not set up an instance of the alpha".format(e))

alpha.on()

with open(LOGFILE, 'w') as LF:
    LF.write(','.join(COLUMNS))

    while True:
        _dt_    = datetime.datetime.utcnow().isoformat()
        _data_  = alpha.pm()

        LF.write(','.join([_dt_, _data_['PM1'],_data_['PM2.5'], _data_['PM10']]))

        sleep(SAMPLE_INT)

    LF.close()

P.S.

I hope this is the appropriate way to engage and ask questions, but I want your guidance: please don't hesitate to let me know if I should be asking this somewhere else or in some other manner or providing different content/formatting!

DancingQuanta commented 6 years ago

Few friendly suggestions:

Aside

The formatting above is called Github-flavoured markdown. This helps to discuss things on Github.

About run_opcn2_usbiss.py, well not my work ;). I suggest commenting your issues with run_opcn2_usbiss.py on its gist page https://gist.github.com/dhhagan/93e8dcf4d7983ace9433fb0a4c7ff3b5. Easier to discuss things there within the context of that script.