Find USB serial port with Python script - python

I am trying to write a script in python so I can find in 1 sec the COM number of the USB serial adapter I have plugged to my laptop.
What I need is to isolate the COMx port so I can display the result and open putty with that specific port. Can you help me with that?
Until now I have already written a script in batch/powershell and I am getting this information but I havent been able to separate the text of the COMx port so I can call the putty program with the serial parameter.
I have also been able to find the port via Python but I cant isolate it from the string.
import re # Used for regular expressions (unused)
import os # To check that the path of the files defined in the config file exist (unused)
import sys # To leave the script if (unused)
import numpy as np
from infi.devicemanager import DeviceManager
dm = DeviceManager()
dm.root.rescan()
devs = dm.all_devices
print ('Size of Devs: ',len(devs))
print ('Type of Devs: ',type(devs))
myarray = ([])
myarray =np.array(devs)
print ('Type of thing: ',type(myarray))
match = '<USB Serial Port (COM6)>' (custom match. the ideal would be "USB Serial Port")
i=0
#print (myarray, '\n')
while i != len(devs):
if match == myarray[i]:
print ('Found it!')
break
print ('array: ',i," : ", myarray[i])
i = i+1
print ('array 49: ', myarray[49]) (here I was checking what is the difference of the "element" inside the array)
print ('match : ', match) (and what is the difference of what I submitted)
print ('end')
I was expecting the if match == myarray[i] to find the two elements but for some reason it doesnt. Its returning me that those two are not the same.
Thank you for any help in advance!
=== UPDATE ===
Full script can be found here
https://github.com/elessargr/k9-serial

this is a follow up answer from #MacrosG
i tried a minimal example with properties from Device
from infi.devicemanager import DeviceManager
dm = DeviceManager()
dm.root.rescan()
devs = dm.all_devices
print ('Size of Devs: ',len(devs))
for d in devs:
if "USB" in d.description :
print(d.description)

If Python says the strings are not the same I dare say it's quite likely they are not.
You can compare with:
if "USB Serial Port" in devs[i]:
Then you should be able to find not a complete letter by letter match but one that contains a USB port.
There is no need to use numpy, devs is already a list and hence iterable.

If you want to do this with regular-expressions:
def main():
from infi.devicemanager import DeviceManager
import re
device_manager = DeviceManager()
device_manager.root.rescan()
pattern = r"USB Serial Port \(COM(\d)\)"
for device in device_manager.all_devices:
try:
match = re.fullmatch(pattern, device.friendly_name)
except KeyError:
continue
if match is None:
continue
com_number = match.group(1)
print(f"Found device \"{device.friendly_name}\" -> com_number: {com_number}")
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
Output:
Found device "USB Serial Port (COM3)" -> com_number: 3

Huge thanks to everyone and especially to bigdataolddriver since I went with his solution
Last thing!
for d in devs:
if "USB Serial Port" in d.description :
str = d.__str__()
COMport = str.split('(', 1)[1].split(')')[0]
i=1
break
else:
i=0
if i == 1:
print ("I found it!")
print(d.description, "found on : ", COMport)
subprocess.Popen(r'"C:\Tools\putty.exe" -serial ', COMport)
elif i ==0:
print ("USB Serial Not found \nPlease check physical connection.")
else:
print("Error")
Any ideas how to pass the COMport to the putty.exe as a parameter?
===== UPDATE =====
if i == 1:
print ("I found it!")
print(d.description, "found on : ", COMport)
command = '"C:\MyTools\putty.exe" -serial ' + COMport
#print (command)
subprocess.Popen(command)
Thank you everyone!

Related

MegaRAID nagios monitoring

I have been beating my head against the wall, trying to figure out what is wrong with the following nagios plugin I wrote. When I run the following code:
#!/usr/bin/env python3
import paramiko
import os.path
import sys
OK = 0
WARNING = 1
CRITICAL = 2
DEPENDENT = 3
UNKNOWN = 4
active = str("Active")
online = str("Online")
optimal = str("Optimal")
k = str("OK")
degrade = str("Degraded")
fail = str("Failed")
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
hostname='<hostname>',
username='<service account>',
key_filename=os.path.join(os.path.expanduser('~'), ".ssh", "id_rsa.pub")
)
stdin,stdout,stderr = client.exec_command("sudo /opt/MegaRAID/MegaCli/MegaCli64 -ShowSummary -a0")
check = str(stdout.read().decode('ascii'))
client.close()
OK_STR = str("RAID is OK!")
WARN_STR = str("Warning! Something is wrong with the RAID!")
CRIT_STR = str("CRITICAL! THE RAID IS BROKEN")
UNK_STR = str("Uh oh! Something ain't right?")
print(check)
if (degrade) in (check):
print(WARN_STR) and sys.exit(WARNING)
elif (fail) in (check):
print(CRIT_STR) and sys.exit(CRITICAL)
elif str('Exit Code: 0x00') in (check):
print(OK_STR) and sys.exit(OK)
else:
sys.exit(UNKNOWN) and print(UNK_STR)
I recieve the output that I expect running it from CLI. If I change my logic on the if statement, the exit code changes and I have verified using 'echo $?'.
However, in my LibreNMS front end, I receive no stdout message and an exit code of 1, which is not how my code outputs in the terminal. If anybody can find something wrong with my code, I really need the help.

How to filter characters for comparison of strings in Python

i am very new to coding and I am not familiar with python, could you guys give me maybe a small example of how you would solve this problem.
Basically this new device i will be working on has a 2D code(its sort of a barcode kkind of thing) and when i scan the code witha 2D scanner a string like this shows up on my notepad for example: 58183#99AF0M000F9EF3F800
the last 12 characters are the MAC address and the first 5 characters are the order number.
i need to compare that(58183#99AF0M000F9EF3F800) with the MAC address value i get from the XML page.
here is the terminal output for more reference:
####################################################################################################
Current device information:
Order-number: 58184 Software-version: 1.0.0 ( Build : 1 ) Hardware version: 1.00 MAC address: 00:0F:9E:F4:1A:80
desired-Order-number: 58183 desired-Softwareversion: 1.0.0 ( Build : 1 ) desired-hardwareversion: 1.00 pc-praefix: 7A2F7
PASS
PS C:\Users\Aswin\Python Project>
The MAC address from the XML page has looks like this "00:0F:9E:F4:1A:80" and the 2D scancode looks like this "58183#99AF0M000F9EF3F800". how can i take the last 12 characters of this scan code and compare it with the mac address from the XML page to see if they match.
Any example of code blocks would be much appreciated guys.
try:
preflash = urllib.request.urlopen("http://10.10.10.2", timeout=3).getcode()
print("Web page status code:", preflash, "FAIL")
sys.exit(0)
except urllib.error.URLError:
correct = urllib.request.urlopen("http://192.168.100.5", timeout=10).getcode()
print("Web page status code:", correct)
print("IP address: 192.168.100.5 is reachable")
print(100*"#")
# Declare url String
url_str = 'http://192.168.100.2/globals.xml'
# open webpage and read values
xml_str = urllib.request.urlopen(url_str).read()
# Parses XML doc to String for Terminal output
xmldoc = minidom.parseString(xml_str)
# prints the order_number from the xmldoc
order_number = xmldoc.getElementsByTagName('order_number')
ord_nmr = order_number[0].firstChild.nodeValue
# prints the firmware_version from the xmldoc
firmware_version = xmldoc.getElementsByTagName('firmware_version')
frm_ver = firmware_version[0].firstChild.nodeValue
# prints the hardware_version from the xmldoc
hardware_version = xmldoc.getElementsByTagName('hardware_version')
hrd_ver = hardware_version[0].firstChild.nodeValue
v = hrd_ver.split()[-1]
# prints the mac_address from the xmldoc
mac_address = xmldoc.getElementsByTagName('mac_address')
mac_addr = mac_address[0].firstChild.nodeValue
print("Current device information: ")
print("Order-number: ",ord_nmr, "Software-version: ",frm_ver, "Hardware version: ",v, "MAC address: ",mac_addr)
d_ordernum = "58183"
d_hw_version = "1.00"
d_sf_version = "1.0.0 ( Build : 1 )"
pc_praefix = "7A2F7"
print("desired-Order-number: 58183 desired-Softwareversion: 1.0.0 ( Build : 1 ) desired-hardwareversion: 1.00 pc-praefix: 7A2F7")
if d_sf_version == frm_ver:
print("PASS")
else:
print("FAIL")
You could take the string from the scan code and slice it
scan_code_cropped = scancode_string[11:]
This will get you the last 12 characters of the scan code.
Now to get the MAC address in a format to be able to compare it to the scan code, split it on the basis of ":"
list_of_chars = mac_address_string.split(":")
this will get you the character list, which can be concatenated using
mac_address_string_joined = ''.join(list_of_chars)
and finally to compare the two strings
if scan_code_cropped == mac_address_string_joined:
print("Mac address & Scan code matched !")
If needed in a function format, here you go:
def match_scan_with_mac(scancode_string, mac_address_string):
# get the last 12 characters of the scan code
scan_code_cropped = scancode_string[11:]
# get the mac address without the ":"
list_of_chars = mac_address_string.split(":")
mac_address_string_joined = ''.join(list_of_chars)
# compare the MAC address and the scan string
if scan_code_cropped == mac_address_string_joined:
print("Mac address & Scan code matched !")
return True
return False

Print new line not working in Python

The \n just doesn't seem to work for me when I use it with print. I am using Python 2.7.8. I don't get whats wrong, I think \n with a print should print a new line very straight forwardly.
import sys
import os
import subprocess
from collections import OrderedDict
import xmlrpclib
import hawkey
op_name = sys.argv[1]
pkg_name = sys.argv[2]
# Hawkey Configurations
sack = hawkey.Sack()
path = "/home/thejdeep/test_repo/repodata/%s"
repo = hawkey.Repo("test")
repo.repomd_fn = path % "repomd.xml"
repo.primary_fn = path % "b6f6911f7d9fb63f001388f1ecd0766cec060c1d04c703c6a74969eadc24ec97-primary.xml.gz"
repo.filelists_fn = path % "df5897ed6d3f87f2be4432543edf2f58996e5c9e6a7acee054f9dbfe513df4da-filelists.xml.gz"
sack.load_repo(repo,load_filelists=True)
# Main Function
if __name__ == "__main__":
print "Querying the repository\n"
print "-----------------------\n"
print "Found packages :\n"
print "--------------\n"
q = hawkey.Query(sack)
q = q.filter(name=pkg_name,latest_per_arch=True)[0]
if q:
for pkg in q:
print str(pkg)
else:
print "No packages with name "+pkg_name+" found. Exiting"
sys.exit()
print "--------------------"
print "Performing Dependency Check"
Output is something like this. Basically its printing in the same line :
Querying the repository ----------------------- Found packages : --------------
Using print method automatically add \n at the end of the line so its not necessary put \n at the end of each line.

How do I dynamicly connect to different devices on their COM ports with the same function?

I have two devices that each have their usb-serial connector. The usb-serial connection gives access to 3 COM ports for communication to different chips on each device.
I want to create a function initialise() that automatically scans and hooks up to the COM ports of the device which isnt in use yet.
I currently have the following, but it fails to hook up with the second device when I run the function twice and I am stuck right now so I need a clever suggestion.
def initialise():
PORTMAPPINGWIN = {'fwmain': ('COM8','COM12','COM4'),
'fwutil': ('COM9','COM13','COM5'),
'fwcif': ('COM10','COM14','COM6')}
PORTMAPPINGMAC = {'fwmain': ('/dev/tty.usbserial-000013FAB','/dev/tty.usbserial-12345B'),
'fwutil': ('/dev/tty.usbserial-000013FAC','/dev/tty.usbserial-12345C'),
'fwcif': ('/dev/tty.usbserial-000013FAD','/dev/tty.usbserial-12345D')}
if os.name == 'nt':
_portmap = PORTMAPPINGWIN
else:
_portmap = PORTMAPPINGMAC
_available = []
_n = len(_portmap['fwmain'])
for portaddress in range(_n):
for termname in _portmap.keys():
usb = _portmap[termname][portaddress]
try:
_ser = serial.Serial(usb, 115200)
_ser.close()
_available.append(usb)
except serial.SerialException:
pass
_available.sort()
if _available != [] and _available != None:
if _available[0] == 'COM10': #TODO use a regex instead to replace all COM5 instances with COM05 so that we can sort properly list('COM5').insert(re.search(r'(?<=COM)\d', 'COM5').start(), '0')
if len(_available) < 4:
_available.insert(3, _available.pop(0))
elif len(_available) < 7:
_available.insert(6, _available.pop(0))
elif len(_available) < 10:
_available.insert(9, _available.pop(0))
print([port for port in _available])
if len(_available) > 3:
_available = _available[:3]
Hmmm. I changed except serial.SerialException: to except Exception: and now it works fine.
Thank you me.
I think this is a cool procedure for anyone who want to start the same script on multiple attached devices. And if you dont want to pre-specify the COM ports that the device is listed at, you could just replace
for portaddress in range(_n):
for termname in _portmap.keys():
usb = _portmap[termname][portaddress]
with for usb in range(255): usb = 'COM' + str(usb) or something like that..

Using a RegEx to match IP addresses

I'm trying to make a test for checking whether a sys.argv input matches the RegEx for an IP address...
As a simple test, I have the following...
import re
pat = re.compile("\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}")
test = pat.match(hostIP)
if test:
print "Acceptable ip address"
else:
print "Unacceptable ip address"
However when I pass random values into it, it returns "Acceptable IP address" in most cases, except when I have an "address" that is basically equivalent to \d+.
Using regex to validate IP address is a bad idea - this will pass 999.999.999.999 as valid. Try this approach using socket instead - much better validation and just as easy, if not easier to do.
import socket
def valid_ip(address):
try:
socket.inet_aton(address)
return True
except:
return False
print valid_ip('10.10.20.30')
print valid_ip('999.10.20.30')
print valid_ip('gibberish')
If you really want to use parse-the-host approach instead, this code will do it exactly:
def valid_ip(address):
try:
host_bytes = address.split('.')
valid = [int(b) for b in host_bytes]
valid = [b for b in valid if b >= 0 and b<=255]
return len(host_bytes) == 4 and len(valid) == 4
except:
return False
You have to modify your regex in the following way
pat = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
that's because . is a wildcard that stands for "every character"
regex for ip v4:
^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
otherwise you take not valid ip address like 999.999.999.999, 256.0.0.0 etc
I came across the same situation, I found the answer with use of socket library helpful but it doesn't provide support for ipv6 addresses. Found a better way for it:
Unfortunately, it Works for python3 only
import ipaddress
def valid_ip(address):
try:
print (ipaddress.ip_address(address))
return True
except:
return False
print (valid_ip('10.10.20.30'))
print (valid_ip('2001:DB8::1'))
print (valid_ip('gibberish'))
You are trying to use . as a . not as the wildcard for any character. Use \. instead to indicate a period.
def ipcheck():
# 1.Validate the ip adderess
input_ip = input('Enter the ip:')
flag = 0
pattern = "^\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}$"
match = re.match(pattern, input_ip)
if (match):
field = input_ip.split(".")
for i in range(0, len(field)):
if (int(field[i]) < 256):
flag += 1
else:
flag = 0
if (flag == 4):
print("valid ip")
else:
print('No match for ip or not a valid ip')
import re
ipv=raw_input("Enter an ip address")
a=ipv.split('.')
s=str(bin(int(a[0]))+bin(int(a[1]))+bin(int(a[2]))+bin(int(a[3])))
s=s.replace("0b",".")
m=re.search('\.[0,1]{1,8}\.[0,1]{1,8}\.[0,1]{1,8}\.[0,1]{1,8}$',s)
if m is not None:
print "Valid sequence of input"
else :
print "Invalid input sequence"
Just to keep it simple I have used this approach.
Simple as in to explain how really ipv4 address is evaluated.
Checking whether its a binary number is although not required.
Hope you like this.
str = "255.255.255.255"
print(str.split('.'))
list1 = str.split('.')
condition=0
if len(list1)==4:
for i in list1:
if int(i)>=0 and int(i)<=255:
condition=condition+1
if condition!=4:
print("Given number is not IP address")
else:
print("Given number is valid IP address")
If you really want to use RegExs, the following code may filter the non-valid ip addresses in a file, no matter the organiqation of the file, one or more per line, even if there are more text (concept itself of RegExs) :
def getIps(filename):
ips = []
with open(filename) as file:
for line in file:
ipFound = re.compile("^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$").findall(line)
hasIncorrectBytes = False
try:
for ipAddr in ipFound:
for byte in ipAddr:
if int(byte) not in range(1, 255):
hasIncorrectBytes = True
break
else:
pass
if not hasIncorrectBytes:
ips.append(ipAddr)
except:
hasIncorrectBytes = True
return ips
re.sub('((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])', '--', '127.0.0.1')
With this regular expression, only numbers from 0 to 255 could compose the address. It also handles leading zeros, so 127.00.0.1 would no pass.
IP address uses following authentication :
255 ---> 250-255
249 ---> 200-249
199 ---> 100-199
99 ---> 10-99
9 ---> 1-9
import re
k = 0
while k < 5 :
i = input("\nEnter Ip address : ")
ip = re.match("^([1][0-9][0-9].|^[2][5][0-5].|^[2][0-4][0-9].|^[1][0-9][0-9].|^[0-9][0-9].|^[0-9].)([1][0-9][0-9].|[2][5][0-5].|[2][0-4][0-9].|[1][0-9][0-9].|[0-9][0-9].|[0-9].)([1][0-9][0-9].|[2][5][0-5].|[2][0-4][0-9].|[1][0-9][0-9].|[0-9][0-9].|[0-9].)([1][0-9][0-9]|[2][5][0-5]|[2][0-4][0-9]|[1][0-9][0-9]|[0-9][0-9]|[0-9])$",i)
k = k + 1
if ip:
print ("\n=====================")
print ("Valid IP address")
print ("=====================")
break
else :
print ("\nInvalid IP")
else :
print ("\nAllowed Max 5 times")
Reply me if you have doubt?
import re
st1 = 'This is my IP Address10.123.56.25 789.356.441.561 127 255 123.55 192.168.1.2.3 192.168.2.2 str1'
Here my valid IP Address is only 192.168.2.2 and assuming 10.123.56.25 is not a valid one as it is combined with some string and 192.168.1.2.3 not valid.
pat = r'\s(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\s|$))'
match = re.search(pat,st1)
print match.group()
================ RESTART: C:/Python27/Srujan/re_practice.py ================
192.168.2.2
This will grep the exact IP Address, we can ignore any pattern look like an IP Address but not a valid one. Ex: 'Address10.123.56.25', '789.356.441.561' '192.168.1.2.3'.
Please comment if any modifications are required.
This works for python 2.7:
import re
a=raw_input("Enter a valid IP_Address:")
b=("[0-9]+"+".")+"{3}"
if re.match(b,a) and b<255:
print "Valid"
else:
print "invalid"
""" regex for finding valid ip address """
import re
IPV4 = re.fullmatch('([0-2][0-5]{2}|\d{2}|\d).([0-2][0-5]{2}|\d{2}|\d).([0-2][0-5]{2}|\d{2}|\d).([0-2][0-5]{2}|\d{2}|\d)', '100.1.1.2')
if IPV4:
print ("Valid IP address")
else:
print("Invalid IP address")

Categories

Resources