mcclown / pyseneye

A module for interacting with Seneye range of aquarium and pond sensors
Apache License 2.0
8 stars 4 forks source link

Adding support for multiple devices in SUDevice() #8

Open meteosat007 opened 4 years ago

meteosat007 commented 4 years ago

Hi,

Been using this code for 2 years now and will be adding a second USB to the Pi and want to extract values from both. I can see that d=SUDevice() delivers the serial number, but despite many attempts I cannot work out how to use <pyseneye.sud.SUDevice object at 0x76a505d0> my response, in the next request d.action(Action.ENTER_INTERACTIVE_MODE) to allow me to retrieve data from 2 USB Seneye connected to 1 RPi.

Sure its a simple fix but it has me scratching my head here.

Regards

mcclown commented 4 years ago

Great to hear that you've been using this code for so long successfully!

I never built the library with more than 1 device in mind an unfortunately I don't have 2 to test/validate. Looking at the code I suspect that the change required would be somewhere between line 522 and 533 in sud.py.

The most likely candidate is line 522, according to the documentation here you can pass _findall=True to usb.core.find and that will return multiple devices.

I'd try modifying sud.py to include the following below. Sorry I haven't been able to test this as my Pi is being used for something else right now...so this is really back of a napkin coding, off the top of my head.

class SUDevice:

    def __init__(self, dev_index = 0):

        dev_list = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, find_all=True)
        dev = dev_list[dev_index]

If you still have an issue I'll try to borrow a friends Seneye and extend to add this functionality. If you do get it to work then add a pull request and I'll release a new version with this new functionality.

Let me know if you need any more help.

meteosat007 commented 4 years ago

Hi Stephen,

No worries, the second Seneye arrives today so will test and share results.

On the other point.

Which part of the returned <pyseneye.sud.SUDevice object at 0x76a505d0> from the d=SUDevece() is then sent to the interactive mode next step d.action(Action.ENTER_INTERACTIVE_MODE).

I have tried 0x76a505d0 which is the serial number I guess, the whole string in speech marks, no speech marks but it returns an error each time.

Checked you very comprehensive documentation and all other stuff on the WEB but struggling.

With you change above I can use the correct part of the returned d=SUDevice() from each device to get the results.

Hope that makes sense.

Alan

From: Stephen Mc Gowan notifications@github.com Reply to: mcclown/pyseneye reply@reply.github.com Date: Wednesday, 18 March 2020 at 09:24 To: mcclown/pyseneye pyseneye@noreply.github.com Cc: Alan Sullivan alansullivan65@icloud.com, Author author@noreply.github.com Subject: Re: [mcclown/pyseneye] Question on the response to d=SUDevice() (#8)

Great to hear that you've been using this code for so long successfully!

I never built the library with more than 1 device in mind an unfortunately I don't have 2 to test/validate. Looking at the code I suspect that the change required would be somewhere between line 522 and 533 in sud.py.

The most likely candidate is line 522, according to the documentation here you can pass find_all=True to usb.core.find and that will return multiple devices.

I'd try modifying sud.py to include the following below. Sorry I haven't been able to test this as my Pi is being used for something else right now...so this is really back of a napkin coding, off the top of my head.

class SUDevice:

    def init(self, dev_index = 0):

        dev_list = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, find_all=True)         dev = dev_list[dev_index] If you still have an issue I'll try to borrow a friends Seneye and extend to add this functionality. If you do get it to work then add a pull request and I'll release a new version with this new functionality.

Let me know if you need any more help.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

mcclown commented 4 years ago

What I've specified isn't going to use the serial numbers of the devices, it will just identify them in the order the USB identifies them in. If that order is the same every time, then what I've specified should work.

You'll call SUDevice(0) for the first device and SUDevice(1) for the second device. SUDevice() will just select the first device by default.

If that doesn't consistently identify the devices in the same order, then we'll have to get a bit more involved and try to identify them by their serial numbers.

meteosat007 commented 4 years ago

Great to hear that you've been using this code for so long successfully!

I never built the library with more than 1 device in mind an unfortunately I don't have 2 to test/validate. Looking at the code I suspect that the change required would be somewhere between line 522 and 533 in sud.py.

The most likely candidate is line 522, according to the documentation here you can pass _findall=True to usb.core.find and that will return multiple devices.

I'd try modifying sud.py to include the following below. Sorry I haven't been able to test this as my Pi is being used for something else right now...so this is really back of a napkin coding, off the top of my head.

class SUDevice:

    def __init__(self, dev_index = 0):

        dev_list = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID, find_all=True)
        dev = dev_list[dev_index]

If you still have an issue I'll try to borrow a friends Seneye and extend to add this functionality. If you do get it to work then add a pull request and I'll release a new version with this new functionality.

Let me know if you need any more help.

I made changes as below but get this error.

class SUDevice: """Encapsulates a Seneye USB Device and it's capabilities."""

def __init__(self**, dev_index = 0**):
    """Initialise and open connection to Seneye USB Device.

    Allowing for actions to be processed by the Seneye device.

    ..  note:: When finished SUDevice.close() should be called, to
        free the USB device, otherwise subsequent calls may fail.

    ..  note:: Device will need to be in interactive mode, before taking
        any readings. Send Action.ENTER_INTERACTIVE_MODE to do this.
        Devices can be left in interactive mode but readings will not be
        cached to be sent to the Seneye.me cloud service later.

    :raises ValueError: If USB device not found.
    :raises usb.core.USBError: If permissions or communications error
    occur while trying to connect to USB device.

    :Example:
        >>> from pyseneye.sud import SUDevice, Action
        >>> d.action(Action.ENTER_INTERACTIVE_MODE)
        >>> s = d.action(Action.SENSOR_READING)
        >>> s.ph
        8.16
        >>> s.nh3
        0.007
        >>> s.temperature
        25.125
        >>> d.action(Action.LEAVE_INTERACTIVE_MODE)
        >>> d.close()
    """
    dev_list = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID**, find_all=True**)
    **dev = dev_list[dev_index]**

    if dev is None:
        raise ValueError('Device not found')

Error seen is with d=SUDevice() or d=SUDevice(0)

sudo python3 seneye-home.py Traceback (most recent call last): File "seneye-home.py", line 70, in main() File "seneye-home.py", line 15, in main d = SUDevice(0) File "/usr/local/lib/python3.4/dist-packages/pyseneye/sud.py", line 523, in init dev = dev_list[dev_index] TypeError: 'generator' object is not subscriptable

Sorry for all the questions but this level of code not normally my area...

Alan

mcclown commented 4 years ago

Ah, this may take a little more thought. Let me see if I can get a python environment spun up at the weekend, then I can take a look.

meteosat007 commented 4 years ago

OK no worries. I will search the internet too for answers. 2nd Seneye here now so will plug it in and experiment.

Will try Python 2 as I think the syntax on your suggestion is different between versions and I will let you know if I make progress.

Alan

From: Stephen Mc Gowan notifications@github.com Reply to: mcclown/pyseneye reply@reply.github.com Date: Wednesday, 18 March 2020 at 12:43 To: mcclown/pyseneye pyseneye@noreply.github.com Cc: Alan Sullivan alansullivan65@icloud.com, Author author@noreply.github.com Subject: Re: [mcclown/pyseneye] Adding support for multiple devices in SUDevice() (#8)

Ah, this may take a little more thought. Let me see if I can get a python environment spun up at the weekend, then I can take a look.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.

meteosat007 commented 4 years ago

Hi Stephen,

So good news is that I have found a way to specify the USB address in the SUDevice call so that I can call either Seneye.

It will require me to run two separate python scripts, although I may make them into one.

Both of my devices are on the same USB bus=1 so only the address 4 or 5 is required.

Changes to sud.py can be seen below.

class SUDevice:

    """Encapsulates a Seneye USB Device and it's capabilities."""

    def init(self, address):

        """Initialise and open connection to Seneye USB Device.

        Allowing for actions to be processed by the Seneye device.

        ..  note:: When finished SUDevice.close() should be called, to

            free the USB device, otherwise subsequent calls may fail.

        ..  note:: Device will need to be in interactive mode, before taking

            any readings. Send Action.ENTER_INTERACTIVE_MODE to do this.

            Devices can be left in interactive mode but readings will not be

            cached to be sent to the Seneye.me cloud service later.

        :raises ValueError: If USB device not found.

        :raises usb.core.USBError: If permissions or communications error

        occur while trying to connect to USB device.

        :Example:

            >>> from pyseneye.sud import SUDevice, Action

            >>> d.action(Action.ENTER_INTERACTIVE_MODE)

            >>> s = d.action(Action.SENSOR_READING)

            >>> s.ph

            8.16

            >>> s.nh3

            0.007

            >>> s.temperature

            25.125

            >>> d.action(Action.LEAVE_INTERACTIVE_MODE)

            >>> d.close()

        """

        #dev = usb.core.find(idVendor=VENDOR_ID, idProduct=PRODUCT_ID)

        dev = usb.core.find(bus=1, address=address)

        print(dev)

It works a treat for me but I’m sure you may find a better way no doubt.

Regards

Alan

From: Stephen Mc Gowan notifications@github.com Reply to: mcclown/pyseneye reply@reply.github.com Date: Wednesday, 18 March 2020 at 12:43 To: mcclown/pyseneye pyseneye@noreply.github.com Cc: Alan Sullivan alansullivan65@icloud.com, Author author@noreply.github.com Subject: Re: [mcclown/pyseneye] Adding support for multiple devices in SUDevice() (#8)

Ah, this may take a little more thought. Let me see if I can get a python environment spun up at the weekend, then I can take a look.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or unsubscribe.