1

I'm trying to understand why I'm not able to open multiple times the same serial port with Digi-Xbee (import digi.xbee) API for python while with Xbee (import xbee) API for python I can.

When I run the code bellow the exception digi.xbee.exception.InvalidOperatingModeException: Could not determine operating mode is raised.

from digi.xbee.devices import *
import time
import codecs


class start(object):
            
    while True:
        xbeeApi2 = DigiMeshDevice(port='/dev/ttyUSB0', baud_rate=9600)
        xbeeApi2.open()
        time.sleep(0.5)
        message = xbeeApi2.read_data(timeout=None)
        if message is not None:
            print(codecs.decode(message.data, 'utf-8'))  
        time.sleep(1) 

XBee module is a S2C (XB24C) set as Digimesh 2.4 TH, firmware 9002 (newest) with a USB Dongle. Python is 3.7 & my host hardware is a Raspberry Pi 3 B+ running Debian.

Any help would be appreciated.

EDIT 1 Exception is raised when, for the second time, {xbeeApi2.open()} is executed. In fact, my original code has multiple threads that import the class where the port is opened, many times before the previous thread had the chance to close it. The 'original' piece of code, that runs fine is bellow:

from xbee import ZigBee
import serial
import time



class start(object):
    
    while True:
        ser = serial.Serial('/dev/ttyUSB0', 9600)
        xbeeApi2 = ZigBee(ser, escaped=True)  # S2 e S2C
        time.sleep(0.5)
    message = ''
        try:
            message = xbeeApi2.wait_read_frame(timeout=0.5)
        except:
            pass #timeout exception
        if message is not None:
            print(message)
        time.sleep(1)

1 Answers1

0

Well, you aren't closing it. Why not create the device and open it before your while True loop?

And you could configure it to just sleep for 0.1 seconds when message is None to reduce processor load. You'll be able to keep up with the message queue that way -- if there was a message, you want to immediately check for another queued message before doing any sleeping.

from digi.xbee.devices import *
import time
import codecs

class start(object):
    xbeeApi2 = DigiMeshDevice(port='/dev/ttyUSB0', baud_rate=9600)
    xbeeApi2.open()
    while True:
        message = xbeeApi2.read_data(timeout=None)
        if message is not None:
            print(codecs.decode(message.data, 'utf-8'))
        else:
            time.sleep(0.1) 
tomlogic
  • 11,489
  • 3
  • 33
  • 59
  • Well, thanks for the reply. The code I pasted above is a simplification of what happens in my original code. I have multiple threads that import a class that opens the serial port. As I'm trying to migrate from 'import xbee' to 'import digi.xbee' I'd like to understand that different behavior. – Jonny Quest Jul 15 '20 at 12:24
  • OK. Maybe update your question with more information? What line throws the exception? Can you simplify your original code to something you can share here that still exhibits the failure? – tomlogic Jul 16 '20 at 00:30
  • I made the suggestions. About "Can you simplify your original code to something you can share here that still exhibits the failure?", the answer would be the first piece of code. – Jonny Quest Jul 16 '20 at 18:04
  • And when you try my version of your code? My guess is that you shouldn't be calling `open()` a second time. Can't you create your `DigiMeshDevice()` object and open it once, and then hold on to it for further calls to `.read_data()`? – tomlogic Jul 17 '20 at 05:08
  • Well, your code works like a charm. Unfortunately, with the code structure that I have today, I can't do just one open() (multiple threads and etc.). Apparently, or I keep using xbee library (not digi-xbee) or I'll have to change my code structure. That's why I'm trying to understand the difference between the two libraries, why with one I can do open() multiple times and with the other I can't. – Jonny Quest Jul 17 '20 at 14:54