How to make calls with GSM modem using python - 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?

Related

Abort a pending serial.read() called in a parallel thread when the serial port gets closed in the main program

I am currently developing a custom Serial monitor in Python using the Tkinter framework as GUI generator and the Pyserial library to handle low level communication. To receive serial data and plot the received byte on the program window I am using a parallel thread that keeps living till the stop_serial_thread variable is set to True.
This variable is set in the main program when I close the window program since the closeSerialMonitor() function is automatically executed.
If I run the program without a serial Port opened everything runs as expected and the thread exit properly. When a serial communication is ongoing the thread get stuck without never exiting, probably because the ser.read() never returns
I've already tried the followings without any success:
serial read timeout != 0
calling ser.cancel_read() to cancel pending reading
creating a raise_exception method in the serialPlotter class to raise an exception and exiting the thread
What is the right way to properly close the thread and the serial port as soon as I want to close the program?
#comm.py
ser = serial.Serial()
stop_serial_thread = False
class serialPlotter(threading.Thread):
def __init__(self, name, monitor, autoscroll):
threading.Thread.__init__(self)
self.name = name
self.monitor = monitor
self.autoscroll = autoscroll
def receive(self):
if(ser.is_open == True):
chr = ser.read() # <----- blocking read
self.monitor.config(state=NORMAL)
self.monitor.insert(END,chr)
if self.autoscroll.get() == True:
self.monitor.see("end")
self.monitor.config(state=DISABLED)
def run(self):
print ("Starting " + self.name)
while(stop_serial_thread == False):
self.receive()
print("Ending " + self.name)
#serial_console.py
...
def closeSerialMonitor():
ser.cancel_read()
comm.stop_serial_thread = True
ser.close()
window.destroy()
...
When you close your application execute:
import sys # Import the module sys in order to be able to use exit()
sys.exit()
The sys.exit() function allows the developer to exit from Python.
I had the same problem some time ago with serial communication, and that's how I fixed it

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.

Python - socket CAN connection

I am using python to receive data from Linux socket CAN.
ID is 0x1f7d8401, whereas the ID of the data I received was 401, showing only the last three digits.
What should I modify to get the whole ID value except 0x?
Attached is the source code.
import can
import time
import os
print('\n\rCAN Rx test')
print('Bring up CAN0....')
os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
time.sleep(0.1)
try:
bus = can.interface.Bus(channel='can0', bustype='socketcan_native')
except OSError:
print('Cannot find PiCAN board.')
exit()
print('Ready')
try:
while True:
message = bus.recv() # Wait until a message is received.
c = '{0:f} {1:x} {2:x} '.format(message.timestamp, message.arbitration_id, message.dlc)
s=''
for i in range(message.dlc ):
s += '{0:x} '.format(message.data[i])
print(' {}'.format(c+s))
except KeyboardInterrupt:
#Catch keyboard interrupt
os.system("sudo /sbin/ip link set can0 down")
print('\n\rKeyboard interrtupt')
I just copied your code for testing, but with vcan0, instead of can0. It works fine.
Able to receive full address. I don't know how you are sending data.
I used cansend vcan0 1f7d8401#data. (No '0x' prefix for canid, here).

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

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)

Send data using a already open socket in python

I built a small program that listen to arbitrary connections and processes their requests, saving the events and connections information to a sqlite database. Once the connection is closed and opened again, it updates the source port.
This is working like a charm, but now I want to be able to randomly send those hosts messages, and I can't open new connections to them because they may be behind a NAT.
Is there a way to utilize the already open connections to transmit data? I mean, I could write a function in the thread_cliente's while True, that checks if there is a message in the database to be delivered to it, but I figured that there must be an easier or a more elegant way to do it.
Below is my code for a socket server. I translated my comments from Portuguese to English. Unfortunately my co-workers insist on using Portuguese variables, so this may cause some confusion.
#!/usr/bin/env python3
import socket
import sys
import logging
from _thread import start_new_thread
from MyPack import all_my_stuff
def print_help():
print(f'{sys.argv[0]} [TCP Port] [Someting that my program do]')
sys.exit()
def start_server(porta):
servico = socket.socket()
try:
servico.bind(('', porta))
except socket.error as e:
logging.error(e)
servico.listen(1024) # Is 1024 the max simultaneous client number?
while True:
cliente, endereco = servico.accept()
logging.debug(
f'New connection {endereco[0]}:{endereco[1]}'
)
try:
start_new_thread(thread_cliente, (cliente, endereco, ))
except Exception as e:
logging.error(e)
servico.close()
def thread_cliente(conexao, endereco):
while True:
data = conexao.recv(128)
if data:
resposta = None
sibulla_db.insere_conexao(endereco[0], endereco[1], sys.argv[1])
resposta = all_my_stuff.do_something(data, sys.argv[1], endereco)
if resposta:
logging.debug(f'Sending data: {resposta}')
conexao.sendall(bytes.fromhex(resposta))
else:
# Close connection
logging.debug(
f'Connection closed {endereco[0]}:{endereco[1]}'
)
break
conexao.close()
def main():
if len(sys.argv) == 1 or sys.argv[1] == 'help':
# are you running it right, or asking for help
print_help()
# Log
logging.basicConfig(
format='%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
filename='sibulla.log',
level=logging.DEBUG
)
# Start it
start_server(int(sys.argv[1]))
if __name__ == '__main__':
main()
Sending back on the original socket is probably the best way to talk to the clients.
If you're not concerned about the number of clients getting too high, you could keep the client connection open until you need it, and save the socket somewhere for later use.

Categories

Resources