Bluez4 get device name during agent pair - python

I am implementing a custom Bluetooth pairing agent in Python using Bluez via DBUS. The agent needs to return one of a number of fixed PIN codes (legacy PINs, not simple pair mode requests) depending on which type of device is trying to pair. The devices are Bluetooth enabled medical monitors (blood pressure, scales etc) of which I have no control.
Originally, I was looking at the first bit of the devices Mac address and returning a PIN based on the manufacture prefix. This was working well. But the device I am now trying to add support for uses the same prefix (I assume it has the same BT chip) but a different PIN as one of the other devices I need to support. The only thing unique about the devices are their names which are always constant (such as "AND 1234" or "IEM 5678") so I tried to change by agent to look at the first bit of the name instead
knownPins = {
"aandd": "12345",
"iem ": "5678",
"default": "98689"
}
#dbus.service.method("org.bluez.Agent", in_signature="o", out_signature="s")
def RequestPinCode(self, device):
pprint("RequestPinCode ({})", device)
dbdevice = dbus.Interface(bus.get_object("org.bluez", device),
"org.bluez.Device")
bits = device.split('/')
mac = bits[-1].replace("dev_","").replace("_",":").lower()
props = dbdevice.GetProperties()
if not props["Name"]:
raise Rejected()
try:
for name, pin in knownPins.items():
if props["Name"].startswith(name):
return pin
return knownPins["default"]
except:
raise Rejected()
But, in most cases props["Name"] is simply empty - i assume this is because the pair request is being initiated by the remote party and since I have not done a discover, I dont know its name.
So my question is, how can I force a inquiry at this point in the process so I can get the device name? I have tried
adapter.CreateDevice(mac)
Which gives org.bluez.Error.AlreadyExists
I have tried
adapter.RemoveDevice(device)
adapter.CreateDevice(mac)
Which gives org.bluez.Error.DoesNotExist: Device creation in progress
I assume in both instances this is because Bluez is in the middle of trying to create the device
Thanks

Related

How am I able to check which devices I'm interfacing with?

I work at a microwave technology company and part of my job is developing software to interface with the devices we use using Python, specifically PyVISA. I'm currently trying to write a program that interfaces with several different types of devices that have different command structures, so before executing the code, I want to be able to check which type of device is connected (all use GPIB addresses). How can I go about doing this? Right now I've been trying to send identity commands using nested try/except blocks as shown below because the different devices have different identify commands:
import pyvisa as visa
address = "GPIB0::6::INSTR"
rm = visa.ResourceManager()
device = rm.open_resource(address)
try:
device.write("*IDN?")
identity = device.read()
except visa.errors.VisaIOError:
try:
device.write("I")
device.write("STB?")
identity = device.read()
except visa.errors.VisaIOError:
try:
device.write("ID?")
identity = device.read()
except visa.errors.VisaIOError:
identity = "Unknown"
print(identity)
The device I'm testing the code with requires the device.write("ID?") version of this command, however instead of returning the identity, it's returning the numerical error code. Is there a better way to implement this?
I would remove the try/except block and see exactly where the device is failing. Since you are getting a numerical error code, I'm betting the error flow is as follows:
The script sends *IDN?
The device doesn't recognize this command and goes into an error state.
The script sends I
The device is already in an error state and doesn't respond.
The script queries STB?
The device reports the error it logged earlier.
The script interprets this response as the device name, even though it's the answer to the Status Byte query.
I find it's often better to write the identity function specifically for each device. For example: def identity_dev1() for a device that needs *IDN? and def identity_dev2() for a device that needs I and so on.
If you want a monolithic function that can do all of the above, you'll have to change the way you handle the status byte. Here's an example:
import pyvisa as visa
address = "GPIB0::6::INSTR"
rm = visa.ResourceManager()
device = rm.open_resource(address)
identity = None
try:
device.write("*IDN?")
identity = device.read()
except visa.errors.VisaIOError:
device.write("*RST") # get rid of the error state and try something else
if not identity:
try:
device.write("ID?")
identity = device.read()
except visa.errors.VisaIOError:
device.write("*RST") # get rid of error state
if not identity:
identity = "Unknown"
In general it's better to not do extra try/except behavior over GPIB communication. Trying the wrong command takes extra time and can put the instrument in an error state. In the code above, I use the *RST command to leave the error state, but this isn't guaranteed to work on all tools.
print(identity)

badly formed hexadecimal UUID string with Adafruit library

The issue
I am trying to play with a Bluefruit LE Friend dongle (Adafruit).
They provide a python library to communicate with it.
Unfortunately, the example they provide doesn't work:
user#server# python ../../low_level.py
Using adapter: user-VirtualBox
Disconnecting any connected UART devices...
Searching for UART device...
Connecting to device...
Discovering services...
Traceback (most recent call last):
File "../../low_level.py", line 106, in <module>
ble.run_mainloop_with(main)
File "build/bdist.linux-x86_64/egg/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 118, in _user_thread_main
File "../../low_level.py", line 70, in main
device.discover([UART_SERVICE_UUID], [TX_CHAR_UUID, RX_CHAR_UUID])
File "build/bdist.linux-x86_64/egg/Adafruit_BluefruitLE/bluez_dbus/device.py", line 106, in discover
File "build/bdist.linux-x86_64/egg/Adafruit_BluefruitLE/bluez_dbus/device.py", line 137, in advertised
File "/usr/lib/python2.7/uuid.py", line 134, in __init__
raise ValueError('badly formed hexadecimal UUID string')
ValueError: badly formed hexadecimal UUID string
What I tried
I added a line in /usr/lib/python2.7/uuid.py to print the uuid value when the exception is raised; I get the value 1800. I can't find where does this value comes from.
I can't find the file build/bdist.linux-x86_64/egg/Adafruit_BluefruitLE/bluez_dbus/device.py to debug with that one…
Here's the code, from their GitHub repo:
# Example of low level interaction with a BLE UART device that has an RX and TX
# characteristic for receiving and sending data. This doesn't use any service
# implementation and instead just manipulates the services and characteristics
# on a device. See the uart_service.py example for a simpler UART service
# example that uses a high level service implementation.
# Author: Tony DiCola
import logging
import time
import uuid
import Adafruit_BluefruitLE
# Enable debug output.
#logging.basicConfig(level=logging.DEBUG)
# Define service and characteristic UUIDs used by the UART service.
UART_SERVICE_UUID = uuid.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
TX_CHAR_UUID = uuid.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E')
RX_CHAR_UUID = uuid.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E')
# Get the BLE provider for the current platform.
ble = Adafruit_BluefruitLE.get_provider()
# Main function implements the program logic so it can run in a background
# thread. Most platforms require the main thread to handle GUI events and other
# asyncronous events like BLE actions. All of the threading logic is taken care
# of automatically though and you just need to provide a main function that uses
# the BLE provider.
def main():
# Clear any cached data because both bluez and CoreBluetooth have issues with
# caching data and it going stale.
ble.clear_cached_data()
# Get the first available BLE network adapter and make sure it's powered on.
adapter = ble.get_default_adapter()
adapter.power_on()
print('Using adapter: {0}'.format(adapter.name))
# Disconnect any currently connected UART devices. Good for cleaning up and
# starting from a fresh state.
print('Disconnecting any connected UART devices...')
ble.disconnect_devices([UART_SERVICE_UUID])
# Scan for UART devices.
print('Searching for UART device...')
try:
adapter.start_scan()
# Search for the first UART device found (will time out after 60 seconds
# but you can specify an optional timeout_sec parameter to change it).
device = ble.find_device(service_uuids=[UART_SERVICE_UUID])
if device is None:
raise RuntimeError('Failed to find UART device!')
finally:
# Make sure scanning is stopped before exiting.
adapter.stop_scan()
print('Connecting to device...')
device.connect() # Will time out after 60 seconds, specify timeout_sec parameter
# to change the timeout.
# Once connected do everything else in a try/finally to make sure the device
# is disconnected when done.
try:
# Wait for service discovery to complete for at least the specified
# service and characteristic UUID lists. Will time out after 60 seconds
# (specify timeout_sec parameter to override).
print('Discovering services...')
device.discover([UART_SERVICE_UUID], [TX_CHAR_UUID, RX_CHAR_UUID])
# Find the UART service and its characteristics.
uart = device.find_service(UART_SERVICE_UUID)
rx = uart.find_characteristic(RX_CHAR_UUID)
tx = uart.find_characteristic(TX_CHAR_UUID)
# Write a string to the TX characteristic.
print('Sending message to device...')
tx.write_value('Hello world!\r\n')
# Function to receive RX characteristic changes. Note that this will
# be called on a different thread so be careful to make sure state that
# the function changes is thread safe. Use Queue or other thread-safe
# primitives to send data to other threads.
def received(data):
print('Received: {0}'.format(data))
# Turn on notification of RX characteristics using the callback above.
print('Subscribing to RX characteristic changes...')
rx.start_notify(received)
# Now just wait for 30 seconds to receive data.
print('Waiting 60 seconds to receive data from the device...')
time.sleep(60)
finally:
# Make sure device is disconnected on exit.
device.disconnect()
# Initialize the BLE system. MUST be called before other BLE calls!
ble.initialize()
# Start the mainloop to process BLE events, and run the provided function in
# a background thread. When the provided main function stops running, returns
# an integer status code, or throws an error the program will exit.
ble.run_mainloop_with(main)
This code depends on D-Bus, specifically the 'properties' offered by it. I would to say that the problem is here:
uuids = self._props.Get(_INTERFACE, 'UUIDs')
https://github.com/adafruit/Adafruit_Python_BluefruitLE/blob/master/Adafruit_BluefruitLE/bluez_dbus/device.py#L131
Probably you either didn't properly install D-Bus, or there's been another issue (linking to it, configuration, version issue, etc). When you try and get the 'UUIDs' property, you get invalid strings, which then get sense down to uuid.UUID() here:
return [uuid.UUID(str(x)) for x in uuids]
and you get the error you've seen. I would print out the value of the uuids array for debugging purposes, see what the value of the elements in it are, and proceed accordingly.
Good luck!
Well u have two ways to fix it.
Right way read more about this and configure your adafruit bluetooth.
Or bad way u can just comment this if statement check
if len(hex) != 32:
raise ValueError('badly formed hexadecimal UUID string')
in /usr/lib64/python2.7/uuid.py problem is comming from the len of "hex" parameter is need to be configured like thist 128 bit 6e400001b5a3f393e0a9e50e24dcca9e and not 16 bit0x1800.
To see which parameters of GATT u need to configure just put a
print "this is value of hex", hex
in /usr/lib64/python2.7/uuid.py before the previosly commented if statement.

Pyserial code to connect peripheral device to PC automatically when using USB- Serial cable

I have one peripheral device (say hardware circuit with microcontroller). I have to iput some commands to this peripheral device via serial communication. These commands are embedded into a python script.
I am using USB-Serial cable to connect peripheral device to PC.
Now I have to write the code in pyserial so that PC will automatically detect the com port on which Peripheral device is connected and connects the devide with PC successfully.(loop back can be possible)
Currently I am using following Code in Pyserial. I have explicitely mentioned that Peripheral is connected to PC on COM1 ---
try:
self.ser = serial.Serial(0)
#self.ser.port='/dev/ttyS1'
self.ser.baudrate = 9600
self.ser.bytesize = serial.EIGHTBITS
self.ser.parity = serial.PARITY_NONE
self.ser.stopbits = serial.STOPBITS_ONE
self.ser.timeout = 1
self.ser.xonxoff = False #disable software flow control
self.ser.rtscts = False #disable hardware (RTS/CTS) flow control
self.ser.dsrdtr = False #disable hardware (DSR/DTR) flow control
self.ser.writeTimeout = 2 #timeout for write
except Exception, e:
print "error open serial port: " + str(e)
Please let me know that how can a COM port is automatically detected and gets connect afterwards?
This is a common issue and can be solved by checking for a specific return code (usually an identification string) from the peripheral device. Here's an example, using pyserial:
from serial.tools import list_ports
def locate_port():
"""Attempt to locate the serial port to which the device
is connected."""
status_request_string = 'OI;' # Output information
expected_response = 'DISPENSEMATE'
device_port = None
for port_name, port_desc, hw_id in list_ports.comports():
with serial.Serial(port=port_name, **device_serial_settings) as ser:
ser.write(status_request_string)
if ser.readline().startswith(expected_response):
device_port = port_name
break
if not device_port:
raise UserWarning('Could not find a serial port belonging to '
'the asymtek dispensemate.')
return device_port
Usually, the manual of the device you're communicating with has at least one command that does not change the state of the device, but merely echoes back your last line or returns its configuration, hardware ROM version or simply its name. It is this response (and the command that requests it), that you 'll need to fill in for expected_response and status_request_string respectively. The device_serial_settings is a dictionary that contains the parameters such as baudrate and parity bits; everything needed to connect properly to the device, except for its name.
As you can see, the code above was written for an Asymtek Dispensemate (an old one too and thus difficult to get support for).
If you call that function, you can use its return value to simply connect to the device:
port = locate_port()
my_device = serial.Serial(port, **device_serial_settings)
There is one caveat though: if the computer is connected to several serial devices that are all powered on, it is possible that you send an illegal command to the other devices. In the best case, they simply reply with an error code and their state will be unaffected, but the command could also make changes to these devices, so check all other peripherals for their dictionaries of "allowed opcodes".

Trying to discover iOS devices on my network using python script

Trying to use pybonjour but not sure if it is what I need. https://code.google.com/p/pybonjour/
I want to be able to discover iOS devices that appear on my network automatically, will be running a script later on based on this, but first I want to just discover a iOS devices as soon as it appear/disappears on my wifi network.
So the question, how do I do this? running on a windows machine with python27 and the pybonjour package installed, the two examples work from the pybonjour page, but what command do I run to discover iOS devices using the scripts included on my network? or will this only discovery services running on my pc that i run this script on!
If I am going in the wrong direction please let me know, I can't seem to find the documentation on this package!
python browse_and_resolve.py xxxxxx
Thx
Matt.
Update...
This article and the browser was helpful, http://marknelson.us/2011/10/25/dns-service-discovery-on-windows/ in finding the services I needed to search for.
example; (this discovered my apple tv's, not at home atm so can't check what the iphone is called! I assume iphone!
python browse_and_resolve.py _appletv._tcp
Also if you have the windows utility dns-sd.exe this will search for all the services available on the network. I used this to find what I was looking for.
dns-sd -B _services._dns-sd._udp
Update...
"Bonjour is used in two ways: - publishing a service - detecting (browsing for) available services".
For what I want to do, I don't think it will work as the ipad/iPhone won't advertise a service unless I'm running a app that advertise one (or jailbreak my iPhone/ipad and then ssh will be open). Any more ideas?
What you're trying to do (a) probably can't be done, and (b) probably wouldn't be much use if it could.
The point of Bonjour is to discover services, not devices. Of course each service is provided by some device, so indirectly you can discover devices with it… but only by discovering a service that they're advertising.
As far as I know, (except Apple TVs) don't advertise any services, except while you're running an app that uses Bonjour to find the same app on other machines. (Except for jailbroken devices, which often advertise SSH, AFP, etc.)
There are a few ways to, indirectly, get a list of all services being advertised by anyone on the network. The simplest is probably to use Bonjour Browser for Windows. (I've never actually used it, but the original Mac tool and the Java port, both of which I have used, both suggest this Windows port for Windows users.) Fire it up and you'll get a list of services, and you can click on each one to get the details.
So, you can verify that your iPhone and iPad aren't advertising any services, which will show that there is no way to detect them via Bonjour.
Meanwhile, even if you did find a device, what are you planning to do? Presumably you want to communicate with the device in some way, right? Whatever service you're trying to communicate with… just browse for that service—and then, if appropriate, filter down to iOS devices. That's got to be easier than browsing for iOS devices and then filtering down to those that have the service you want.
As for whether there's any way to detect iOS devices… Well, there are at least two possibilities. I don't know if either of them will work, but…
First, even if the iOS device isn't advertising anything for you, I assume it's browsing for services you can advertise. How else does it find that there's an Apple TV to AirTunes to, an iTunes on the LAN to sync with, etc.?
So, use Bonjour Browser to get a list of all services your iTunes-running desktop, Apple TV, etc. are advertising. Then turn off all the services on your desktop, use PyBonjour to advertise whichever services seem plausibly relevant (and, if need be, use netcat to put trivial listeners on the ports you advertise). Then turn on your iPhone, and see if it connects to any of them. You may want to leave it running for a while, or switch WiFi off and back on. (I'm guessing that, despite Apple's recommendations, it doesn't browse continuously for most services, but just checks every once in a while and/or every time its network status changes. After all, Apple's recommendations are for foreground interactive apps, not background services.)
Unfortunately, even if you can find a service that all iOS devices will connect to, you may not be able to distinguish iOS devices from others just by getting connections there. For example, I'm pretty sure any Mac or Windows box running iTunes will hit up your fake AirTunes service, and any Mac will hit your AirPrint, and so on. So, how do you distinguish that from an iPhone hitting it? You may need to actually serve enough of the protocol to get information out of them. Which will be particularly difficult for Apple's undocumented protocols.
But hopefully you'll get lucky, and there will be something that all iOS devices, and nothing else, will want to talk to. iTunes Sync seems like the obvious possibility.
Alternatively, there are a few things they have to broadcast, or they just wouldn't work. You can't get on a WiFi network without broadcasts. And most home WiFi networks use DHCP, which means they have to broadcast DHCP discover (and request), as well. There may be some kind of heuristic signature you can detect in these messages. If nothing else, enabling DDNS should cause the device to send its hostname, and you can guess based on that (e.g., unless you change the defaults, hostname.lower().endswith('iphone')).
The easiest way is probably to set up your desktop as the main access point for your home network. I believe it's as simple as turning on Internet Connection Sharing somewhere in the control panel. (Setting up as a DHCP relay agent is much less overhead than being a full router, but I have no idea how you'd even get started doing that on Windows.) Then you can capture the DHCP broadcasts (or, failing that, the 802.11 broadcasts) as they come in. Wireshark will capture and parse the messages for you easily, so you can watch and see if it looks like this is worth pursuing farther. (See RFC 2131 for details on the format that aren't obvious from Wireshark's cryptic one-liner descriptions.)
You can take this even farther and watch the internet connections every host makes once they're connected to the internet. Any device that's periodically checking the App Store, the iOS upgrade server, etc.… Well, unless one of the jailbreak devteam guys lives in your house, that's probably an iPhone, right? The downside is that some of these checks may be very periodic, and detecting an iPhone 6 hours after it connects to your network isn't very exciting.
Use python-nmap rather than Bonjour. Or you could use pyzeroconf (Bonjour is an implementation of zeroconf) but it is a little outdated (but should still work).
python-nmap is probably easiest, let's suppose you wanted to find all connected devices that have 'iPhone' or 'iPad' in their hostname (just a simplistic concept):
import nmap
...
def notify_me(ip, hostname):
print("I found an iOS device! IP Address: %s, Hostname: %s" % (ip, hostname))
iOS_device_list = ['iPhone', 'iPad']
iOS_devices_on_net = {}
nm = nmap.PortScanner()
# scan ip range
for i in range(2, 50, 1):
ip = "192.168.1." + str(i)
# specify ports to scan
nm.scan(ip, '62078') # Matt mentioned that it picks up iphone-sync on this port
hostname = nm[ip].hostname()
for device in iOS_device_list:
if device.lower() in hostname.lower():
iOS_devices_on_net.update({ip:hostname})
notify_me(ip, hostname)
# show all iOS devices in ip range
print iOS_devices_on_net
The limitation of this approach is that it relies on the individual having not changed their hostname which originally includes their name and device name. It also assumes that there is a port listening on the iOS device that will return a hostname (this may not be the case). You can use osscan which is preferred by running it as a command using python-nmap library. This is obviously a much better approach. My concept above is just a simple example of how it can be used.
Using nmap from the command line (I believe python-nmap has nm.commandline() method) is simplest:
nmap -O -v ip
Also try adding --osscan-guess; --fuzzy for best results. Example:
nmap -O -v --osscan-guess ip
Then just search the output for iOS device keywords (see this example). It's human-readable. Note that you'll need to be running all of this as an administrator for it to work properly (Windows: runas, other: sudo).
So I have been working on the same issue for about a year now. I got it to work on my mac fairly quickly, but had a lot of trouble getting it to work right on my PC. I have tried many many different approaches. I have a home automation system that turns on the heating and hot water (via an arduino and RF module) when I or my partner are home (that is our iPhones are detectable on the home WiFi). In the end I used 'nslookup' to find the IP address for the iPhones (in case the IP address did change as they are dynamic (but they actually never do on my router)) and 'nmap' to detect if the iPhone is on the network. If the iPhone is in very deep sleep 'nmap' does not always find the phone, so I have made it check 10 times before it says the phone is home. Below is part of my home automation code in python. I have used threading. Any questions with the below code let me know.
# Dictionary to store variables to reuse on program restart
v = {
'boilerControlCH' : 'HIH', # 'scheduled' or 'HIH' (Honey I'm Home)
'boilerControlHW' : 'scheduled',
'thermostatSetPoint' : 20.8,
'thermostatVariance' : 0.1,
'morningTime' : datetime(1970,1,1,6,0,0),
'nightTime' : datetime(1970,1,1,23,0,0),
'someOneHome' : False,
'guest' : False,
'minimumTemperatureOO' : False,
'minimumTemperature' : 4.0,
'iPhoneMark' : {'iPhoneHostname' : 'marks-iphone', 'home' : False},
'iPhoneJessica' : {'iPhoneHostname' :'jessicaesiphone', 'home' : False}
}
and
# Check if anyone at home
def occupancyStatus(person, Bol = False):
with lockOccupancyStatus:
someOneHome = False
if 'iPhone' in person:
v[person]['home'] = Bol
elif 'retest' in person:
pass
else:
v[person] = Bol
if v['guest'] == True:
someOneHome = True
for key in v:
if 'iPhone' in key:
if v[key]['home'] == True:
someOneHome = True
v['someOneHome'] = someOneHome
variablesToFile()
return
and the main code
# iPhone home status threading code
class nmapClass(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global exitCounter
nmapThread()
msg.log('Exited nmapThread')
waitEvent.set()
waitEventAdjustable.set()
serialDataWaiting.set()
exitCounter += 1
def nmapThread():
iPhone = {}
maxCounts = 10
for phone in v:
if 'iPhone' in phone:
iPhone[phone] = {}
iPhone[phone]['hostname'] = v[phone]['iPhoneHostname']
iPhone[phone]['count'] = maxCounts
#msg.log(iPhone)
while exitFlag[0] == 0:
for phone in iPhone:
if iPhone[phone]['count'] > 0:
phoneFound = False
IPAddress = '0.0.0.0'
# Find iPhones IP address using its hostname
commandNsloolup = 'nslookup %s' %iPhone[phone]['hostname']
childNslookup = pexpect.popen_spawn.PopenSpawn(commandNsloolup, timeout = None)
output = childNslookup.readline()
while '\r\n' in output:
#msg.log(output)
if 'Name:' in output:
output = childNslookup.readline()
if 'Address:' in output:
tempStr = output
startPoint = tempStr.find('192')
tempStr = tempStr[startPoint:]
IPAddress = tempStr.replace('\r\n', '')
#msg.log(IPAddress)
output = childNslookup.readline()
if IPAddress == '0.0.0.0':
pass
#msg.error('Error finding IP address for %s' %iPhone[phone]['hostname'], GFI(CF()).lineno)
else:
#commandNmap = 'nmap -PR -sn %s' %IPAddress
#commandNmap = 'nmap -p 62078 -Pn %s' %IPAddress # -p specifies ports to try and access, -Pn removes pinging
commandNmap = 'nmap -p 62078 --max-rate 100 %s' %IPAddress
childNmap = pexpect.popen_spawn.PopenSpawn(commandNmap, timeout = None)
output = childNmap.readline()
while '\r\n' in output:
if 'Host is up' in output:
phoneFound = True
break
output = childNmap.readline()
#if phoneFound:
# break
if phoneFound:
iPhone[phone]['count'] = 0
if v[phone]['home'] == False:
msg.log('%s\'s iPhone has returned home' %phone)
occupancyStatus(phone, True)
waitEventAdjustable.set()
#else:
#msg.log('%s\'s iPhone still at home' %phone)
else:
iPhone[phone]['count'] -= 1
if v[phone]['home'] == True and iPhone[phone]['count'] == 0:
msg.log('%s\'s iPhone has left home' %phone)
occupancyStatus(phone, False)
waitEventAdjustable.set()
#else:
#msg.log('%s\'s iPhone still away from home' %phone)
elif iPhone[phone]['count'] < 0:
msg.error('Error with count variable in iPhone dictionary', GFI(CF()).lineno)
longWait = True
for phone in iPhone:
if iPhone[phone]['count'] > 0:
longWait = False
#msg.log('%s: %s' %(phone, iPhone[phone]['count']))
if longWait:
#msg.log('wait long')
# 600 = run every 10 minutes
waitEvent.wait(timeout=600)
for phone in iPhone:
iPhone[phone]['count'] = maxCounts
else:
#msg.log('wait short')
waitEvent.wait(timeout=60)
return
The code may not work if you copy it straight into your own script, as there are some parts missing which I have not copied about to try and keep things simple and easy to read, but hopefully the above code gives everyone a sense of how I did things.

python : How to detect device name/id on a serial COM

I would like some indication on how to do this in python:
Identify the port named a specific name in the serial com (\Device\VCP0 and \Device\VCP1 these are get by browsing in regedit window)
And get the id of the device that is pluged
I can already identify the avalable COM with this pySerial code that scan up the active serial port COM
import serial
def scan():
"""scan for available ports. return a list of tuples (num, name)"""
available = []
for i in range(256):
try:
s = serial.Serial(i)
available.append( (i, s.portstr))
s.close() # explicit close 'cause of delayed GC in java
except serial.SerialException:
pass
return available
if __name__=='__main__':
print "Found ports:"
for n,s in scan():
print "(%d) %s" % (n,s)
Thanks in advance
I am not sure what operating system you are using, but this is in Win7-x64
import win32com.client
wmi = win32com.client.GetObject("winmgmts:")
for serial in wmi.InstancesOf("Win32_SerialPort"):
print (serial.Name, serial.Description)
Using this information, you can parse it and get the COM numbers.
You can get other attributes of the Serial instances here:
http://msdn.microsoft.com/en-us/library/aa394413(v=vs.85).aspx
Two answer
1) Because this relies on the hardware available, it is perfectly possible that the test code worked in the environment it was written on, but doesn't work in your environment - may be quite likely if you are on Windows and this was written on Linux. The code uses port 0 - don't know how that maps to COM1 etc.
2) On Windows, COM ports used to have DOS names like COM1, COM2 - i.e. A string, not an int (they aren't like TCP/IP port numbers). More recently in Windows there is the \.\COMnotanumber format which allows a more generic name, I've seen these used by a USB to serial converter. Having had a quick look at the source code of pyserial SerialBase in serialutil.py, it's a bit odd IMO, because AFAICT self.name only gets set when you use an explicit port setting by calling self.port(portname). You might want to try intializing the serial port instance with serport = Serial(0) then explicitly calling serport.port('COM1') (or whatever your port name is instead of COM1).
Just corrected the code. its working fine... :)
import serial
def scan():
available = []
for i in range(256):
try:
s = serial.Serial('COM'+str(i))
available.append( (s.portstr))
s.close() # explicit close 'cause of delayed GC in java
except serial.SerialException:
pass
for s in available:
print "%s" % (s)
if __name__=='__main__':
print "Found ports:"
scan()
If you are using a USB to TTY serial adapter, a unique symbolic link to the device driver file will appear in /dev/serial/by-id. The folder will only appear if a serial device is plugged in. The file name displayed is created from the product information in the USB interface chip on the device and will be unique for that device.
For instance, a Korad KD3005P programmable power supply will show up as usb-Nuvoton_USB_Virtual_COM_A92014090305-if00. The symbolic link will resolve to '/../../ttyACM0'. The required device drive file is then '/dev/ttyACM0'.

Categories