Only write when serial device outputs data - python-3.x

I am trying to make a data-logger than writes the output from a serial device that only outputs once per minute. I need it to have a time stamp on the output. The code I have so far will log the output but it keeps logging blanks with a timestamp in-between the device's output. How do I get it to only write a line with the timestamp when the device has output?
#!/usr/bin/env python
Log data from serial port
import argparse
import serial
import datetime
import time
import os
timestr = time.strftime("%Y%m%d")
Tstamp = time.strftime("%Y/%m/%d %H:%M ")
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-d", "--device", help="device to read from", default="/dev/ttyUSB0")
parser.add_argument("-s", "--speed", help="speed in bps", default=9600, type=int)
args = parser.parse_args()
outputFilePath = os.path.join(os.path.dirname(__file__),
datetime.datetime.now().strftime("%Y-%m-%d") + ".csv")
with serial.Serial(args.device, args.speed) as ser, open(outputFilePath,'w') as outputFile:
print("Logging started. Ctrl-C to stop.")
try:
while True:
time.sleep(1)
x = (ser.read(ser.inWaiting()))
data = x.decode('UTF-8')
outputFile.write(Tstamp + " " + data + '\n')
outputFile.flush()
except KeyboardInterrupt:
print("Logging stopped")
Sorry for the poor formatting I am not sure how to make it look right on here.

By adding if x!= "" and indenting properly I got it to work. Now I just need ot fix it to append the file and not overwrite it.
#!/usr/bin/env python
# Log data from serial port
import argparse
import serial
import datetime
import time
import os
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("-d", "--device", help="device to read from", default="/dev/ttyUSB0")
parser.add_argument("-s", "--speed", help="speed in bps", default=9600, type=int)
args = parser.parse_args()
outputFilePath = os.path.join(os.path.dirname(__file__),
datetime.datetime.now().strftime("%Y-%m-%d") + ".csv")
with serial.Serial(args.device, args.speed) as ser, open(outputFilePath,'w') as outputFile:
print("Logging started. Ctrl-C to stop.")
try:
while True:
time.sleep(1)
x = (ser.read(ser.inWaiting()))
data = x.decode('UTF-8')
if data !="":
outputFile.write(time.strftime("%Y/%m/%d %H:%M ") + " " + data )
outputFile.flush()
except KeyboardInterrupt:
print("Logging stopped")

Related

Stock price logging function

I have this function where the price of a stock gets logged in real time every 2 seconds and save it into a csv file however I cant see anything in the csv when I open it. What am I missing from the script?
import pandas as pd
import time
import urllib
import sys
import fix_yahoo_finance as yf
def stocks():
# Enter stock symbol
stock = input("Enter stock: ")
# Name CSV file
csvy= str(stock) + time.strftime('.%A.%d.%b.%Y').replace(' ', '') + ".csv"
csvy = csvy.replace(':' , '')
with open(csvy, 'w') as f:
sys.stdout = f
while 1 > 0:
print(yf.get_live_price(stock))
time.sleep(2)
stocks()
You wrote:
print(yf.get_live_price(stock))
You want to additionally flush the buffer so your new text is immediately visible:
print(yf.get_live_price(stock), flush=True)
Alternatively, consider assigning the live price to a temp variable,
and then outputting it twice, with print() and f.write(),
rather than assigning a new value to stdout.
Then you'd be able to flush them independently according to your need,
f.flush() or sys.stdout.flush().

Check BGP status

I recently had an interview and was asked to write a code that logs into 3 routers and reloads each, one at a time - checks that BGP is established and the interfaces are up before moving to reload the next device. We have been provided an imported module that can SSH into the router and reload it. Thoughts anyone? I'm new to Python
Though a module was provided for SSH, I started by coding it out and here is what I tired; just to give an idea of how the router works and what I am checking for:
import socket
import paramiko
def run_ssh_command(username, password, host, command):
"""
Using paramiko to SSH into remote locations and run commands
"""
port = 22
s = paramiko.SSHClient()
s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
s.connect(host, port, username, password, look_for_keys=False, timeout=5.0)
except paramiko.AuthenticationException as e:
print("authentication failed: ", e)
s.close()
return
except socket.timeout as e:
print("socket timeout: ", e)
s.close()
return
except paramiko.SSHException as e:
print("SSH Exception: ", e)
s.close()
return
except socket.error as e:
print("socket error: ", e)
s.close()
return
(stdin, stdout, stderr) = s.exec_command(command)
print ("ran command ", command)
# for line in stdout.readlines():
# print(line)
s.close()
if __name__ == "__main__":
while True:
run_ssh_command("CompRouter", "backbonedevice", "10.10.10.25", "show ip bgp summary")
So my line of thought is to SSH to the device, issue a "show ip bgp summary" command - this is what the table typically looks like:
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down Statd
10.10.10.2 4 65536 7 7 1 0 0 00:03:04 0
The idea is to check that the InQ/OutQ values are zero or non of the BGP neighbor are "Down", then and only then do I move to reload the next router.
This is particularly where I am stuck. Given a table like this, how to I check the entire InQ/OutQ column (there might be more than one neighbor) and then take the necessary action?
Opted to use napalm and netmiko - works like a charm:
from simplecrypt import encrypt, decrypt
from pprint import pprint
from netmiko import ConnectHandler
from napalm import get_network_driver
import json
#from time import time
import time
def read_device_data(devices_filename):
devices = {} #Create a dictionary for each IP's unique info
with open(devices_filename) as device_info:
for lines in device_info:
this_dev = lines.strip().split(',')
dev = {'ipaddr': this_dev[0],
'type': this_dev[1],
'name': this_dev[2]}
devices[dev['ipaddr']] = dev
print('Displaying info for all devices below: ')
pprint(devices)
return devices
#Create a function to decrypt and read file containing credentials encrypted in the format ip,username,password
def read_device_creds(device_cred_filename, key):
print('\n Decoding encrypted device credentials....')
with open(device_cred_filename, 'rb') as device_creds_file:
device_creds_decry = decrypt(key, device_creds_file.read())
device_creds_list = json.loads(device_creds_decry.decode('utf-8'))
pprint(device_creds_list)
print('\n Displaying device credentials in dictionary format:')
"""
Convert device_creds_list to dictionary using list comprehension
"""
device_creds_dict = {this_dev[0]: this_dev for this_dev in device_creds_list}
print(device_creds_dict)
return device_creds_dict
def check_BGP(net_device, cred):
print(f"Connecting to {net_device['ipaddr']} right now to check BGP status.....")
while True:
try:
driver = get_network_driver('ios')
iosv = driver(net_device['ipaddr'], cred[1], cred[2])
iosv.open()
except:
print('Waiting to establish a socket...')
else:
time.sleep(30)
ios_output = iosv.get_bgp_neighbors()
for k,v in ios_output.items():
for y in v.values():
if type(y) == dict:
for z in y.values():
print(f"BGP peer is up? {z['is_up']}")
return z['is_up'] == True
def reload(creds):
iosv_device = {
'device_type': 'cisco_ios',
'ip': creds[0],
'username': creds[1],
'password': creds[2]
}
net_connect = ConnectHandler(**iosv_device)
output = net_connect.send_command_timing('wr mem')
time.sleep(10)
output += net_connect.send_command_timing('reload')
output += net_connect.send_command_timing('y')
print(output)
def is_alive(alive_dev, alive_cred): #check if device is back online after reload
while True:
try:
driver = get_network_driver('ios')
iosvl2 = driver(alive_dev['ipaddr'], alive_cred[1], alive_cred[2])
iosvl2.open()
except:
print(f"Attempting to reconnect to {alive_cred[0]}")
else:
alive_output = iosvl2.is_alive()
print(alive_output)
return alive_output['is_alive'] == True
break
if __name__ == '__main__':
net_devices = read_device_data('devices_data')
net_creds = read_device_creds('encrypted_device_creds', 'cisco')
# starting_time = time()
for ipadd, device_info in net_devices.items():
print(net_devices.items())
while True:
print (f'Connecting to: {ipadd}')
if check_BGP(device_info, net_creds[ipadd]) == True:
print(f'Reloading {ipadd} now')
reload(net_creds[ipadd])
else:
print(f'Re-checking BGP on {ipadd}')
if is_alive(device_info, net_creds[ipadd]) == True and check_BGP(device_info, net_creds[ipadd]) == True:
print(f'{ipadd} back online and BGP OK!')
break
else:
print('Router down or BGP failed to reconverged; exiting script')
break
# print ('\n---- End get config sequential, elapsed time=', time() - starting_time)
In the example below, I wrote a code that detects BGP route limits. Its purpose is to calculate the route limit rate by learning the information under the Interfaces. In this regard, I recommend the TTP module, where you can create your own templates.
from netmiko import ConnectHandler
from getpass import getpass
from pprint import pprint
from ttp import ttp
from genie.testbed import load
from pprint import pprint
import json
import time
from multiprocessing.dummy import Pool as ThreadPool
from netmiko import Netmiko
#**************************************************************************************************************************
with open("user_pass.txt", "r") as f5:
user_pass = f5.readlines()
for list_user_pass in user_pass:
if "username" in list_user_pass:
username = list_user_pass.split(":")[1].strip()
if "password" in list_user_pass:
password = list_user_pass.split(":")[1].strip()
def _ssh_(nodeip):
try:
huawei = {
'device_type': 'huawei', 'ip': nodeip, 'username':
username, 'password': password, }
con = Netmiko(**huawei)
print(nodeip.strip() + " " + "basarili giris")
except Exception as e:
print(e)
f_3.write(nodeip.strip() + "\n")
return
#**************************************************************************************************************************
data_to_parse_0 = con.send_command_timing('display ip vpn-instance | ignore-case i Customer_A')
print(data_to_parse_0)
ttp_template_0 ="""
{{Customer_Name}} {{nodeip}} {{IPV4}}
"""
parser_0 = ttp(data=data_to_parse_0, template=ttp_template_0)
parser_0.parse()
#print result in JSON format
results_0 = parser_0.result(format='json')[0]
print(results_0)
#str to list **convert with json.loads
result_0 = json.loads(results_0)
print(result_0[0]["Customer_Name"])
#**************************************************************************************************************************
data_to_parse = con.send_command_timing("display current-configuration configuration vpn-instance {}".format(result_0[0]["Customer_Name"]))
print(data_to_parse)
ttp_template ="""
{{routing-table}} limit {{ total_number | DIGIT }} {{total_number2}}
"""
parser = ttp(data=data_to_parse, template=ttp_template)
parser.parse()
#print result in JSON format
results = parser.result(format='json')[0]
print(results)
#str to list **convert with json.loads
result = json.loads(results)
print(result)
#**************************************************************************************************************************
data_to_parse_2 = con.send_command_timing('dis ip routing-table vpn-instance' + " " + result_0[0]["Customer_Name"] + " " + " statistics | i Summary Prefixes")
print(data_to_parse_2)
ttp_template_2 ="""
Summary Prefixes : {{ used_number | DIGIT }}
"""
parser2 = ttp(data=data_to_parse_2, template=ttp_template_2)
parser2.parse()
#print result in JSON format
results2 = parser2.result(format='json')[0]
print(results2)
#str to list **convert with json.loads
result2 = json.loads(results2)
print(result2[0]["used_number"])
#**************************************************************************************************************************
result3 = (int(result2[0]["used_number"]) / int(result[0]["total_number"])) * 100
print(int(result3))
with open("vrf_limit_result.txt", "a") as f:
f.write("Customer_Result" +"_" + nodeip +"==>" + str(result3)+ "\n")
f.close()
#**************************************************************************************************************************
f_2 = open("ip_list.txt", "r")
ip_list = f_2.readlines()
f_2.close()
f_3 = open("Ssh_unconnected_2.txt", "w")
# Therading method
myPool = ThreadPool(100)
result = myPool.map(_ssh_, ip_list)

Error using win32com & pttsx3 for Python Voice Recognition

'''
Please help me out at this stage.i want to do this program with win32com & pyttsx 3. tried both but not working . Below is my code please check and help.
I want program to answer me back as as per defined answers.
Program is working fine and replying as a text but i am not getting any response by voice..
'''
# audio.py File
import pyaudio
import speech_recognition as sr
import pyglet
from commands import Commander
import subprocess
import win32com.client as wincl
import wave
import pyttsx3
running = True #ss
def say(text):
speak = wincl("SAPI.SpVoice")
speak.Speak('say ' + text, shell=True)
def play_audio(filename):
chunk = 1024
wf = wave.open(filename, 'rb')
pa = pyaudio.PyAudio()
stream = pa.open(
format=pa.get_format_from_width(wf.getsampwidth()),
channels = wf.getnchannels(),
rate = wf.getframerate(),
output = True
)
data_stream = wf.readframes(chunk)
while data_stream:
stream.write(data_stream)
data_stream = wf.readframes(chunk)
stream.close()
pa.terminate()
play_audio("./audio/after.wav")
# Upper part is to play sound using pyaudio
r = sr.Recognizer()
cmd = Commander() #
def initSpeech():
print("Listening.....")
play_audio("./audio/before.wav")
with sr.Microphone() as source:
print("Say Something")
audio = r.listen(source)
play_audio("./audio/before.wav")
command = ""
try:
command = r.recognize_google(audio)
except:
print("Couldn't understand you bro. ")
print("Your Command: ")
print(command)
if command == "quit":
running = False #
#echo('You Said: ' + command)
cmd.discover(command) #
#speak.Speak('You Said: ' + command) -------> no comment
while running == True:
initSpeech()
-----------------------------------------------------------------------------------------------------
# commands.py File
import subprocess
import os
class Commander:
def __init__(self):
self.confirm = ["yes", "affirmative", "si", "sure", "do it", "yeah", "confirm"]
self.cancel = ["no", "negative", "negative soldier", "don't", "wait", "cancel"]
def discover(self, text):
if "what" in text and "your name" in text:
if "my" in text:
self.respond("You haven't told your name yet")
self.respond("My name is python commander. How are you")
def respond(self, response):
print(response)
speak.Speak('say ' + response, shell=True) # This Speak is
from pywin32

appending command name to files python3

While learning through the network automation with python, I have created a script to capture the few network switch details with some sorts of commands. i have explicitely kept the commands in commands.txt and login credentilas in a file devices.json in a Jason format to pick it from and when i run this it works as expected by creating a file with command out details with time stamp.
What i Want: As i have commands.txt file which has diffrent commands, where i would like to have an idea of creating a separate file for each command which i have into commands.txt. as of now everything getting captured to a single file, desired example ..
prod-stvdx-sw_vcs_details.txt-Apr-10-2018:12:53
prod-stvdx-sw_vcs.txt-Apr-10-2018:12:53
prod-stvdx-sw_fabric_trunk.txt-Apr-10-2018:12:53
Below is the script version:
from __future__ import absolute_import, division, print_function
import json
import netmiko
import signal
import sys
import time
timestamp = time.strftime('%b-%d-%Y:%H:%M')
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # IOError: Broken pipe
signal.signal(signal.SIGINT, signal.SIG_DFL) # KeyboardInterrupt: Ctrl-C
if len(sys.argv) < 3:
print('Usage: cmdrunner.py commands.txt devices.json')
exit()
netmiko_exceptions = (netmiko.ssh_exception.NetMikoTimeoutException,
netmiko.ssh_exception.NetMikoAuthenticationException)
#username, password = getPass.get_credentials()
with open(sys.argv[1]) as cmd_file:
commands = cmd_file.readlines()
with open(sys.argv[2]) as dev_file:
devices = json.load(dev_file)
for device in devices:
#device['username'] = username
#device['password'] = password
try:
print('~' * 79)
print('Connecting to device:', device['ip'])
connection = netmiko.ConnectHandler(**device)
filename = connection.base_prompt + '.txt' + '-' + timestamp
with open(filename, 'w') as out_file:
for command in commands:
out_file.write('++++ Output of ' + command + '\n\n')
out_file.write(connection.send_command(command) + '\n\n')
connection.disconnect()
except netmiko_exceptions as e:
print('Failed to ', device['ip'], e)
My commands.txt File:
$ cat commands.txt
show vcs details
show vcs
show fabric islports
show fabric isl
show fabric trunk
show logging raslog
show version
show ip int brief
Run
$ ./brocade_2.py commands.txt devices.json
-rw-r--r-- 1 moli moli 286K Apr 10 12:53 prod-stvdx-sw.txt-Apr-10-2018:12:53
I think if I understand correctly, you want to capture the output of each command in a separate file:
from __future__ import absolute_import, division, print_function
import json
import netmiko
import signal
import sys
import time
timestamp = time.strftime('%b-%d-%Y:%H:%M')
signal.signal(signal.SIGPIPE, signal.SIG_DFL) # IOError: Broken pipe
signal.signal(signal.SIGINT, signal.SIG_DFL) # KeyboardInterrupt: Ctrl-C
if len(sys.argv) < 3:
print('Usage: cmdrunner.py commands.txt devices.json')
exit()
netmiko_exceptions = (netmiko.ssh_exception.NetMikoTimeoutException,
netmiko.ssh_exception.NetMikoAuthenticationException)
#username, password = getPass.get_credentials()
with open(sys.argv[1]) as cmd_file:
commands = cmd_file.readlines()
with open(sys.argv[2]) as dev_file:
devices = json.load(dev_file)
for device in devices:
#device['username'] = username
#device['password'] = password
try:
print('~' * 79)
print('Connecting to device:', device['ip'])
connection = netmiko.ConnectHandler(**device)
for command in commands:
filename = connection.base_prompt +'-'+ command+'.txt' + '-' + timestamp
with open(filename, 'w') as out_file:
out_file.write('++++ Output of ' + command + '\n\n')
out_file.write(connection.send_command(command) + '\n\n')
connection.disconnect()
except netmiko_exceptions as e:
print('Failed to ', device['ip'], e)

Pyserial, Getting extra info from OBD Device

I am new at programming and am trying to communicate with my vehicle with an OBD II device. Serial to USB. I've done what I want it to do but I get the command I entered to print out. How do I just get the information from the device?
Heres my code. I am using Python 3.2.3
import serial
import time
import string
import io
import os
import sys
ser = serial.Serial("/dev/ttyUSB1")
ser.baudrate = 38400
s = input('Enter AT command --> ')
print ('AT command = ' + s)
ser.write(bytes(s + '\r\n', encoding = 'utf-8'))
ser.timeout = 1
response = ser.read(999).decode('utf-8')
print(response)
ser.close()
And here is what prints out when I enter the command 'atrv'.
>>>
Enter AT command --> atrv
AT command = atrv
atrv
0.1V
>>>
How do I prevent the 'atrv' above the 0.1V from printing out?
Send ATE0 to the ELM-device.
This disables the echo, so atrv won't be send back to you!
Have a look into this: http://elmelectronics.com/DSheets/ELM327DS.pdf , collection of lots of AT commands, could be helpful!
on a raspberry PI i had to modify the code to:
import serial
import time
import string
import io
import os
import sys
ser = serial.Serial("/dev/rfcomm0")
ser.baudrate = 115200
s = input('Enter AT command --> ')
print ('AT command = ' + s)
ser.flushInput();
ser.write(bytes(s + '\r\n', encoding = 'utf-8'))
ser.flush();
ser.timeout = 1
response = ser.read(999).decode('utf-8')
print(response)
ser.close()

Resources