Why can I only initialize specific PCAN Channel once? - python

Using python-can library here. Here's a simple code to print out can messages:
from can.interface import Bus
bus = Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=500000)
for msg in bus:
print(msg)
It runs just fine until I stop the program (running this in Pycharm IDE) and try to run it again. It will show this error:
can.interfaces.pcan.pcan.PcanError: A PCAN Channel has not been initialized yet or the initialization process has failed
I can't figure out why that is. It's fixed by 'restarting' the program, either by reinserting the CAN Dongle or by restarting Pycharm. Is it because the previous instance was cached somewhere? Would appreciate advice on this.

If I'm not mistaken you never shut down the first instance of the bus. You must call bus.shutdown() at the end of your script. If you do not call bus.shutdown() before you run it again, you are trying to instantiate and already existing bus instance.

This will happen, when your application will not close the channel with CAN_UnInitialize(), or when you break the application with a debugger. So please uninitialize the channel before you close your application, or reboot your system once.

Related

Icecast stream switching sources without the clients stopping playback

Good morning :)
I have some questions regarding an icecast-setup.
We have my own (Nextcloud)-Server sitting in our church. This works perfectly fine and since here in Germany the community services got forbidden already once during all this Covid19-stuff, we want to have a stream-setup. I managed to set up an icecast-instance on our server and we use my old laptop with Rocket Broadcaster and a Steinberg CI2 to provide the source for the stream. That works all as intended. We already used it once because we stopped public services for two weeks after one of our member got tested positive after he went abroad for a week.
Our operator on the PA doesn't want to have another display there, which would disturb him from listening the sermon.
My project regarding this: I have a RPi4 and a Behringer U-Phoria UMC202HD. The input atm is a standard mic, that is connected to the Interface.
The Pi is configured with darkice and uses its own icecast installation, while I am testing everything at home. Since I started the streaming project, after the service we switched Rocket Broadcaster to use VLC and a folder of old service recordings (mastered and in MP3-format) to provide a source to listen while we are at work or on travels. This option gets used pretty regularly and I want to keep it going.
My plan is to have a little box with a LED levelmeter, where the input level is shown. That should be done with a little python script. Also I want to add two buttons, where presets for the two setups get loaded. Button 1: kill the current source and start the darkice livestream. Button 2: kill the current source and start the playback of old recordings. Both options should have visual feedback for the operator. The raspberry has to work in headless mode without need for a VNC or SSH-connection for the normal usage.
My problem: I tried:
sudo killall darkice && /home/pi/darkice.sh
This code will get changed, because I probably have to use ices for the mp3-playback. So basically it kills darkice, starts the ices playback (for now only restarts the stream in a blink) and vice versa.
The bash-file exists and gets executed at reboot via cronjob. That works well. When I execute the above mentioned killall command, icecast continues the broadcast almost instantly, but the stream stops on the clients. Everyone needs to restart it.
Do I have an option to change the setup, so that I am able to switch between the two options without the need for everyone to restart?
My plan was to create a bash-script, where I do this all inside and execute it via GPIO-input and pythoncode.
Thanks in advance!

Pyngrok to getting connecting continuously

I have just started using ngrok, and while using the standard procedure, I can start the tunnel using ./ngrok tcp 22 and see that tunnel open in my dashboard,
But I would like to use pyngrok, and here when I use:
from pyngrok.conf import PyngrokConfig
from pyngrok import ngrok
ngrok.set_auth_token("<NGROK_AUTH_TOKEN>")
pyngrok_config = PyngrokConfig(config_path="/opt/ngrok/ngrok.yml")
ngrok.get_tunnels(pyngrok_config=pyngrok_config)
ssh_url = ngrok.connect()
It connects and generates a tunnel, but I can't see anything open in the dashboard, why?
Maybe because the python script executes and generates URL and then stops and comes out of it, but then how to make it keep running, or how to even start a tunnel using python or even API ? Please suggest the correct script, using python or API?
The thread with the ngrok tunnel will terminate as soon as the Python process terminates. So you are correct, the reason this is happening is because your script is not long lived. The easiest way to accomplish this is by following the example in the documentation.
Another issue is how you're setting the authtoken. Since you're not using the default config_path, you need to set this before setting the authtoken so it gets updated in the correct file (you'd also need to pass it to connect()). There are a couple ways to do this, but the easiest way from the docs is to just update the default config (since that's what will be used if you don't pass a pyngrok_config to any future method calls).
I also see that you're response variable is ssh_url, so you probably want to start a TCP tunnel to a port other than 80 (the default)—perhaps you've configured this in your ngrok.yml, but if not, I've updated the call to connect() to ensure this is the type of tunnel started for you and in case others try to use this same code snippet.
Full disclosure, I am the developer of pyngrok. Here is your code snippet updated with my changes.
import os, time
from pyngrok.conf import PyngrokConfig
from pyngrok import ngrok, conf
conf.get_default().config_path = "/opt/ngrok/ngrok.yml"
ngrok.set_auth_token(os.environ.get("NGROK_AUTH_TOKEN"))
ssh_tunnel = ngrok.connect(22, "tcp")
ngrok_process = ngrok.get_ngrok_process()
try:
# Block until CTRL-C or some other terminating event
ngrok_process.proc.wait()
except KeyboardInterrupt:
print(" Shutting down server.")
ngrok.kill()

Keeping ports open in a python script that is run continuously

I'm trying to develop a server script using python 3.4 that runs perpetually and responds to client requests on up to 5 separate ports. My preferred platform is Debian 8.0. The platform currently runs on a virtual machine in the cloud. My script works fine when I run it off the command line - I need to now (1) keep it running once I log off the server and (2) keep several ports open through the script so that a windows client can connect to them.
For (1),
After trying several options [I tried using upstart, added the script to rc.local, used nohup with & to run it off the terminal, etc] that didn't seem to work, I eventually found something that does seem to keep the script running, even if it's not very elegant - I wrote an hourly cron script that checks to see if the script is running in the process list, and if not, to execute it.
Whenever I login to the VM now, I see the following output when I type 'ps -ef':
root 22007 21992 98 Nov10 14-12:52:59 /usr/bin/python3.4 /home/userxyz/cronserver.py
I assume that the script is running based on the fact that there is an active process in the system. I mention this part because I suspect that there could be a correlation with part (2) of my issue.
For (2),
The script is supposed to open ports 49100 - 49105 and listen for connection requests, etc. When I run the script from the terminal, zenmap from my client machine verifies that these ports are open. However, when the cron job initiates the script, these ports don't seem to stay open. My windows client program can't connect to the script either.
The python code I use for listening to a port:
f = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
f.bind((serviceIP, 49101))
f.listen(5)
while True:
scName, address = f.accept()
[code to handle request]
scName.shutdown(socket.SHUT_WR)
scName.close()
Any insight or assistance would be greatly appreciated!
What you ask is not easy because it depends on a variety of factors:
What is the frequency of the data received?
How many clients are expected to connect to this server?
Is there a chance two clients try to connect at the same time?
How long it takes to handle some received data?
What do you need to do with your data?
Write to a database?
Write to a file?
Calculate something?
Etc.
Depending on your answer you'll have some design decisions to make for your solution.
But since you need an answer, here's a hack that represent a way to do things:
import socketserver
import threading
import datetime
class SleepyGaryReceptionHandler(socketserver.BaseRequestHandler):
log_file_name = "/tmp/sleepygaryserver.log"
def handle(self):
# self.request is defined in BaseRequestHandler
data_received = self.request.recv(1024)
# self.client_address is also defined in BaseRequestHandler
sender_address = self.client_address[0]
# This is where you are supposed to do something with your data
# This is an example
self.write_to_log('Someone from {} sent us "{}"'.format(sender_address,
data_received))
# A way to stop the server from going on forever
# But you could do this other ways but it depends what condition
# should cause the shutdown
if data_received.startswith(b"QUIT"):
finishing_thread = threading.Thread(target=self.finish_in_another_thread)
finishing_thread.start()
# This will be called in another thread to terminate the server
# self.server is also defined in BaseRequestHandler
def finish_in_another_thread(self):
self.write_to_log("Shutting down the server")
self.server.shutdown()
# Write something (with a timestamp) to a text file so that we
# know something is happenning
def write_to_log(self, message):
timestamp = datetime.datetime.now()
timestamp_text = timestamp.isoformat(sep=' ', timespec='seconds')
with open(self.log_file_name, mode='a') as log_file:
log_file.write("{}: {}\n".format(timestamp_text, message))
service_address = "localhost"
port_number = 49101
server = socketserver.TCPServer((service_address, port_number),
SleepyGaryReceptionHandler)
server.serve_forever()
I'm using here the socketserver module instead of listening directly at a socket. This standard library module has been written to simplify writing a server. so use it!
All I do here is write to a text file what has been received. You would have to adapt it to your use.
But to have it running continuously use a cron job but to start it at the startup of the computer. Since this script will block until the server is stopped, we have to run it in the background. It would look something like that:
#reboot /usr/bin/python3 /home/sleepygary/sleppys_server.py &
I have tested it and after 5 hours it still does his thing.
Now like I said, it is a hack. If you want to go all the way and do things like any other services on your computer you have to program it in a certain way. You can find more information on this page: https://www.freedesktop.org/software/systemd/man/daemon.html
I'm really tired so there may be some errors here and there.

PyVISA SerialInstrument requires hard reset to connect after failure

I am working with a Keysight waveform generator and pyVisa and I notice that if my code doesn't complete successfully and ends I need to perform a hard reset of the device to attempt my code again.
I have tried resetting the device under the __del__ method so that the device is in a known state but that doesn't seem to work. I've also tried using pyvisa.resources.SerialInstrument.clear(). Has anyone else had a problem like this and how did you solve it?
The host computer is running windows 7. PyVISA version is 1.8. After the program fails by me cancelling the python script I will try to send a simple *IDN? SCPI command to the device and I get error:
pyvisa.errors.VisaIOError: VI_ERROR_TMO (-1073807339): Timeout expired before operation completed.
If I try to call pyvisa.resources.SerialInstrument.clear() on the device I get error
pyvisa.errors.VisaIOError: VI_ERROR_INV_SETUP (-1073807302): Unable to start operation because setup is invalid (usually due to attributes being set to an inconsistent state).
The problem was that the device was still being connected to by another instance. The cause of that was because running visa.ResourceManager().list_resources() was listing the device twice, once as a USB device and also as an ASRL.
The solution was to call visa.ResourceManager().list_resources(query='USB?*') to make sure that the instrument is only listed once in my results. (Alternately, I could have disabled USB or GPIB in the device settings.) Then call device.clear() immediately after opening the resource to make sure that the buffers were empty because at the error there might have been unread data there. This solved the problem.

PsychoPy: send triggers over parallel port of PC with XP 32 bit

I am having problems with sending triggers from a 32 bit PC with Windows XP Professional and Psychopy v.1.81.03 to the parallel port.
I am positive that the port address is 378, and am able to send triggers with Eprime and I am able to turn specific pins on and off with the software parmon (http://english.eazel.com/lv/group/view/kl35264/Parmon.htm)
I have tried using the experiment posted by Stéphanie and Nicholas (see this post in the psychopy google group: https://groups.google.com/forum/#!topic/psychopy-users/PxPhRDkuu2A)
I have verified that pywin32 (version 217) and parallel are installed, and tried both
port = parallel.ParallelPort(address=0x0378)
port = parallel.PParallelInpOut32(address=0x0378)
When using ParallelPort, I get:
Traceback (most recent call last):
File “ D:\SebastianKorb\untitled2_lastrun.py”, line 65, in
port = parallel.ParallelPort(address=0x0378) AttributeError: ‘module’
object has no attribute ‘ParallelPort’
Line 65 is where the command port = parallel.ParallelPort(address=0x0378)
is executed (note though that before that there is the line from psychopy import parallel)
When using PParallelInpOut32 I get the same (only now the error is about ‘PParallelInpOut32’)
I also tried to run the few lines of code shown on the psychopy reference manual (http://www.psychopy.org/api/parallel.html):
from psychopy import parallel
port = parallel.ParallelPort(address=0x0378)
port.setData(4)
port.readPin(2)
port.setPin(2, 1)
But again, I get the same type of error.
I should mention that I have also verified that I have administrator access to the file C:\Windows\system32\drivers\parport.sys
Can you please advise me on what I should try next?
I overlooked that it's actually the other way around. The direct calls to the parallel-port functions (as below) are deprecated. Nevertheless, they should still work. So maybe give it a try:
from psychopy import parallel
parallel.setPortAddress(0x378) #address for parallel port on many machines
parallel.setData(0) #sets all pins low
parallel.setPin(2,1) # set a certain pin high
parallel.setData(0) #sets all pins low
You should leave the pin high for a while or leave out the last line. Otherwise, you won't be able to detect the change. That's also how it is done in the Coder hardware demo "parallelPortOutput.py". Maybe try this first.
Best,
Axel
Addition:
Sebastian, my hunch at the moment is that the port does not even get initiated. I think the problem at the moment is that the respective error messages are only logged, but no informative error message is thrown (check the log files). That means that actually somehow the port drivers cannot be accessed on your system for some reason.
In the Coder Shell type from psychopy import parallel and then do next port = parallel.ParallelPort() (no address). Now just type port and paste the output here. My guess is that you only get the base class (ParallelPort) with which you cannot do anything, i.e., something like <psychopy.parallel.ParallelPort object at 0xe4805b0>. In that case, you would need to fix access to the drivers somehow.
I'm gong to back Axel's "hunch" here. I think it's extremely likely that either you don't have a parallel port driver installed or it isn't working. Try installing the InpOut32 driver from here, restart your computer and see if that fixes it:
http://www.highrez.co.uk/Downloads/InpOut32/
cheers,
Jon

Categories

Resources