Good morning, I am using git hub examples as a base to make a can bus connection through the pican2 duo can, the python can configuration and the pican2 drivers were installed correctly the problem comes when running the code since A few seconds after running the program I get the extended_id and socketcan_native error, it appears as follows:
" init() got an unexpected keyword argument 'is_extended_id'".
I am viewing the comments and it has worked for several of them and several have the same problem. If anyone has the same problem or has already solved it, can you guide me.
I am using python can 4.1.0.
And tried to fix it by downloading older versions of python can, but when entering the commands : sudo apt-get update
sudo apt-get upgrade automatically upgrades me to the newest version of python. I have to send these commands to be able to use the pican2 duo can card.
I leave the url that I am using
https://github.com/skpang/PiCAN-Python-examples/blob/master/obdii_logger.py
#!/usr/bin/python3
#
## obdii_logger.py
#
# This python3 program sends out OBDII request then logs the reply to the sd card.
# For use with PiCAN boards on the Raspberry Pi
# http://skpang.co.uk/catalog/pican2-canbus-board-for-raspberry-pi-2-p-1475.html
#
# Make sure Python-CAN is installed first http://skpang.co.uk/blog/archives/1220
#
# 24-08-16 SK Pang
#
import RPi.GPIO as GPIO
import can
import time
import os
import queue
from threading import Thread
led = 22
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(led,GPIO.OUT)
GPIO.output(led,True)
# For a list of PIDs visit https://en.wikipedia.org/wiki/OBD-II_PIDs
ENGINE_COOLANT_TEMP = 0x05
ENGINE_RPM = 0x0C
VEHICLE_SPEED = 0x0D
MAF_SENSOR = 0x10
O2_VOLTAGE = 0x14
THROTTLE = 0x11
PID_REQUEST = 0x7DF
PID_REPLY = 0x7E8
outfile = open('log.txt','w')
print('\n\rCAN Rx test')
print('Bring up CAN0....')
# 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')
try:
bus = can.interface.Bus(channel='can0', bustype='socketcan_native')
except OSError:
print('Cannot find PiCAN board.')
GPIO.output(led,False)
exit()
def can_rx_task(): # Receive thread
while True:
message = bus.recv()
if message.arbitration_id == PID_REPLY:
q.put(message) # Put message into queue
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=[0x02,0x01,ENGINE_COOLANT_TEMP,0x00,0x00,0x00,0x00,0x00],extended_id=False)
bus.send(msg)
time.sleep(0.05)
# Sent a Engine RPM request
msg = can.Message(arbitration_id=PID_REQUEST,data=[0x02,0x01,ENGINE_RPM,0x00,0x00,0x00,0x00,0x00],extended_id=False)
bus.send(msg)
time.sleep(0.05)
# Sent a Vehicle speed request
msg = can.Message(arbitration_id=PID_REQUEST,data=[0x02,0x01,VEHICLE_SPEED,0x00,0x00,0x00,0x00,0x00],extended_id=False)
bus.send(msg)
time.sleep(0.05)
# Sent a Throttle position request
msg = can.Message(arbitration_id=PID_REQUEST,data=[0x02,0x01,THROTTLE,0x00,0x00,0x00,0x00,0x00],extended_id=False)
bus.send(msg)
time.sleep(0.05)
GPIO.output(led,False)
time.sleep(0.1)
q = queue.Queue()
rx = Thread(target = can_rx_task)
rx.start()
tx = Thread(target = can_tx_task)
tx.start()
temperature = 0
rpm = 0
speed = 0
throttle = 0
c = ''
count = 0
# Main loop
try:
while True:
for i in range(4):
while(q.empty() == True): # Wait until there is a message
pass
message = q.get()
c = '{0:f},{1:d},'.format(message.timestamp,count)
if message.arbitration_id == PID_REPLY and message.data[2] == ENGINE_COOLANT_TEMP:
temperature = message.data[3] - 40 #Convert data into temperature in degree C
if message.arbitration_id == PID_REPLY and message.data[2] == ENGINE_RPM:
rpm = round(((message.data[3]*256) + message.data[4])/4) # Convert data to RPM
if message.arbitration_id == PID_REPLY and message.data[2] == VEHICLE_SPEED:
speed = message.data[3] # Convert data to km
if message.arbitration_id == PID_REPLY and message.data[2] == THROTTLE:
throttle = round((message.data[3]*100)/255) # Conver data to %
c += '{0:d},{1:d},{2:d},{3:d}'.format(temperature,rpm,speed,throttle)
print('\r {} '.format(c))
print(c,file = outfile) # Save data to file
count += 1
except KeyboardInterrupt:
#Catch keyboard interrupt
GPIO.output(led,False)
outfile.close() # Close logger file
os.system("sudo /sbin/ip link set can0 down")
print('\n\rKeyboard interrtupt')
I found through experimentation that changing 'socketcan-native' to 'socketcan' got me past that error. This worked for me:
bus = can.interface.Bus(channel = 'can0', bustype = 'socketcan')
The can.interface.Bus() call works for me when I use:
message = can.Message(arbitration_id=0x111, data=[0, 1, 2, 3, 4, 5, 6, 7], is_extended_id=False)
When I got the sample code it didn't have:
is_exteneded_id
Instead it had:
extended_id
I notice in your code you have:
extended_id
Related
I'm writing a Jukebox program that plays media based on key combinations (A1, B2, C3, etc.). Everything works the way I expect with the exception of the "media_player.next()" command.
Let's say you queue up 3 songs. If you hit the "y" key, it skips the song as I'd expect. My issue is that once it gets to the 3rd song, if you hit "y" again, it will circle back to the first song. I don't want that. I want the "y" key to take you forward in the media list...if that is the last song in the media list, don't go to the next song. How do I know if that's the last song in the media list or how do you stop VLC from going back to the beginning?
#!/usr/bin/env python3
#
import os, sys, csv, vlc, time, serial
from pynput.keyboard import Key, Listener
#
# Set Defaults
#
DefaultUSBPath="/media/pi"
#
# Declare variables
#
USBDrive = None
Action = None
Playlist = []
SelectionCount = []
Sel_char = None
#
# Find the USB Drive
#
USBDrive = os.path.join(DefaultUSBPath, "USB30FD")
#
# Adding to playlist - Returns directory contents and adds to playlist
#
def addplaylist(track):
list = None
if os.path.isdir(os.path.join(USBDrive, track)):
files = [f for f in os.listdir(os.path.join(USBDrive, track)) if os.path.isfile(os.path.join(USBDrive, track, f))]
for f in files:
if list is None:
list = os.path.join(USBDrive, track, f)
else:
list = list + ";" + os.path.join(USBDrive, track, f)
else:
print ("Error(3) - Selection is invalid")
if list is None:
print ("Error(4) - Selection has no media")
return list
#
# MediaPlayer function
#
def vlc_WhatsPlaying():
pass
def vlc_SongStarted(event):
print("Started")
song = media_player.get_media_player().get_media().get_mrl() # return path of current playing media
print(song)
splittrack = song.split("/")
track = splittrack[-2]
print(track)
return
def vlc_SongFinished(event):
print("Finished")
song = media_player.get_media_player().get_media().get_mrl() # return path of current playing media
print(song)
splittrack = song.split("/")
track = splittrack[-2]
#media_list.remove_index(0)
#media_player.play_item_at_index(1)
return
#
# Define keyboard actions
#
def on_press(key):
global Action, player
try:
Sel_char = int(key.char)
except:
try:
Sel_char = str(key.char)
Sel_char = Sel_char.upper()
except:
Sel_char = None
if Sel_char == "Z":
return False
elif Sel_char == "Y":
print("Skip")
media_player.next()
elif type(Sel_char) == str:
Action = Sel_char
elif type(Sel_char) == int:
Plist = None
Action = Action + str(Sel_char)
print("Action: " + Action)
Plist = addplaylist(Action)
if Plist is not None:
if ";" in Plist:
print(Plist)
Plist = Plist.split(";")
for p in Plist:
media_list.add_media(p)
else:
media_list.add_media(Plist)
# find section in array and increase the count by one
if not media_player.is_playing():
media_player.play()
else:
print ("Error(4) - Selection has no media")
else:
pass
#
# Setting Up Media Player
#
# creating Instance class object
player = vlc.Instance('--no-xlib --quiet ') # no-xlib for linux and quiet don't complain
media_player = vlc.MediaListPlayer() # creating a media player object
media_list = player.media_list_new() # creating a new media list
media_player.set_media_list(media_list) # setting media list to the media player
new = player.media_player_new() # new media player instance
media_player.set_media_player(new) # setting media player to it
media_events = new.event_manager() # setting event handler
# setting up events
media_events.event_attach(vlc.EventType.MediaPlayerMediaChanged, vlc_SongStarted)
media_events.event_attach(vlc.EventType.MediaPlayerEndReached, vlc_SongFinished)
# Read keyboard input
#
print("Ready...")
with Listener(on_press=on_press) as listener:
listener.join()
#
# Program is shutting down
#
print ("")
print ("Have a nice day!")
print ("")
sys.exit()
As mentioned in my comment the MediaListEndReached doesn't appear to do anything for me, so running with the idea of the list being the easiest way of addressing the issue, the following code tests the list position of the item being played and exits, if the next or previous command attempts to pass beyond the end of the list.
You can achieve the same result simply tracking an index variable.
You may have to adjust the splitting of the mrl to match the entries in your list.
import vlc
import time
## pinched from vlc for keyboard input
import termios
import tty
import sys
mymedia = ["vp.mp3","vp1.mp3","happy.mp3"]
def getch(): # getchar(), getc(stdin) #PYCHOK flake
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
return ch
## end pinched code
def jukebox():
player.play_item_at_index(0)
m = player.get_media_player()
print("Playing - ",m.get_media().get_mrl())
while True:
k = getch()
if k == "n": #Next
media = m.get_media()
if media.get_mrl().rsplit("/",1)[1] == mymedia[-1]: #Next requested but already at the end
break
player.next()
if k == "p": #Previous
media = m.get_media()
if media.get_mrl().rsplit("/",1)[1] == mymedia[0]: #Previous requested but already at the beginning
break
player.previous()
if k == " ": #Pause
player.pause()
if k == "q": #Quit
player.stop()
return True
time.sleep(0.1)
state = player.get_state()
print(state,m.get_media().get_mrl())
print("End of list")
vlc_instance = vlc.Instance('--no-xlib --quiet ') # no-xlib for linux and quiet don't complain
player = vlc_instance.media_list_player_new()
Media = vlc_instance.media_list_new(mymedia)
player.set_media_list(Media)
print("Welcome to Jukebox")
print("Options - space = Play/Pause, n = Next, p = Previous, q = Quit")
print("Media",mymedia)
jukebox()
I am trying to read some serial data from raspberry pi 3 using pyserial api, I need the data in a particular sequence e.g 3xxx7xxxBxxxExxx, however, sometimes the data stream starts from Exxx3xxx7xxxBxxx, how can I ensure that I always read the right sequence irrespective of how the data streams in.
This is for reading data from a control card used in a special pump application.
import serial
import time
ser = serial.Serial(
port = '/dev/ttyACM0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = seial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1
)
time.sleep = 1
try:
while 1:
if ser.inWaiting() > 0:
data = ser.read(8)
print(data.hex())
this gives me the result in 3xxx7xxxBxxxExxx sometimes and other times it starts from 7xxx or Exxx, however, I always want to be able to extract the sequence 3xxx7xxxBxxxExxx irrespective of where the stream starts from.
Assuming that the marker which you use to determine the start of the sequence is a full byte 0x30 you can try the following code. It will read one byte at a time until the start marker is found. Then it will read another 7 bytes and append them:
import serial
import time
ser = serial.Serial(
port = '/dev/ttyACM0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = seial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1
)
time.sleep = 1
start_marker = b'\xE0'
try:
while 1:
if ser.inWaiting() > 0:
data = ser.read(1)
if data != start_marker:
continue
data += ser.read(7)
print(data.hex())
EDIT
Try this code to match the most significant 4 bits of each bytes pair:
import serial
import time
ser = serial.Serial(
port = '/dev/ttyACM0',
baudrate = 9600,
parity = serial.PARITY_NONE,
stopbits = seial.STOPBITS_ONE,
bytesize = serial.EIGHTBITS,
timeout = 1
)
time.sleep = 1
data = bytes()
try:
while 1:
if ser.inWaiting() > 0:
data += ser.read(1)
if len(data) < 8:
continue
if len(data) > 8:
data = data[-8:]
if not (
data[0] >> 4 == 0x3 and
data[2] >> 4 == 0x7 and
data[4] >> 4 == 0xB and
data[6] >> 4 == 0xE
):
continue
print(data.hex())
Im trying to simulate two machines working, and failing at random times. When they fail they call assistance. These two machines is part of bigger system of different machines, which needs to know when its neighbor has failed to do its job.
So far, I have made the simulate of the two machines, but I cant figure out how to send messages to their neighbors without each machine needing to know the whole system?
This is what I have so far:
import simpy
import random
random_seed=42
MTTF = 3500
break_mean = 1 / MTTF
sim_time = 4 * 7*24*60 # 4 weeks 24/7
num_machines = 2
rep_time = 30
tpp = 20 #20 minutes to make each part
neighbour = 3 #How many should it send to?
#Creating a class called messaging which is an object.
class messaging(object):
#DEfing the initilizing function, and initilize self, Environment, and capacity which is set to infinity, by a simpy core-function.
def __init__(self, env, capacity=simpy.core.Infinity):
self.env = env
self.capacity = capacity
self.pipes = []
#Making a function which work on everything that is a part of the message. With name Put.
def put(self, value):
if not self.pipes: #How to get this error?
raise runtime_error('There are no output pipes.')
#Create a variable, events, store to it pipe values
events = broken_machine()
return self.env.all_of(events)
def get_output_conn(self):
#Set the capacity of pipe variable to store infinity.
pipe = simpy.Store(self.env, capacity=self.capacity)
#to each pipes, add(or append) pipe
self.pipes.append(pipe)
return pipe
def mesg_generator(number, env, out_pipe):
msg = ('Failed')
def message_reciever(name, env, in_pipe):
while True:
msg = yield in_pipe.get()
print("%s received message: %s" % (number, msg[1]))
def time_per_part():
return tpp
def ttf():
return random.expovariate(break_mean)
class Machine(object):
def __init__(self, env, number, repair):
#self.arg = arg
self.env = env
self.number = number
self.parts_made = 0
self.times_broken = 0
self.broken = False
self.process = env.process(self.working(repair))
env.process(self.broken_machine())
def working(self, repair):
while True:
work = time_per_part()
while work:
try:
begin = self.env.now
yield self.env.timeout(work)
work = 0
except simpy.Interrupt:
self.broken = True
work -= self.env.now - begin
with repair.request(priority = 1) as req:
yield req
yield self.env.timeout(rep_time)
self.times_broken +=1
yield message_reciever()
#print('Machine down')
self.broken = False #Machine fixed again
self.parts_made +=1
def broken_machine(self):
while True:
yield self.env.timeout(ttf())
if not self.broken:
self.process.interrupt()
def other_jobs(env, repair):
while True:
work = tpp
while work:
with repair.request(priority=2) as req:
yield req
try:
begin = env.now
yield env.timeout(work)
work = 0
except simpy.Interrupt:
work -= env.now - begin
print("This simulates machines 3 and 4 doing the same tasks.")
random.seed(random_seed)
env = simpy.Environment()
pipe = simpy.Store(env)
bc_pipe = messaging(env)
repair = simpy.PreemptiveResource(env, capacity = 1)
machines = [Machine(env, 'Machine %d' % i, repair)
for i in range(num_machines)]
env.process(other_jobs(env, repair))
env.run(until=sim_time)
#Show how many times each machine failed:
for machine in machines:
print("%s broke down %d times" %(machine.number, machine.times_broken))
I am trying to write a simple tool that measures the TCP port open, the code works well.
The issue I have is that when I compare the TCP ping result to other tools, such psping (Sysinternals), tcpping , check_tcp(Nagios), I get much lower results than my code.
In my code open TCP port open takes around 9~10ms, others tools takes 0.200~0.500ms
in the beginning, thought its related to the case if I have multiple interfaces on my computer, I added to bind to the correct interface and didn't change the results.
In addition, i found that the difference between python and other tools, I used Wireshark to capture both python and psping, and I found that
the final handshake from client side FIN, ACK is much slower in Python than psping and that is the difference the 10ms.
Is there any flag in Python TCP to make it faster?
My question is, why I get such different results?
Please advice
Thanks
as suggested post from babygame0ver solve the "latency" issue added threading and latency now much other tools
Thanks
#!/usr/bin/env python3
"""
TCP Ping Test (defaults to port 80, 10000 packets)
Usage: ./tcpping.py host [port] [maxCount]
- Ctrl-C Exits with Results
"""
import sys
import socket
import time
import signal
from timeit import default_timer as timer
import threading
host = None
port = 80
a = time.clock()
time.sleep(2)
b = time.clock()
print(b-a)
# Default to 10000 connections max
maxCount = 10000
count = 0
## Inputs
# Required Host
try:
host = sys.argv[1]
except IndexError:
print("Usage: tcpping.py host [port] [maxCount]")
sys.exit(1)
# Optional Port
try:
port = int(sys.argv[2])
except ValueError:
print("Error: Port Must be Integer:", sys.argv[3])
sys.exit(1)
except IndexError:
pass
# Optional maxCount
try:
maxCount = int(sys.argv[3])
except ValueError:
print("Error: Max Count Value Must be Integer", sys.argv[3])
sys.exit(1)
except IndexError:
pass
# Pass/Fail counters
passed = 0
failed = 0
def getResults():
""" Summarize Results """
lRate = 0
if failed != 0:
lRate = failed / (count) * 100
lRate = "%.2f" % lRate
print("\nTCP Ping Results: Connections (Total/Pass/Fail): [{:}/{:}/{:}] (Failed: {:}%)".format((count), passed, failed, str(lRate)))
def signal_handler(signal, frame):
""" Catch Ctrl-C and Exit """
getResults()
sys.exit(0)
# Register SIGINT Handler
signal.signal(signal.SIGINT, signal_handler)
# Loop while less than max count or until Ctrl-C caught
while count < maxCount:
# Increment Counter
count += 1
success = False
# New Socket
s = socket.socket(
socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.10.19', 0))
# 1sec Timeout
s.settimeout(1)
# Try to Connect
try:
# Start a timer
t = threading.Thread(target=s.connect((host, int(port))))
#threads.append(t)
s_start = timer()
t.start()
# Stop Timer
s_stop = timer()
s.shutdown(socket.SHUT_RD)
success = True
# Connection Timed Out
except socket.timeout:
print("Connection timed out!")
failed += 1
except OSError as e:
print("OS Error:", e)
failed += 1
# Stop Timer
#s_stop = timer()
s_runtime = "%.2f" % (1000 * (s_stop - s_start))
if success:
print("Connected to %s[%s]: tcp_seq=%s time=%s ms" % (host, port, (count-1), s_runtime))
passed += 1
# Sleep for 1sec
if count < maxCount:
time.sleep(1)
# Output Results if maxCount reached
getResults()
I am writing a small application to monitor some temperatures using a raspberry pi. I would like to be able to remotely start or restart the monitoring script remotely. I connect via SSH, cd to the .py file's directory, and then i "python temp_controller.py &". This gives me an error importing something. "from w1thermsensor import W1ThermSensor". This error does not occur when running the script from Thonny directly on the Pi.
"Main" file.
import Send_Email
import Temp_Sensor
import os
import glob
import math
import timefuncs
import apc_controls
program_start_time = timefuncs.get_time() #Used to determine how long the program has been running.
printable_start_time = timefuncs.get_printable_time()
filename = ("Temperature Data " + printable_start_time.strftime("%c") + ".txt")
state = 0 #Used to switch between activities and determine if there has been an error.
temps = [0,0,0,0,0,0,0,0],[0,0] #Holds temperature data
over_temp_counter = 0 #variable for tracking consecutive over temp values
newdir = os.getcwd() + "/temps files"; os.chdir(newdir) #Changes directory to storage location for temperature files
with open(filename, "w+") as tempsfile:
tempsfile.write("Long Term Temperature Monitor Project\r\n")
tempsfile.write("Date-Time,Sensor ID,Sensor Name,Temperature\r\n")
test = 0
while True:
if (math.floor(timefuncs.get_time())) % 30 == 0 and state == 0:
print("sample")
state = 1 #stops this from executing multiple times per second
length = Temp_Sensor.read_sensors(temps) #gets number of sensors and sensor data with IDs
#Writes data line to log file
now = timefuncs.get_printable_time()
tempsfile.write("%s"%now)
i = 0
while i < length:
print("Sensor %s has temperature %.2f" % (temps[i][0], temps[i][1]))
tempsfile.write(",%s"%temps[i][0])
tempsfile.write(",%s"%Temp_Sensor.get_sensor_name(temps[i][0]))
tempsfile.write(",%f"%temps[i][1])
i += 1
tempsfile.write("\r\n")
#Checks temperatures to see if over temp
i = 0
over = False
while i < length:
if Temp_Sensor.check_temp(temps[i][1]):#if over temp
over = True
if over_temp_counter > 1:#ensures there is not a single fluke reading that causes error
print("over temp")
tempsfile.close()#close log file
Send_Email.send_fail_email(filename)#send email with log file
apc_controls.turn_off_apc()#shut down power to test
tempsfile = open("(After error" + printable_start_time.strftime("%c") + ".txt", "w+")
else:
print("increment over")
over_temp_counter += 1
i+=1
if over == False:
over_temp_counter = 0
elif (math.floor(timefuncs.get_time())) % 30 != 0:#if not 30 second increment reset blocker used to prevent the 30 secodn operations from occuring more than once
state = 0
File with the error.
import time
import glob
from w1thermsensor import W1ThermSensor
def read_sensors(data):
i = 0
j = 0
for sensor in W1ThermSensor.get_available_sensors([W1ThermSensor.THERM_SENSOR_DS18B20]):
data[i][j] = sensor.id
j+=1
data[i][j] = sensor.get_temperature()
i+=1
j = 0
return i
def get_sensor_name(id):
if id == "000009ac911f":
return "Sensor 1"
elif id == "000009aecc36":
return "Sensor 2"
def check_temp(value):
if value > 80:
return 1
else:
return 0
I guess on your local machine you did something like pip install w1thermsensor, right? You need to install the w1thermsensor dependency on your Raspberry pi too