Get a new unix timestamp when writing to a file - python-3.x

First post so apologies for any formatting issues ect.
Context - Using a PIR sensor to log visits to a store using a Pi-3.
My aim here is to write a new unix timestamp to a file every time the sensor detects motion.
Below is what code i have so far, this outputs a text file with a unix timestamp. but the stamp appears to be the same for every detection
GPIO.setmode(GPIO.BOARD)
GPIO_PIR = 11
print "PIR Module Test (CTRL-C to exit)"
GPIO.setup(GPIO_PIR,GPIO.IN)
Current_State = 0
Previous_State = 0
Variable= int(time.time())
try:
print "Waiting for PIR to settle ..."
while GPIO.input(GPIO_PIR)==1:
Current_State = 0
print " Ready"
while True :
Current_State = GPIO.input(GPIO_PIR)
if Current_State==1 and Previous_State==0:
print "Motion detected"
Previous_State=1
file = open("textFile.txt", 'a+')
file.write(Variable + "\n")
file.close()
elif Current_State==0 and Previous_State==1:
print " Ready"
Previous_State=0
time.sleep(0.01)
except KeyboardInterrupt:
print " Quit"

Related

How can I print else or if statement only once when the condition is meet instead of infinite without breaking

In the below python code I am checking if google is up when it is up its printing "google.com is up" infinite amount of times,
I want to print just once and wait until it'll go down and when google goes down I want to print "google.com is down" just once and again when google goes up print "google.com is up" like wise continue the loop without breaking.
hostname = "google.com" #example
while True :
response = os.system("ping -c 1 " + hostname + "> /dev/null")
#and then check the response...
if response == 0:
print (hostname, 'is up!')
else :
print (hostname, 'is down!')
You can add variable for checking last value. E.g. if response is 0, setting variable value and print. If response value doesn't change, not print and change variable value
Something like that:
hostname = "google.com" #example
state = -1
while True :
response = os.system("ping -c 1 " + hostname + "> /dev/null")
if response == 0 and state != 0:
print(hostname, 'is up!')
state = 0
else:
if state != 1:
print (hostname, 'is down!')
state = 1
I'm not sure what is True, but if you are in a loop, and want to do something only the first time it's triggered, and not subsequent times, then you would need to flag the first time vs. subsequent times. E.g., before the while statement, initialize two variables, e.g., first.true = 1 and first.false = 1. Inside the if statement, only print if first.true = 1, and after that (but still inside the if statement), set it to 0. This ensures that it will only print the first time it gets there. And likewise with first.false inside the else statement.
You can add a break statement to exit while loop, for example like that:
hostname = "google.com" #example
while True :
response = os.system("ping -c 1 " + hostname + "> /dev/null")
#and then check the response...
if response == 0:
print (hostname, 'is up!')
break
else :
print (hostname, 'is down!')
break
However, i am not understanding your question so good, using a state variable like in the other answer should be ok too!!
You can create an update function with a static last_update string. The update function will not print the same output twice.
def update(st):
if not hasattr(update, "last_update"):
update.last_update = ""
if update.last_update != st:
print(st)
update.last_update = st
while True:
hostname = "www.google.com"
response = os.system("ping " + hostname)
# and then check the response...
if response == 0:
update(f"{hostname} 'is up!")
else:
update(f"{hostname} 'is down!")
In the below code its continuously pinging my home server printing 'down' only onetime when its down and waiting, When the server is up printing 'up' only onetime then again when the server goes down it'll print (down) only onetime.
hostname = "172.16.0.96" #example
while True :
while True :
response = os.system("ping -c 1 " + hostname + "> /dev/null")
if response != 0:
print("down")
break
while True :
response = os.system("ping -c 1 " + hostname + "> /dev/null")
if response == 0:
print("up")
break

How to reset QFile/ QTextStream?

I am getting a file to be reset after a first read. All googling hasn't helped at all.
How do I reset a file to it's begin after it has been read a first time?
Trial one:
inFile = QFile( self._pathFileName )
inFile.open(QFile.ReadOnly | QFile.Text)
stream = QTextStream(inFile)
# Count first all lines in the file
self._numLinesRead = 0
self._mumLinesTotal = 0
while not stream.atEnd():
self._mumLinesTotal=+1
stream.readLine();
inFile.seek(0)
stream.seek(0)
pos = stream.pos() # pos is equal to 0 after this line verified with debugging
while( not stream.atEnd() ): # but here it still thinks he's at file end and jumps over
....
Trial two:
inFile = QFile( self._pathFileName )
inFile.open(QFile.ReadOnly | QFile.Text)
stream = QTextStream(inFile)
# Count first all lines in the file
self._numLinesRead = 0
self._mumLinesTotal = 0
while not stream.atEnd():
self._mumLinesTotal=+1
stream.readLine();
inFile.close()
del inFile
del stream
inFile = QFile( self._pathFileName )
inFile.open(QFile.ReadOnly | QFile.Text)
stream = QTextStream(inFile)
# everyting has been reset?!
while( not stream.atEnd() ): # Nop it still thinks it is atEnd and jumps over
....
I tried all the solutions found in the net. Nothing helps. What I'm doing wrong?
Not sure what I should say, but after a complete reboot of the system "Trial two" worked.
After a second reboot (two days and a lot of code changes later) also "Trial one" came to life.
After all: both trials are from my point of view valid and working.
If in case you discover strange behaviour during development and debugging try a reboot.

How to pick out the second to last line from a telnet command

like the many other threads I've opened, I am trying to create a multi-feature instant replay system utilizing the blackmagic hyperdeck which operates over Telnet. The current feature I am trying to implement is an in-out replay which requires storing two timecode variables in the format of hh:mm:ss;ff where h=hours, m=minutes, s=seconds, and f=frames #30fps. the telnet command for this is transport info, and the response returns 9 lines of which I only want the timecode from the 7th. Any idea on how to do this, as it is way out of my league?
status: stopped
speed: 0
slot id: 1
clip id: 1
single clip: false
display timecode: 00:00:09;22
timecode: 00:00:09;22
video format: 1080i5994
loop: false
Here's ideally what I would like it to look like
import telnetlib
host = "192.168.1.13" #changes for each device
port = 9993 #specific for hyperdecks
timeout = 10
session = telnetlib.Telnet(host, port, timeout)
def In():
session.write(b"transport info \n")
line = session.read_until(b";00",.5)
print(line)
#code to take response and store given line as variable IOin
def out():
session.write(b"transport info \n")
line = session.read_until(b";00",.5)
print(line)
#code to take response and store given line as variable IOout
def IOplay():
IOtc = "playrange set: in: " + str(IOin) + " out: " + str(IOout) + " \n"
session.write( IOtc.encode() )
speed = "play: speed: " + str(Pspeed.get() ) + "\n"
session.write(speed.encode() )
For the most part here's what I got to at least partially work
TCi = 1
TCo = 1
def In():
global TCi
session.write(b"transport info \n")
by = session.read_until(b";00",.5)
print(by)
s = by.find(b"00:")
TCi = by[s:s+11]
def Out():
global TCo
session.write(b"transport info \n")
by = session.read_until(b";00",.5)
print(by)
s = by.find(b"00:")
TCo = by[s:s+11]
def IOplay():
IOtc = "playrange set: in: " + str(TCi) + " out: " + str(TCo) + " \n"
print(IOtc.encode() )
session.write(IOtc.encode() )
speed = "play: speed: 2 \n"
session.write(speed.encode() )
except that its encoding as
b"playrange set: in: b'00:00:01;11' out: b'00:00:03;10' \n"
rather than
"playrange set: in: 00:00:01;11 out: 00:00:03;10 \n"
I need to get rid of the apostrophe's and b prefix in front of the variables
Any ideas?
def get_timecode(text):
tc = ''
lines = text.split('\r\n')
for line in lines:
var, val = line.split(': ', maxsplit=1)
if var == 'timecode':
tc = val
return tc
You could choose to go directly to lines[6], without scanning,
but that would be more fragile if client got out of sync with server,
or if server's output formatting changed in a later release.
EDIT:
You wrote:
session.write(b"transport info \n")
#code to take response and store given line as variable IOin
You don't appear to be reading anything from the session.
I don't use telnetlib, but the docs suggest you'll
never obtain those nine lines of text if you don't do something like:
expect = b"foo" # some prompt string returned by server that you never described in your question
session.write(b"transport info\n")
bytes = session.read_until(expect, timeout)
text = bytes.decode()
print(text)
print('Timecode is', get_timecode(text))

Exiting Python While True loop

I am using a temperature sensor (HS18B20) on my raspberry pi. Every second or so, temperature is recorded onto a spreadsheet and sent to dropbox using a while True loop. It will do this forever until ctrl + c is pressed. In order to upload to dropbox, I cannot have the same file name as another file. The program will give an error and stop. Obviously, I could simply create a file with a different name everytime but to combat having hundreds of different files on dropbox, I delete the file on dropbox and immediately upload the new spreadsheet to dropbox. I have no problem with this technique, except for one thing...
If the program is stopped via ctrl + c right after the file is deleted and during the uploading of the file, the new file doesn't get uploaded and only gets deleted on dropbox (the local .xls file is never deleted; just replaced).
toc = time.strftime("%b %-d, %Y. %H:%M:%S")
dbx.files_delete('/Temperature Data ' + toc + '.xls')
with open(time.strftime("%m_%d_%Y") + '.xls', "rb") as f:
dbx.files_upload(f.read(), '/Temperature Data ' + toc + '.xls')
print("Uploaded to Dropbox")
I thought I set up a fail safe, but it still does not work.
Here is a snippet from my code.
def signal_handler(signal, frame):
signal interrupted
interrupted = True
signal.signal(signal.SIGINT, signal_handler)
interrupted = False
...
while True:
print("Temperature Taken")
a += 1
c += 1
if temp_f < input_bad:
ws.write(a,0,temp_f)
ws.write(a,1,time.strftime("%H:%M:%S %p"))
ws.write(a,2,"YES")
while c % 6 == 0:
c += 1
dbx.files_delete('/Temperature Data ' + toc + '.xls')
with open(time.strftime("%m_%d_%Y") + '.xls', "rb") as f:
dbx.files_upload(f.read(), '/Temperature Data ' + toc + '.xls')
print("Uploaded to Dropbox")
if interrupted:
print("Saving...")
dbx.files_delete('/Temperature Data ' + toc + '.xls')
with open(time.strftime("%m_%d_%Y") + '.xls',"rb") as f:
dbx.files_upload(f.read(), '/Temperature Data ' + toc + '.xls')
quit()
If I ctrl + c the program while it's taking a temperature readings, no problem! The program finishes its loop until c % 6 == 0 and then saves and closes.
If I ctrl + c the program while its saving, yes problem...
I could just print("Do not close the program") when its saving, but I would like to make this idiot proof.
Any tips? Thanks!
You can register a signal handler and the quit the loop when at the end of processing.
import signal
import sys
userQuitRequested = False
def signal_handler(signal, frame):
print('You pressed Ctrl+C!')
userQuitRequested = True
signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C to quit')
You can then check for userQuitRequested in your loop at the appropriate time, and break if True.

Python3 Two-Way Serial Communication: Reading In Data

I am trying to establish a two-way communication via Python3. There is a laser range finder plugged into one of my USB ports and I'd like to send/receive commands to that. I have a sheet of commands which can be sent and what they would return, so this part is already there.
What I need is a convenient way to do it in real-time. So far I have the following code:
import serial, time
SERIALPORT = "/dev/ttyUSB0"
BAUDRATE = 115200
ser = serial.Serial(SERIALPORT, BAUDRATE)
ser.bytesize = serial.EIGHTBITS #number of bits per bytes
ser.parity = serial.PARITY_NONE #set parity check: no parity
ser.stopbits = serial.STOPBITS_ONE #number of stop bits
ser.timeout = None #block read
ser.xonxoff = False #disable software flow control
ser.rtscts = False #disable hardware (RTS/CTS) flow control
ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
ser.writeTimeout = 0 #timeout for write
print ("Starting Up Serial Monitor")
try:
ser.open()
except Exception as e:
print ("Exception: Opening serial port: " + str(e))
if ser.isOpen():
try:
ser.flushInput()
ser.flushOutput()
ser.write("1\r\n".encode('ascii'))
print("write data: 1")
time.sleep(0.5)
numberOfLine = 0
while True:
response = ser.readline().decode('ascii')
print("read data: " + response)
numberOfLine = numberOfLine + 1
if (numberOfLine >= 5):
break
ser.close()
except Exception as e:
print ("Error communicating...: " + str(e))
else:
print ("Cannot open serial port.")
So in the above code I am sending "1" which should trigger "getDistance()" function of the laser finder and return the distance in mm. I tried this on Putty and it works, returns distances up to 4 digits. However, when I launch the above Python script, my output is only the following:
Starting Up Serial Monitor
Exception: Opening serial port: Port is already open.
write data: 1
read data:
and it goes forever. There is no read data or whatsoever.
Where am I mistaken?
Apparently much more simpler version of the code solved the issue.
import serial
import time
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout = 1) # ttyACM1 for Arduino board
readOut = 0 #chars waiting from laser range finder
print ("Starting up")
connected = False
commandToSend = 1 # get the distance in mm
while True:
print ("Writing: ", commandToSend)
ser.write(str(commandToSend).encode())
time.sleep(1)
while True:
try:
print ("Attempt to Read")
readOut = ser.readline().decode('ascii')
time.sleep(1)
print ("Reading: ", readOut)
break
except:
pass
print ("Restart")
ser.flush() #flush the buffer
Output, as desired:
Writing: 1
Attempt to Read
Reading: 20
Restart
Writing: 1
Attempt to Read
Reading: 22
Restart
Writing: 1
Attempt to Read
Reading: 24
Restart
Writing: 1
Attempt to Read
Reading: 22
Restart
Writing: 1
Attempt to Read
Reading: 26
Restart
Writing: 1
Attempt to Read
Reading: 35
Restart
Writing: 1
Attempt to Read
Reading: 36
It seems to me that your ser.timeout = None may be causing a problem here. The first cycle of your while loop seems to go through fine, but your program hangs when it tries ser.readline() for the second time.
There are a few ways to solve this. My preferred way would be to specify a non-None timeout, perhaps of one second. This would allow ser.readline() to return a value even when the device does not send an endline character.
Another way would be to change your ser.readline() to be something like ser.read(ser.in_waiting) or ser.read(ser.inWaiting()) in order to return all of the characters available in the buffer.
try this code
try:
ser = serial.Serial("/dev/ttyS0", 9600) #for COM3
ser_bytes = ser.readline()
time.sleep(1)
inp = ser_bytes.decode('utf-8')
print (inp)
except:
pass

Resources