raspberry pi & gps python-mutithreading - python

I am developing GPS(global sat bu-353s4 USB-type) and raspberry pi 3b based project. In which I want to fetch GPS latitude and longitude data, according to that data I want to play some video files and also want to keep track of last played video name. all this process should be in while loop means in an infinite loop.
I have developed logic for that, the problem I am facing is that whenever video playback is complete it will again fetch GPS data and go to specific folder select video file and play video, in between two video playback the screen gets blank I want continuous video play. I am using OMXplayer to open video.I know it can be solved using the multitasking /multithreading concept but don't know how to implement it in Python.
this is my code :
# class to define background process thread
class Asyncfun(threading.Thread):
def __init__(self, text):
threading.Thread.__init__(self)
self.text = text
def run(self):
os.system(self.text)
print "play finished "
def Main():
try:
while True:
# get the GPS latitude longitude data using another gpsdatafetching file
stdn = gps2.latlong()
lat1 = round(float(stdn[0]),5)
long1 = round(float(stdn[1]),5)
ID = gps_geotest3.test1(lat1,long1)# get the areaid according to current latitudeand longitude
print "id is :", ID
if ID == None:
ID = 17
print "lat long is in this areaId : ",ID
location = '/home/pi/files/'
counter = 0 #keep a count of all files found
mp4files = [] #list to store all csv files found at location
lastplayedindex = 0
areaID = str(ID)
location += areaID
#print "file path is: ",location
for file in os.listdir(location):
if file.endswith(".mp4"):
#print "mp4 file found:\t", file
mp4files.append(str(file))
counter = counter+1
#get the lastplayedindex_aeraid file name
indexfilename='lastplayedindex_'
indexfilename +=areaID
indexfilename += '.txt'
#get the index number from lastplayedindex_aeraid file
with open(indexfilename,'rb') as input_file:
for line in input_file:
lastplayedindex = line
path = "/home/pi/files/"
omxcmd = "omxplayer --display=5 "
print "lastplayed index: ",lastplayedindex
if int(lastplayedindex)< (counter-1) : #compare with total filecount in folder
newlastindex=int(lastplayedindex)+1
vfile = mp4files[newlastindex] #videofile name
omxcmd += (location +'/') #append filelocation
omxcmd += vfile # append filename
#omxcmd is command to open videofile using OMXplayer
#play videofile iin backgroundprocess while sending acknowledgment to webserver about that file
background = Asyncfun(omxcmd)
background.start()
# code to update lastplayed index in local file
counter = 0
#to send acknowledgment to server about which video played last
print "sending acknowledgment to server.."
payload2 = {'DeviceMasterId': '30', 'Fk_Area_ID': areaID,'FileName':vfile}
R = requests.post('url to my website', params = payload2)
if R.status_code != 200:
print "Error:", R.status_code
else :
print "acknowledgment sent successfully."
background.join()
except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
gpsp.running = False
gpsp.join()
scope.__del__()
if __name__ == '__main__':
Main()

Related

Set variable to change on next line in given file during loop python

Here im workin on a script which will go through and analyze all given .mp3 files in a .txt document which will contain the full path to the files. Then it prints out the metadata along with the file path. This analyzing will run in a loop until all lines in the document have been read. I can do this individually if I manually specify the location of the file, but unable to do so when make the variable change per new line in the document when looped. I have tried putting all these functions under 1 large function and looping it but then I still get an undefined variable for "song". Do note: I am a complete noob at python and this is my first attempt at building this small project.
The goal: loop function that goes through every line of .txt and sets that line of text as the "song" variable for the destination that the analyzer function can then go read & print.
Here is the code which works when the file location is manually set:
song = "Z:/Vibe Playlists\Throwbacks\Taio Cruz - Hangover ft. Flo Rida.mp3"
audio1 = ID3(song) #artist,album,title,bpm,initial key,date,
audio2 = MP3(song) #length
audio3 = eyed3.load(song) #publisher
audio4 = mp3.Mp3AudioFile(song) #bitrate
###########################
#global variables for JSON#
###########################
artist = ""
title = ""
album = ""
genre = ""
bpm = ""
initial_key = ""
date = ""
length = ""
publisher = ""
bitrate = ""
song_location = song
###############################
def analyze_metadata():
try:
Artist = audio1['TPE1'].text[0]
# print("Artist:",Artist) #Artist
global artist
artist = Artist
except KeyError:
# print("no artist") - Debugging
pass
try:
Title =audio1['TIT2'].text[0]
global title
title = Title
# print("Title:",audio1['TIT2'].text[0]) #title
except KeyError:
# print("no title") - Debugging
pass
try:
Album = audio1['TALB'].text[0]
global album
album = Album
# print("Album:",audio1['TALB'].text[0]) #album
except KeyError:
# print("no album") - Debugging
pass
try:
Genre = audio3.tag.genre.name
global genre
genre = Genre
# print("Genre:",audio3.tag.genre.name) #genre
except AttributeError:
# print("no genre") - Debugging
pass
try:
Bpm = audio1['TBPM'].text[0]
global bpm
bpm = Bpm
# print("BPM:",audio1['TBPM'].text[0]) #bpm
except KeyError:
# print("no bpm") - Debugging
pass
try:
Initial_Key = audio1['TKEY'].text[0]
global initial_key
initial_key = Initial_Key
# print("Initial Key:",audio1['TKEY'].text[0]) #initial key
except KeyError:
# print("no key") - Debugging
pass
try:
Date = audio1['TDRC'].text[0]
global date
date = Date
# print("Date:",audio1['TDRC'].text[0]) #date/year
except KeyError:
# print("no date") - Debugging
pass
song_length = (audio2.info.length) #length
def convert(seconds):
return time.strftime("%M:%S", time.gmtime(song_length))
# print("Length",convert(song_length))
global length
length = time.strftime("%M:%S", time.gmtime(song_length))
Publisher = audio3.tag.publisher
# print("Publisher:",audio3.tag.publisher) #publisher
global publisher
publisher = Publisher
song_bitrate = str(audio4.info.bit_rate)
song_bitrate = re.sub('[^0-9]', '', song_bitrate)
# print("Bit rate:",song_bitrate, "kbps") #bitrate
global bitrate
bitrate = song_bitrate
#to call function u do this#
analyze_metadata()
#testing global variables for json
def Print_Metadata():
print("Artist:",artist)
print("Title:",title)
print("Album:",album)
print("Genre:",genre)
print("BPM:",bpm)
print("Initial Key:",initial_key)
print("Date:",date)
print("Length:",length)
print("Publisher:",publisher)
print("Bitrate:",bitrate)
print("Location:", song_location)
Print_Metadata()
This prints the metadata to shell, but when I try to run the same code within a while loop that changes the "song" variable to the location of the second line and then third and so on, I get an undefined error.
def make_filepath_variable():
filepath = 'py_test.txt'
with open(filepath) as fp:
line = fp.readline()
cnt = 1
while line:
#print("Line {}: {}".format(cnt, line.strip()))
line = fp.readline()
cnt += 1
global song
song = line
print(song)
make_filepath_variable()
when this code is run before all other functions, The rest of the above code cant grab the variable information. although from this code i can print every line of the text and go down one by one.
I've been going through forums for almost 2 days now trying to find a way to do this and i'm unable to find anything similar or usable that works in my situation.. Some insight or tips would be greatly appreciated, Thanks!

Python for/while loop

Today i am working on a project about incoming phone calls being transcripted and getting saved into text files, but i am also kinda new to python and python loops.
I want to loop over a SQL server column and let each row loop trough the azure Speech to text service i use (all of the phonecall OID's). I have been stuck on this problem for a couple days now so i thought i might find some help here.
import azure.cognitiveservices.speech as speechsdk
import time
from os import path
from pydub import AudioSegment
import requests
import hashlib
import sys
import os.path
import pyodbc
databaseName = '*'
username = '*'
password = '*'
server = '*'
driver = '*'
try:
CONNECTION_STRING = 'DRIVER='+driver+';SERVER='+server+';DATABASE='+databaseName+';UID='+username+';PWD='+ password
conn = pyodbc.connect(CONNECTION_STRING)
cursor = conn.cursor()
storedproc = "* = *'"
cursor.execute(storedproc)
row = cursor.fetchone()
while row:
array = [(int(row[1]))]
row = cursor.fetchone()
i = 0
while i<len(array):
OID = (array[i])
i = i + 1
print(OID)
string = f"{OID}*"
encoded = string.encode()
result = hashlib.sha256(encoded)
resultHash = (result.hexdigest())
Telefoongesprek = requests.get(f"*{OID}", headers={f"api-key":f"{resultHash}"})
with open("Telefoongesprek.mp3", "wb") as f:
f.write(Telefoongesprek.content)
src = "Telefoongesprek.mp3"
dst = "Telefoongesprek.wav"
sound = AudioSegment.from_file(src)
sound.export(dst, format="wav")
def speech_recognize_continuous_from_file():
speech_config = speechsdk.SpeechConfig(subscription="*", region="*")
speech_config.speech_recognition_language = "nl-NL"
audio_config = speechsdk.audio.AudioConfig(filename="Telefoongesprek.wav")
speech_recognizer = speechsdk.SpeechRecognizer(speech_config=speech_config, audio_config=audio_config)
done = False
def stop_cb(evt):
print('CLOSING on {}'.format(evt))
nonlocal done
done = True
all_results = []
def handle_final_result(evt):
all_results.append(evt.result.text)
speech_recognizer.recognized.connect(handle_final_result)
speech_recognizer.session_started.connect(handle_final_result)
speech_recognizer.session_stopped.connect(handle_final_result)
speech_recognizer.canceled.connect(handle_final_result)
speech_recognizer.session_stopped.connect(stop_cb)
speech_recognizer.canceled.connect(stop_cb)
speech_recognizer.start_continuous_recognition()
while not done:
time.sleep(.5)
speech_recognizer.stop_continuous_recognition()
print(all_results)
telefoongesprek = str(all_results)
filename = f"C:\\Users\\Beau\\Contact-verkeer\\contact-verkeer\\telefoon\\STT Transcriptions\\Telefoongesprek#{OID}.txt"
file = open(filename, "w")
file.write(telefoongesprek)
file.close()
speech_recognize_continuous_from_file()
cursor.close()
del cursor
conn.close()
except Exception as e:
print("Error: %s" % e)
everything works apart form each other but i just dont know how to place the loop and witch one i should use (For/While loop). right here im trying to loop over an array but i dont this this is correct.
Error message: Decoding failed. ffmpeg returned error code: 1
[mp3 # 000001cb8c57e0o0] Failed to read frame size: could not seek to 1073.
which i am pretty sure means that my azure function can't find an mp3 file, what means that the "Mp3 to Wav" convert doesn't work.
Thanks in advance!
If I understand your question, you have a database with lots of phone call details. One of the field value in each row is used to create the associated mp3 file. You want to do speech to text using azure on each of the mp3 file you have in your database.
So you can do it in two ways:
Iterate though all rows in the database and create all the associted files into a folder in the local disk with the OID as your filename.
Then write another loop to iterate through this folder and send the files for transcription to Azure Speech to Text service.
The other technique is to do everything in a single loop like the way you have shown which will require some corrections.
Ok, so now that part is clear, we can go into the speech to text part. So azure allow you to send the compressed format for transcription, which means you actually don't need to convert it into wav file.
Please have a look at the modified code below with the changes:
# code snippet borrowed from azure samples
def speech_recognize_continuous_from_file(filename):
class BinaryFileReaderCallback(speechsdk.audio.PullAudioInputStreamCallback):
def __init__(self, filename: str):
super().__init__()
self._file_h = open(filename, "rb")
def read(self, buffer: memoryview) -> int:
try:
size = buffer.nbytes
frames = self._file_h.read(size)
buffer[:len(frames)] = frames
return len(frames)
except Exception as ex:
print('Exception in `read`: {}'.format(ex))
raise
def close(self) -> None:
print('closing file')
try:
self._file_h.close()
except Exception as ex:
print('Exception in `close`: {}'.format(ex))
raise
# Creates an audio stream format. For an example we are using MP3 compressed file here
compressed_format = speechsdk.audio.AudioStreamFormat(compressed_stream_format=speechsdk.AudioStreamContainerFormat.MP3)
callback = BinaryFileReaderCallback(filename=filename)
stream = speechsdk.audio.PullAudioInputStream(stream_format=compressed_format, pull_stream_callback=callback)
speech_config = speechsdk.SpeechConfig(subscription="*", region="*")
speech_config.speech_recognition_language = "nl-NL"
audio_config = speechsdk.audio.AudioConfig(stream=stream)
# Creates a speech recognizer using a file as audio input, also specify the speech language
speech_recognizer = speechsdk.SpeechRecognizer(speech_config, audio_config)
done = False
def stop_cb(evt):
print('CLOSING on {}'.format(evt))
nonlocal done
done = True
all_results = []
def handle_final_result(evt):
all_results.append(evt.result.text)
speech_recognizer.recognized.connect(handle_final_result)
speech_recognizer.session_started.connect(handle_final_result)
speech_recognizer.session_stopped.connect(handle_final_result)
speech_recognizer.canceled.connect(handle_final_result)
speech_recognizer.session_stopped.connect(stop_cb)
speech_recognizer.canceled.connect(stop_cb)
speech_recognizer.start_continuous_recognition()
while not done:
time.sleep(.5)
speech_recognizer.stop_continuous_recognition()
print(all_results)
telefoongesprek = str(all_results)
filename = f"C:\\Users\\Beau\\Contact-verkeer\\contact-verkeer\\telefoon\\STT Transcriptions\\Telefoongesprek#{OID}.txt"
file = open(filename, "w")
file.write(telefoongesprek)
file.close()
try:
CONNECTION_STRING = 'DRIVER='+driver+';SERVER='+server+';DATABASE='+databaseName+';UID='+username+';PWD='+ password
conn = pyodbc.connect(CONNECTION_STRING)
cursor = conn.cursor()
storedproc = "* = *'"
cursor.execute(storedproc)
row = cursor.fetchone()
# loop through the rows
while row:
array = [(int(row[1]))]
i = 0
while i<len(array):
OID = (array[i])
i = i + 1
print(OID)
string = f"{OID}*"
encoded = string.encode()
result = hashlib.sha256(encoded)
resultHash = (result.hexdigest())
telefoongesprek_response = requests.get(f"*{OID}", headers={f"api-key":f"{resultHash}"})
# save the file to local disk as mp3
with open("Telefoongesprek.mp3", "wb") as f:
f.write(telefoongesprek_response.content)
# do the speech to text on the mp3 file
speech_recognize_continuous_from_file(f.name)
# fetch the next row
row = cursor.fetchone()
cursor.close()
del cursor
conn.close()
except Exception as e:
print("Error: %s" % e)
I haven't tested this full code as i don't have the db connections with me. Please fell free to modify for your use case and let me know if you have any issues.

Python writing twice but randomly?

So I am currently working on a program that was handed down to me from a previous coworker and I am working through a strange bug. When reading data output from 2 separate serial sources byte by byte, python will write to the same cell in the .csv file as well as the console.
import serial
from datetime import datetime
import os
pressure_passed = False
arduino_passed = False
file_passed = False
BAUD_RATE = 115200
GARBAGE_CYCLES = 3 # how many cycles to ignore before logging data
garbage_cycle = 0
# Save data to log file
def LogData(startTime, pressureData, arduinoData, file):
global garbage_cycle
if garbage_cycle < GARBAGE_CYCLES:
garbage_cycle += 1
else:
delta = datetime.now() - startTime
ms = delta.total_seconds() * 1000
dataString = "{:0.2f}, {}, {}\n".format(ms, pressureData, arduinoData)
file.write(dataString)
file.flush()
print(dataString, end = "")
# Get the COM port for the Mark-10 Series 5
while not pressure_passed:
try:
pressure_com = input("Enter Mark-10 Series 5 COM Port #: ")
pressure_ser = serial.Serial("COM" + str(pressure_com), BAUD_RATE)
pressure_passed = True
except:
print("Invalid COM Port, please enter a valid port.\n-----")
# Get the COM port for the Arduino
while not arduino_passed:
try:
arduino_com = input("Enter Ardunio COM Port #: ")
arduino_ser = serial.Serial("COM" + str(arduino_com), BAUD_RATE)
arduino_passed = True
except:
print("Invalid COM Port, please enter a valid port.\n-----")
# Get the name for the log file
while not file_passed:
try:
file_name = input("Enter log file name: ")
# Add extension if not already given
if "." not in file_name:
file_name += ".csv"
log_file = open(file_name, "a")
# Add header row to log file
if os.stat(log_file.name).st_size == 0:
log_file.write("time (ms), pressure, rate (deg/ms)")
file_passed = True
except:
print("Invalid file, or could not open the file specified.\n-----")
start = datetime.now()
# Variables to read serial input
pressure_data = ""
last_pressure = ""
arduino_data = ""
last_arduino = ""
# Main program loop
# Serial is read from byte by byte to better sync the two devices
while True:
try:
x_changed = False
y_changed = False
# Read from Mark-10 serial if available
# x is a byte read from the serial line, converted to ascii
if pressure_ser.in_waiting > 0:
x = pressure_ser.read().decode('ascii')
x_changed = True
# Read from Arduino serial if available
# y is a byte read from the serial line, converted to ascii
if arduino_ser.in_waiting > 0:
y = arduino_ser.read().decode('ascii')
y_changed = True
# If new data received, check if we should log it
if x_changed:
if x == '\n': # New line detected, log the accumulated data
if last_pressure != pressure_data:
LogData(start, last_pressure, last_arduino, log_file)
last_pressure = pressure_data
pressure_data = ""
elif x != '\r': # Otherwise, add the read character to the string
pressure_data += x
if y_changed:
if y == '\n': # New line detected, log the accumulated data
if last_arduino != arduino_data:
LogData(start, last_pressure, last_arduino, log_file)
last_arduino = arduino_data
arduino_data = ""
elif y != '\r': # Otherwise, add the read character to the string
arduino_data += y
except Exception as e:
print(e)
if arduino_ser.isOpen():
arduino_ser.close()
if pressure_ser.isOpen():
pressure_ser.close()
log_file.close()
break
Here is what the file is spitting out, IE the double printing to a single cell. Sample of the data
Any advice is much appreciated, thank you all!
It looks like when a new pressure is read in, but the value has not changed from last time, then it's not resetting the string that's accumulating all the characters and it doubles up. Then on the next pass, when the REAL pressure hasn't changed, it compares the doubled to the non-doubled and writes again, and vice-versa.
Try unindenting the line that resets the string to remove it from the if clause:
# If new data received, check if we should log it
if x_changed:
if x == '\n': # New line detected, log the accumulated data
if last_pressure != pressure_data:
LogData(start, last_pressure, last_arduino, log_file)
last_pressure = pressure_data
pressure_data = ""
elif x != '\r': # Otherwise, add the read character to the string
pressure_data += x
Then the same thing for the arduino value block.
Your logs will probably be much shorter now.
I like your username! My guess is that it is reading from the serial too quickly and going through the loop twice before the arduino has time to change the value of in_waiting.
At the top of your code add:
import time
And in the LogData function add:
time.sleep(0.1)
Give that a shot and let me know if it helps. 0.1s may be too long for your application but it is a good test to see if this is the issue. If it is, you can play around with the amount of time it sleeps.
Based on the sample output provided, I think it's not writing twice but rather the following specific condition is met occasionally which calls two identical LogData() lines.
Only when Condition 1 AND Condition 2 are met - the data is written "twice". Note that the LogData() call is same in both conditions.
Condition 1:
# If new data received, check if we should log it
if x_changed:
if x == '\n': # New line detected, log the accumulated data
if last_pressure != pressure_data:
LogData(start, last_pressure, last_arduino, log_file)
Condition 2:
if y_changed:
if y == '\n': # New line detected, log the accumulated data
if last_arduino != arduino_data:
LogData(start, last_pressure, last_arduino, log_file)

Trying to understand a snippet

I'm trying to understand the following IF statement and what res does.
if sentence is not None:
# gps successfully parsed a message from module
# see if we have valid coordinates
res = check_for_valid_coordinates(gps)
Given below is the full code. Does it just run the function?
GPS_TIMEOUT_SECS=10
# init I2C to P21/P22
i2c = machine.I2C(0, mode=I2C.MASTER, pins=('P22', 'P21'))
# write to address of GPS
GPS_I2CADDR = const(0x10)
raw = bytearray(1)
i2c.writeto(GPS_I2CADDR, raw)
# create MicropyGPS instance
gps = MicropyGPS()
# store results here.
last_data = {}
print("Start reading GPS data...")
def check_for_valid_coordinates(gps):
if gps.satellite_data_updated() and gps.valid:
last_data['date'] = gps.date_string("long")
last_data['latitude'] = gps.latitude_string()
last_data['longitude'] = gps.longitude_string()
while True:
# read some data from module via I2C
raw = i2c.readfrom(GPS_I2CADDR, 16)
# feed into gps object
for b in raw:
sentence = gps.update(chr(b))
if sentence is not None:
# gps successfully parsed a message from module
# see if we have valid coordinates
res = check_for_valid_coordinates(gps)
print("Finished.")
if 'date' in last_data:
print("# ", last_data['date'])
if 'latitude' in last_data and 'longitude' in last_data:
print("> ", last_data['latitude'], " ", last_data['longitude'])
i2c.deinit()
Any help is appreciated. Thanks.

Dronekit Python didn't go to specific location

I have problem about Dronekit on Python
My project about receive GPS Location from Android application
and Launch drone flying to that Position, Everything work fine but problem is Drone can takeoff but drone didn't go to that Location(Testing 10+ times work only 1 time)
Here is my code (I think problem is GlobalRelative)
# Import DroneKit-Python
from dronekit import connect, VehicleMode, LocationGlobalRelative
import time
import urllib2
import simplejson
import json
import requests
#Wait for json data
response = urllib2.urlopen("http://localhost:3000/posts")
data = simplejson.load(response)
print(data)
json_string = data[0]["Information"]
gps = json.loads(json_string)
x=gps['lat']
y=gps['lon']
r = requests.delete('http://localhost:3000/posts/1')
# Connect to the Vehicle.
print("Connecting")
vehicle = connect('com4', wait_ready=False, baud=57600)#; vehicle.wait_ready(True, timeout=300)
print("Connected")
# Get some vehicle attributes (state)
print "Get some vehicle attribute values:"
print " GPS: %s" % vehicle.gps_0
print " Battery: %s" % vehicle.battery
print " Last Heartbeat: %s" % vehicle.last_heartbeat
print " Is Armable?: %s" % vehicle.is_armable
print " System status: %s" % vehicle.system_status.state
print " Mode: %s" % vehicle.mode.name # settable
# Takeoff Function
def arm_and_takeoff(tgt_altitude):
print("Arming motors")
# while not vehicle.is_armable:
# time.sleep(1)
vehicle.mode = VehicleMode("GUIDED")
vehicle.armed = True
print("Takeoff")
vehicle.simple_takeoff(tgt_altitude)
# wait reach tgt_altitude
while True:
altitude = vehicle.location.global_relative_frame.alt
if altitude >= tgt_altitude -1:
print("Altitude Reached")
break
time.sleep(1)
# Main
arm_and_takeoff(10)
# Speed
vehicle.airspeed = 7
# Go to wp
wp1 = LocationGlobalRelative(x, y, 10)
# Close vehicle object before exiting script
vehicle.mode = VehicleMode("RTL")
vehicle.close()
print("Completed")
Alternative, If I can't fix this problem I want to use MissionPlanner( I test on it , and it work) But I want to wait for GPS Location from Phone, and Launch the mission( every thing must automatic ) I have no idea how to bypass MissionPlanner
The line: wp1 = LocationGlobalRelative(x, y, 10) only assign wp1 variable with a location coordinate. You can use vehicle.simple_goto(wp1). simple_goto is a built in function in dronekit to command the vehicle to specific coordinate you can read more about it here http://python.dronekit.io/automodule.html?highlight=simple_goto#dronekit.Vehicle.simple_goto

Categories

Resources