Problem opening same port multiple times in python Digi-XBee API - python

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)

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)

Related

no data found when trying to log CAN data using a PiCAN2 and a raspberry pi

I'm not sure what I'm really doing here and need a little guidance to point me in the right direction with regards to CANBUS sniffing.
I am currently using a PiCAN2 (with gps and gyro) with a raspberry pi 4 to sniff the CANBUS output from a mobileye detection unit. I have the CAN output protocol of the mobileye, the raspberry pi is set up with all the libraries installed and everything seems to be working correctly except the capture of CAN data (the logger captures GPS and all the kinematic data perfectly).
I've been going around in circles because I can't seem to find why I get very intermittent CAN data from the mobileye unit.
I am trying to get send a request to the unit and waiting for any output but am not getting anything.
I even just try to run:
candump can0 or cansniffer can0 and dont get anything.
I've tried to tie directly to the vehicle CAN as well and get intermittent CAN as well.
I've soldered on a jumper to bridge JP2 to use the 120 ohm resistor but that makes the can0 interface disappear. Confirmed this using ifconfig and so I leave the jumper open.
I also sometimes get an sm.smBUS error message that bus.recv() does not exist?
My code is as follows:
from gps import *
import datetime
import sys
import smbus
import math
import time, inspect
import signal
import serial
import RPi.GPIO as GPIO
import can
import os
import binascii
import bitstring
from bitstring import BitArray
import threading
from threading import Thread
from can import Message
try:
import queue
except ImportError:
import Queue as queue
#### Bring up can0 interface at 500kbps
os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
time.sleep(0.1)
print('Ready')
#### define global variables
PICANGPS_PORT = "/dev/serial0"
led = 22
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(led,GPIO.OUT)
GPIO.output(led,True)
mbdata = ''
PID_REQUEST= 0x7DF
###### ive left out some bits relating to GPS and the file name definitions
#### Communicate with CAN interface
try:
bus = can.interface.Bus(channel='can0', bustype='socketcan_native')
except OSError:
print('Cannot find PiCAN board.')
GPIO.output(led,False)
exit()
#### CAN Receive thread
def can_rx_task(): # Receive thread
while True:
print ('Receiving Message')
msg = bus.recv()
if msg.arbitration_id == MB_DISPLAY:
q.put(msg) # Put message into queue
print ('Received Message!')
if msg.arbitration_id == CAR_SIGNALS:
q.put(msg) # Put message into queue
print ('Received Message!')
#### CAN Transmit thread
def can_tx_task(): # Transmit thread
while True:
GPIO.output(led,True)
# Sent a Engine coolant temperature request
msg = can.Message(arbitration_id=PID_REQUEST,data=[0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],extended_id=False)
bus.send(msg)
time.sleep(0.05)
GPIO.output(led,False)
time.sleep(0.05)
q = queue.Queue()
rx = threading.Thread(target = can_rx_task)
rx.start()
tx = threading.Thread(target = can_tx_task)
tx.start()
#### main loop
try:
while True:
# create log file - timestamped
f=open(path+fname+".csv",'a')
# get current timestamp
now = datetime.datetime.now()
picantimestamp = now.strftime("%Y/%m/%d %H:%M:%S.%f")
#### mobileye CAN sniff loop
for i in range(4):
# CAN sniff for CAN data frame
if q.empty() != True: # Check if there is a message in queue
mbdata = q.get()
c = '{0:f} {1:d} {2:x} '.format(mbdata.timestamp,count, mbdata.arbitration_id, mbdata.dlc)
s = ''
print ('Received CAN Message')
for j in range(mbdata.dlc):
s += '{0:x} '.format(mbdata.data[j])
Does anyone have any suggestions on what I should try to troubleshoot this?
Happy to discuss it further, I'm just a little confused and would gladly take any input.

How to make calls with GSM modem using python

I am trying to use gsmmodem-new on python to make calls from attached gsm modem. The modem is connected on serial com 1 and the baud rate is set at 115200. Sim card has no PIN code enabled.
I am simply trying to use the example provided by the developers
#!/usr/bin/env python
"""\
Demo: dial a number (simple example using polling to check call status)
Simple demo app that makes a voice call and plays sone DTMF tones (if
supported by modem)
when the call is answered, and hangs up the call.
It polls the call status to see if the call has been answered
Note: you need to modify the NUMBER variable for this to work
"""
from __future__ import print_function
import sys, time, logging
from hashlib import new
PORT = 'COM1'
BAUDRATE = 115200
NUMBER = '6973233298' # Number to dial - CHANGE THIS TO A REAL NUMBER
PIN = None # SIM card PIN (if any)
waitingForModemToRespondInSeconds = 10
from gsmmodem.modem import GsmModem
from gsmmodem.exceptions import InterruptedException, CommandError
def main():
if NUMBER == None or NUMBER == '00000':
print('Error: Please change the NUMBER variable\'s value before
running this example.')
sys.exit(1)
print('Initializing modem...')
logging.basicConfig(format='%(levelname)s: %(message)s',
level=logging.DEBUG)
modem = GsmModem(PORT, BAUDRATE)
modem.connect(PIN,waitingForModemToRespondInSeconds)
print('Waiting for network coverage...')
modem.waitForNetworkCoverage(30)
print('Dialing number: {0}'.format(NUMBER))
call = modem.dial(NUMBER)
print('Waiting for call to be answered/rejected')
wasAnswered = False
while call.active:
if call.answered:
wasAnswered = True
print('Call has been answered; waiting a while...')
time.sleep(3.0)
print('Playing DTMF tones...')
try:
if call.active: # Call could have been ended by remote party while we waited in the time.sleep() call
call.sendDtmfTone('9515999955951')
except InterruptedException as e:
# Call was ended during playback
print('DTMF playback interrupted: {0} ({1} Error {2})'.format(e, e.cause.type, e.cause.code))
except CommandError as e:
print('DTMF playback failed: {0}'.format(e))
finally:
if call.active: # Call is still active
print('Hanging up call...')
call.hangup()
else: # Call is no longer active (remote party ended it)
print('Call has been ended by remote party')
else:
# Wait a bit and check again
time.sleep(0.5)
if not wasAnswered:
print('Call was not answered by remote party')
print('Done.')
modem.close()
if __name__ == '__main__':
main()
but the process stucks when a connection is trying to be established with the modem. It seems that it cannot connect to the modem in order to proceed to the next steps.
Can someone please help me?

Missing packages with python-xbee library and raspberry

I'm trying to send some packages from an MSP to a Raspberry Pi 3 through 2 Xbee S1 modules.
Xbee are configured as DigiMesh 2.4 with escaped frames, one as router and other as coordinator. At the raspberry the connection is made with USB dongle.
My code, at MSP, sends a package at every 10 us with CTS flow control. When the coordinator is plugged into my PC running windows, I can see, through XCTU, all packages arriving, everything just fine!!!
But, when the dongle is at raspberry, running Raspbian and the following code, some packages can not arrive.
As everything works properly with XCTU, the problem resides in the code, probably handling serial port or anything similar to that.
So, any help would be much appreciate!!!
start.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# copyright: Thiago Cruz <thiagoalberto#gmail.com>
import sys
import os
from PyQt4 import QtGui
from middleware.QueueMiddleware import QueueMiddleware
from jobs.ScheduleJob import ScheduleJob
def startQueue():
queue = QueueMiddleware()
queue.start()
def assyncSchedule():
schedule = ScheduleJob()
schedule.run()
def runApp():
startQueue()
app = QtGui.QApplication(sys.argv)
sys.exit(app.exec_())
if __name__ == '__main__':
runApp()
QueueMiddleware.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# copyright: Thiago Cruz <thiagoalberto#gmail.com>
import threading
import time
import serial
import Queue
from middleware.DataProcessorGear import DataProcessorGear
from xbee import ZigBee
minutes = 0
class QueueMiddleware(threading.Thread):
__instance = None
PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
# The XBee addresses I'm dealing with
BROADCAST = '\x00\x00\x00\x00\x00\x00\xFF\xFF'
UNKNOWN = '\xFF\xFE' # This is the 'I don't know' 16 bit address
def __new__(cls):
if QueueMiddleware.__instance is None:
QueueMiddleware.__instance = super(QueueMiddleware, cls).__new__(cls)
return QueueMiddleware.__instance
def __init__(self):
QueueMiddleware.__instance = self
threading.Thread.__init__(self)
self.dataPacketsQueue = Queue.Queue()
# Create API object, which spawns a new thread
self.ser = serial.Serial(
port='/dev/ttyUSB0',
baudrate = 9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
timeout=1
)
self.xbeeApi = ZigBee(self.ser, callback=self.message_received, escaped=True)
print 'start queue'
def __del__(self):
# halt() must be called before closing the serial
# port in order to ensure proper thread shutdown
self.xbeeApi.halt()
self.ser.close()
self.processor = None
def run(self):
# Do other stuff in the main thread
while True:
try:
time.sleep(1)
#if self.dataPacketsQueue.qsize() > 0:
# lock = threading.Lock()
# processor = DataProcessorGear(self.dataPacketsQueue, lock)
# processor.start()
except KeyboardInterrupt:
break
def message_received(self, data):
global minutes
minutes += 1
print minutes
self.dataPacketsQueue.put(data, block=True, timeout=None)
I already tried to change the values of time.sleep() and have suppressed the execution of the subsequent threads to "isolate" the problem.
My console displays values from ~120 to ~170. MSP only sends 200 data packages!!
So... any guesses ??
Thanks in advance.
Enable hardware flow control and change the baudrate from 9600 to 115200. You'll have to update your XBee module configuration for the new baudrate, but you'll stand a chance of getting your packets through.
I assume you meant to write that you're sending packets every 10ms instead of every 10us. At 10ms/packet, you're at 100 packets/second. 9600 baud is only about 960 characters per second, and your packets are surely larger than 9 characters with the API overhead.
Kind of a solution.....
After trying different approaches in my code, even tried the script below...
#!/usr/bin/python
import serial
serialport = serial.Serial("/dev/ttyUSB0", 115200, timeout=None,rtscts=True,dsrdtr=True)
while True:
serialport.flush()
command = serialport.readline()
print str(command).encode('hex')
I was able to get a desired behavior by changing the XBee MR parameter (Mesh unicast retries - The maximum number of network packet delivery attempts) to the maximum (0x7), none of my packages are lost, even for a delay of 0s (zero) between the transmission of each package.
Probably, as said by tomlogic, if I run my code on a faster PC, I believe, I'll get my packages.
When I do this test, i'll post the results here.
Thanks.

How to prevent raw_input from blocking on windows?

I'm trying to build a basic chat application and I need it to post messages from other users while waiting for input from the client.
Of course select() is not an option on Windows for this case.
What else can I do?
I tried this, but the program still waits for input and then shows other messages:
from socket import *
from threading import *
s=socket(AF_INET,SOCK_STREAM)
s.connect(('10.0.0.11',1340))
def sender():
while (True):
try:
s.send(raw_input(">> "))
except:
return
def geter():
while(True):
print s.recv(1000)
Thread(target=sender).start()
Thread(target=geter).start()

multiprocessing with serial port

I've a target board which sends me CPU load for every 1sec which communicates through serial port. I want to write a python code which reads data from serial port for every 1sec second and writes to a file and also it should check for user input i.e. if user enters command it should pass that command to target board.
You can create two threads, one listening for user input, the other polling the serial port every second. Check out threading for information on multithreading in python and pyserial for information on reading from serial ports. The threading package provides your desired repetition functionality: https://docs.python.org/2/library/threading.html#timer-objects
[EDIT]
Sample code, obviously replace /dev/ttyS1 with the desired port and do something useful with the user input:
import serial
import threading
def read_from_serial():
# port = "/dev/ttyS1"
# ser = serial.Serial(port, 19200, timeout = 1)
# print ser.readline()
# ser.close()
print "read"
threading.Timer(1, read_from_serial).start()
if __name__ == "__main__":
serial_thread = threading.Thread(target = read_from_serial())
serial_thread.start()
while True:
print raw_input("User input: ")

Categories

Resources