How to establish bluetooth HFP service level connection - python

I am trying to establish a HFP (Hands Free Profile) service level connection using the python test code provided in the bluez repository.
In order to even run, the example needed some modifications:
Fix the deprecated import statement:
import glib
try:
from gi.repository import GObject
except ImportError:
import gobject as GObject
=>
from gi.repository import GLib as glib
Change the mainloop object:
mainloop = GObject.MainLoop()
=>
mainloop = glib.MainLoop()
Disable audio since it is not relevant to this test:
audio_supported = False
Encode commands sent to bytes:
os.write(self.fd, cmd + "\r\n")
=>
os.write(self.fd, f"{cmd}\r\n".encode())
Decode bytes received from buffer:
buf = buf.strip()
=>
buf = buf.decode('utf8').strip()
Change BDADDR_ANY to the phone's address:
At this point the example runs, in order to actually attempt a connection I added the following code:
fd = os.open("test.log", os.O_RDWR)
profile.NewConnection(options.path, fd, opts)
At this point I get an error from NewConnection() at the following line: fd = fd.take()
Looking at the code, fd seems to be a simple file descriptor so commenting out this line helps me move on.
The actual problem that I am facing now is that I get no reply from the device after sending the initial AT command (line 78 from the link above). As per the Bluetooth HFP 1.8 spec this is supposed to start the service level connection procedure. I am not even sure that my command is making it to the device.
I also tried another example which is a bit newer. This one is able to open a RFCOMM connection through a socket (BluetoothSocket) but the connection keeps getting reset. This is because the _read_at() function (line 181) does not receive anything from the device and times out.

Related

Python error 10042 Pusher WebSocket

I try to connect to Pusher Websocket API using the following code :
https://github.com/nlsdfnbch/Pysher/
import pysher
# Add a logging handler so we can see the raw communication data
import logging
root = logging.getLogger()
root.setLevel(logging.INFO)
ch = logging.StreamHandler(sys.stdout)
root.addHandler(ch)
pusher = pysher.Pusher('de504dc5763aeef9ff52')
# We can't subscribe until we've connected, so we use a callback handler
# to subscribe when able
def connect_handler(data):
channel = pusher.subscribe('live_trades')
channel.bind('trade', callback)
pusher.connection.bind('pusher:connection_established', connect_handler)
pusher.connect()
while True:
# Do other things in the meantime here...
time.sleep(1)
instead of some valid response, i get this every few seconds :
Connection: Error - [WinError 10042] An unknown, invalid, or
unsupported option or level was specified in a getsockopt or
setsockopt call Connection: Connection closed Attempting to connect
again in 10 seconds.
what is the problem ?
I saw the same error using a different library that uses websockets. I can see from your description (and link) that Pysher uses websockets.
I found (yet another) websocket client for Python that reported an issue with websockets, specifically with Python 3.6.4: [https://github.com/websocket-client/websocket-client/issues/370]
It references the bug in Python tracker as well [https://bugs.python.org/issue32394]
Upgrading to Python 3.6.5 worked for me. Alternatively, they suggest that upgrading to Windows 10 1703+ should work too (just for completeness; I have not verified this).

What is difference between pymodbus and pymodbus3 modules?

Hope you are doing great! I recently started using python for modbus communication. I want to clear my few doubts.
What module is better for modbus implementation using Python - minimalmodbus, pymodbus, pymodbus3 or else.
I am using python3.4 but unable to install pymodbus module using pip or any means. So I installed pymodbus3.
While using pymodbus3 module, I was able to write coils using following code:
import pymodbus3
import serial
from pymodbus3.pdu import ModbusRequest
from pymodbus3.client.sync import ModbusSerialClient as ModbusClient
from pymodbus3.transaction import ModbusRtuFramer
from serial.tools.list_ports import comports
client = ModbusClient(method = "rtu", port = 'COM4',stopbits = 1, bytesize = 8, parity = 'N', baudrate= 19200)
connection = client.connect()
client.write_coil(1000, 1, unit = 0x01)
For reading coil status (function 0x01):
result = client.read_coils(1000,1)
print(result)
client.close()
Its returning None.
Or writing to register and reading is also not working:
client.write_register(0, 1000, unit=0x01)
resu= client.read_holding_registers(0, 1, unit=0x01)
print(resu)
client.close()
Positive response is welcomed!
This is a rather old question, but I want to put this information out there so there is less confusion.
pymodbus3 was a fork of pymodbus created to support python3 before pymodbus did so. pymodbus now fully supports python3 and pymodbus3 is no longer maintained and does not have all the latest that the original does.
See https://github.com/uzumaxy/pymodbus3/issues/7 for details.

SMTP - Fast and reliable connection probing without auth?

Briefing
I am currently building a python SMTP Mail sender program.
I added a feature so that the user would not be able to log in if there was no active internet connection, I tried many solutions/variations to make the real time connection checking as swift as possible, there were many problems such as:
The thread where the connection handler was running suddenly lagged when I pulled out the ethernet cable ( to test how it would handle the sudden disconnect )
The whole program crashed
It took several seconds for the program to detect the change
My current solution
I set up a data handling class which would contain all the necessary info ( the modules needed to share info effectively )
import smtplib
from socket import gaierror, timeout
class DataHandler:
is_logged_in = None
is_connected = None
server_conn = None
user_address = ''
user_passwd = ''
#staticmethod
def try_connect():
try:
DataHandler.server_conn = smtplib.SMTP('smtp.gmail.com', 587, timeout=1) # The place where the connection is checked
DataHandler.is_connected = True
except (smtplib.SMTPException, gaierror, timeout):
DataHandler.is_connected = False # Connection status changed upon a connection error
I put a connection handler class on a second thread, the server connection process slowed down the gui when it was all on one thread.
from root_gui import Root
import threading
from time import sleep
from data_handler import DataHandler
def handle_conn():
DataHandler.try_connect()
smtp_client.refresh() # Refreshes the gui according to the current status
def conn_manager(): # Working pretty well
while 'smtp_client' in globals():
sleep(0.6)
try:
handle_conn() # Calls the connection
except NameError: # If the user quits the tkinter gui
break
smtp_client = Root()
handle_conn()
MyConnManager = threading.Thread(target=conn_manager)
MyConnManager.start()
smtp_client.mainloop()
del smtp_client # The connection manager will detect this and stop running
My question is:
Is this a good practice or a terrible waste of resources? Is there a better way to do this because no matter what I tried, this was the only solution that worked.
From what I know the try_connect() function creates a completely new smtp object each time it is run ( which is once in 0.6 seconds! )
Resources/observations
The project on git: https://github.com/cernyd/smtp_client
Observation: the timeout parameter when creating the smtp object improved response times drastically, why is that so?

Provide remote shell for Python script

I want to create a convenient simple way to connect to my running Python script remotely (via file sockets, TCP or whatever) to get a remote interactive shell.
I thought that this would be easy via IPython or so. However, I didn't really found any good example. I tried to start IPython.embed_kernel(), but that is blocking. So I tried to run that in another thread but that had many strange side effects on the rest of my script and I don't want any side effects (no replacement of sys.stdout, sys.stderr, sys.excepthook or whatever) and it also didn't worked - I could not connect. I found this related bug report and this code snippet which suggest to use mock.patch('signal.signal') but that also didn't worked. Also, why do I need that - I also don't want IPython to register any signal handlers.
There are also hacks such as pyringe and my own pydbattach to attach to some running Python instance but they seem to be too hacky.
Maybe QdbRemotePythonDebugger can help me?
My current solution is to setup an IPython ZMQ kernel. I don't just use
IPython.embed_kernel()
because that has many side effects, such as messing around with sys.stdout, sys.stderr, sys.excepthook, signal.signal, etc and I don't want these side effects. Also, embed_kernel() is blocking and doesn't really work out-of-the-box in a separate thread (see here).
So, I came up with this code, which is far too complicated in my opinion. (That is why I created a feature request here.)
def initIPythonKernel():
# You can remotely connect to this kernel. See the output on stdout.
try:
import IPython.kernel.zmq.ipkernel
from IPython.kernel.zmq.ipkernel import Kernel
from IPython.kernel.zmq.heartbeat import Heartbeat
from IPython.kernel.zmq.session import Session
from IPython.kernel import write_connection_file
import zmq
from zmq.eventloop import ioloop
from zmq.eventloop.zmqstream import ZMQStream
IPython.kernel.zmq.ipkernel.signal = lambda sig, f: None # Overwrite.
except ImportError, e:
print "IPython import error, cannot start IPython kernel. %s" % e
return
import atexit
import socket
import logging
import threading
# Do in mainthread to avoid history sqlite DB errors at exit.
# https://github.com/ipython/ipython/issues/680
assert isinstance(threading.currentThread(), threading._MainThread)
try:
connection_file = "kernel-%s.json" % os.getpid()
def cleanup_connection_file():
try:
os.remove(connection_file)
except (IOError, OSError):
pass
atexit.register(cleanup_connection_file)
logger = logging.Logger("IPython")
logger.addHandler(logging.NullHandler())
session = Session(username=u'kernel')
context = zmq.Context.instance()
ip = socket.gethostbyname(socket.gethostname())
transport = "tcp"
addr = "%s://%s" % (transport, ip)
shell_socket = context.socket(zmq.ROUTER)
shell_port = shell_socket.bind_to_random_port(addr)
iopub_socket = context.socket(zmq.PUB)
iopub_port = iopub_socket.bind_to_random_port(addr)
control_socket = context.socket(zmq.ROUTER)
control_port = control_socket.bind_to_random_port(addr)
hb_ctx = zmq.Context()
heartbeat = Heartbeat(hb_ctx, (transport, ip, 0))
hb_port = heartbeat.port
heartbeat.start()
shell_stream = ZMQStream(shell_socket)
control_stream = ZMQStream(control_socket)
kernel = Kernel(session=session,
shell_streams=[shell_stream, control_stream],
iopub_socket=iopub_socket,
log=logger)
write_connection_file(connection_file,
shell_port=shell_port, iopub_port=iopub_port, control_port=control_port, hb_port=hb_port,
ip=ip)
print "To connect another client to this IPython kernel, use:", \
"ipython console --existing %s" % connection_file
except Exception, e:
print "Exception while initializing IPython ZMQ kernel. %s" % e
return
def ipython_thread():
kernel.start()
try:
ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
pass
thread = threading.Thread(target=ipython_thread, name="IPython kernel")
thread.daemon = True
thread.start()
Note that this code is outdated now. I have made a package here which should contain a more recent version, and which can be installed via pip.
Other alternatives to attach to running CPython process without having it prepared beforehand. Those usually use the OS debugging capabilities (or use gdb/lldb) to attach to the native CPython process and then inject some code or just analyze the native CPython thread stacks.
pyringe
pyrasite
pystuck
pdb-clone
Here are other alternatives where you prepare your Python script beforehand to listen on some (tcp/file) socket to provide an interface for remote debugging and/or just a Python shell / REPL.
winpdb (cross platform) remote debugger
PyCharm IDE remote debugger,
doc
PyDev IDE remote debugger
Twisted Conch Manhole,
official example,
lothar.com example,
lysator.liu.se example,
related StackOverflow question,
blog.futurefoundries.com (2013)
very simple manhole, has also some overview over related projects
ispyd
Eric IDE
Trepan (based on pydb)
rpdb
rconsole
(part of rfoo)
Some overviews and collected code examples:
(QGIS) Example code for PyDev, Winpdb, Eric
Python Wiki: Python debugging tools,
Python Wiki: Python debuggers
(This overview is from here.)

Interfacing with TUN\TAP for MAC OSX (Lion) using Python

I found the following tun\tap example program and can not get it to work:
http://www.secdev.org/projects/tuntap_udp/files/tunproxy.py
I have modified the following lines:
f = os.open("/dev/tun0", os.O_RDWR)
ifs = ioctl(f, TUNSETIFF, struct.pack("16sH", "toto%d", TUNMODE))
ifname = ifs[:16].strip("\x00")
The first line was modified to reflect the real location of the driver. It was originally
f = os.open("/dev/net/tun", os.O_RDWR)
Upon running I get the following error:
sudo ./tuntap.py -s 9000
Password:
Traceback (most recent call last):
File "./tuntap.py", line 65, in <module>
ifs = ioctl(f, TUNSETIFF, struct.pack("16sH", "toto%d", TUNMODE))
IOError: [Errno 25] Inappropriate ioctl for device
I am using the latest tun\tap drivers installed from http://tuntaposx.sourceforge.net/download.xhtml
The OSX tun/tap driver seems to work a bit different. The Linux example dynamically allocates a tun interface, which does not work in OSX, at least not in the same way.
I stripped the code to create a basic example of how tun can be used on OSX using a self-selected tun device, printing each packet to the console. I added Scapy as a dependency for pretty printing, but you can replace it by a raw packet dump if you want:
import os, sys
from select import select
from scapy.all import IP
f = os.open("/dev/tun12", os.O_RDWR)
try:
while 1:
r = select([f],[],[])[0][0]
if r == f:
packet = os.read(f, 4000)
# print len(packet), packet
ip = IP(packet)
ip.show()
except KeyboardInterrupt:
print "Stopped by user."
You will either have to run this as root, or do a sudo chown your_username /dev/tun12 to be allowed to open the device.
To configure it as a point-to-point interface, type:
$ sudo ifconfig tun12 10.12.0.2 10.12.0.1
Note that the tun12 interface will only be available while /dev/tun12 is open, i.e. while the program is running. If you interrupt the program, your tun interface will disappear, and you will need to configure it again next time you run the program.
If you now ping your endpoint, your packets will be printed to the console:
$ ping 10.12.0.1
Ping itself will print request timeouts, because there is no tunnel endpoint responding to your ping requests.
so about the 'No such file or directory' error when doing:
f = os.open("/dev/tun12", os.O_RDWR)
this worked for me:
brew install Caskroom/cask/tuntap

Categories

Resources