Simplest way to publish over Zeroconf/Bonjour? - python

I've got some apps I would like to make visible with zeroconf.
Is there an easy scriptable way to do this?
Is there anything that needs to be done by my network admin to enable this?
Python or sh would be preferrable. OS-specific suggestions welcome for Linux and OS X.

pybonjour doesn't seem to be actively maintained. I'm using python-zeroconf.
pip install zeroconf
Here is an excerpt from a script I use to announce a Twisted-Autobahn WebSocket to an iOS device:
from zeroconf import ServiceInfo, Zeroconf
class WebSocketManager(service.Service, object):
ws_service_name = 'Verasonics WebSocket'
wsPort = None
wsInfo = None
def __init__(self, factory, portCallback):
factory.protocol = BroadcastServerProtocol
self.factory = factory
self.portCallback = portCallback
self.zeroconf = Zeroconf()
def privilegedStartService(self):
self.wsPort = reactor.listenTCP(0, self.factory)
port = self.wsPort.getHost().port
fqdn = socket.gethostname()
ip_addr = socket.gethostbyname(fqdn)
hostname = fqdn.split('.')[0]
wsDesc = {'service': 'Verasonics Frame', 'version': '1.0.0'}
self.wsInfo = ServiceInfo('_verasonics-ws._tcp.local.',
hostname + ' ' + self.ws_service_name + '._verasonics-ws._tcp.local.',
socket.inet_aton(ip_addr), port, 0, 0,
wsDesc, hostname + '.local.')
self.zeroconf.register_service(self.wsInfo)
self.portCallback(port)
return super(WebSocketManager, self).privilegedStartService()
def stopService(self):
self.zeroconf.unregister_service(self.wsInfo)
self.wsPort.stopListening()
return super(WebSocketManager , self).stopService()

Or you can just use bash:
dns-sd -R <Name> <Type> <Domain> <Port> [<TXT>...]
This works by default on OS X. For other *nixes, refer to the avahi-publish man page (which you may need to install via your preferred package manager).

I'd recommend pybonjour.

Although this answer points you in the right direction, it seems that python-zeroconf (0.39.4) had some changes making the example above not work (for me) anymore.
Also I think a more minimal, self-contained, answer would be nice, so here goes:
from zeroconf import ServiceInfo, Zeroconf
PORT=8080
zeroconf = Zeroconf()
wsInfo = ServiceInfo('_http._tcp.local.',
"myhost._http._tcp.local.",
PORT, 0, 0, {"random_key": "1234", "answer": "42"})
zeroconf.register_service(wsInfo)
import time
time.sleep(1000);
Note that anything beyond PORT is optional for ServiceInfo().
You can run multiple of these programs at the same time; they will all bind to the same UDP port without a problem.

Through the Avahi Python bindings, it's very easy.

Related

Network scanner on Python

I am making a network scanner python project and have created below code by looking through youtube learning. But it is not working and giving an error. here is the code-
import nmap
class network(object):
def __init__(self):
ip = input("Enter default IP address 10.10.1.1 10.10.0.1 ")
self.ip = ip
def networkscanner(self):
if len(self.ip) == 0:
network = '10.10.1.1/24'
else:
network = self.ip + '/24'
print("Start scanning please wait....")
nm = nmap.Portscanner()
nm.scan(hosts=network, arguments='-sn')
hosts_list = [(x, nm[x]['status']['state']) for x in nm.all_hosts()]
for host, status, in hosts_list:
print("host \t{}".format(host))
if __name__ == "__main__":
D = network()
D.networkscanner()
What I have understood that nmap doesn't have portscanner attributes but not sure though. I have imported python-nmap too and tried but still not working. Can anyone point me to the right direction please?
According to the documentation, the correct call would be:
nm = nmap.PortScanner()
You have a lower case "s" instead of an upper case.
https://pypi.org/project/python-nmap/
Ok, so I have managed to run the above code without any error, here are few things I did :
Uninstall both nmap and python-nmap and re installed python-nmap
correct some of the spelling and indentations
and voila! It worked.

Finding a specific serial COM port in pySerial (Windows)

I have a script built (Windows 7, Python 2.7) to list the serial ports but I'm looking for a device with a specific name.
My script:
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
print(p)
This returns:
COM3 - Intel(R) Active Management Technology - SOL (COM3)
COM6 - MyCDCDevice (COM6)
COM1 - Communications Port (COM1)
>>>
Great! However, I want this script to automatically pick out MyCDCDevice from the bunch and connect to it.
I tried:
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
if 'MyCDCDevice' in p:
print(p)
// do connection stuff to COM6
But that doesn't work. I suspect because p isn't exactly a string, but an object of some sort?
Anyways, what's the correct way to go about this?
Thanks!!
I know this post is very old, but I thought I would post my findings since there was no 'accepted' answer (better late than never).
This documentation helped with determining members of the object, and I eventually came to this solution.
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
if 'MyCDCDevice' in p.description:
print(p)
# Connection to port
s = serial.Serial(p.device)
To further extend on this, I've found it safer to make use of the PID and VID of the device in question.
import serial.tools.list_ports
# FTDI FT232 device (http://www.linux-usb.org/usb.ids)
pid="0403"
hid="6001"
my_comm_port = None
ports = list(serial.tools.list_ports.comports())
for p in ports:
if pid and hid in p.hwid:
my_comm_port = p.device
Better still, you can use the serial number of the device for the lookup, just in case you have 2 of the same device plugged in.
(Source)
You can use serial.tools.list_ports.grep, which searches all of the description fields for you. For example:
from serial.tools import list_ports
try:
cdc = next(list_ports.grep("MyCDCDevice"))
# Do connection stuff on cdc
except StopIteration:
print "No device found"
If that doesn't work, you may try adding a * to the end of the string you pass to grep in case there are extra characters in the descriptor.

Finding Bluetooth low energy with python

Is it possible for this code to be modified to include Bluetooth Low Energy devices as well? https://code.google.com/p/pybluez/source/browse/trunk/examples/advanced/inquiry-with-rssi.py?r=1
I can find devices like my phone and other bluetooth 4.0 devices, but not any BLE. If this cannot be modified, is it possible to run the hcitool lescan and pull the data from hci dump within python? I can use the tools to see the devices I am looking for and it gives an RSSI in hcidump, which is what my end goal is. To get a MAC address and RSSI from the BLE device.
Thanks!
As I said in the comment, that library won't work with BLE.
Here's some example code to do a simple BLE scan:
import sys
import os
import struct
from ctypes import (CDLL, get_errno)
from ctypes.util import find_library
from socket import (
socket,
AF_BLUETOOTH,
SOCK_RAW,
BTPROTO_HCI,
SOL_HCI,
HCI_FILTER,
)
if not os.geteuid() == 0:
sys.exit("script only works as root")
btlib = find_library("bluetooth")
if not btlib:
raise Exception(
"Can't find required bluetooth libraries"
" (need to install bluez)"
)
bluez = CDLL(btlib, use_errno=True)
dev_id = bluez.hci_get_route(None)
sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)
sock.bind((dev_id,))
err = bluez.hci_le_set_scan_parameters(sock.fileno(), 0, 0x10, 0x10, 0, 0, 1000);
if err < 0:
raise Exception("Set scan parameters failed")
# occurs when scanning is still enabled from previous call
# allows LE advertising events
hci_filter = struct.pack(
"<IQH",
0x00000010,
0x4000000000000000,
0
)
sock.setsockopt(SOL_HCI, HCI_FILTER, hci_filter)
err = bluez.hci_le_set_scan_enable(
sock.fileno(),
1, # 1 - turn on; 0 - turn off
0, # 0-filtering disabled, 1-filter out duplicates
1000 # timeout
)
if err < 0:
errnum = get_errno()
raise Exception("{} {}".format(
errno.errorcode[errnum],
os.strerror(errnum)
))
while True:
data = sock.recv(1024)
# print bluetooth address from LE Advert. packet
print(':'.join("{0:02x}".format(x) for x in data[12:6:-1]))
I had to piece all of that together by looking at the hcitool and gatttool source code that comes with Bluez. The code is completely dependent on libbluetooth-dev so you'll have to make sure you have that installed first.
A better way would be to use dbus to make calls to bluetoothd, but I haven't had a chance to research that yet. Also, the dbus interface is limited in what you can do with a BLE connection after you make one.
EDIT:
Martin Tramšak pointed out that in Python 2 you need to change the last line to print(':'.join("{0:02x}".format(ord(x)) for x in data[12:6:-1]))
You could also try pygattlib. It can be used to discover devices, and (currently) there is a basic support for reading/writing characteristics. No RSSI for now.
You could discover using the following snippet:
from gattlib import DiscoveryService
service = DiscoveryService("hci0")
devices = service.discover(2)
DiscoveryService accepts the name of the device, and the method discover accepts a timeout (in seconds) for waiting responses. devices is a dictionary, with BL address as keys, and names as values.
pygattlib is packaged for Debian (or Ubuntu), and also available as a pip package.

Unable to identify the host : Fabric

I m trying to use fabric module through simple python module
remoteExc.py
from fabric.api import *
def clone_repo(IPADDRESS,USER,fPath,git_url):
env.hosts_string = IPADDRESS
env.user = USER
env.key_filename = fPath
env.disable_known_hosts = 'True'
run('git clone %s' % (git_url))
mainFile.py
from remoteExc import clone_repo
clone_repo(ipAddress,user,fPath,git_url)
When i execute it says
python mainfile.py
No hosts found. Please specify (single) host string for connection:
Please enlight me where i make a mistake
Typo. env.host_string = IPADDRESS - you've got an env.hosts_string instead.
Also, generally you run fabric via fab - unless you're trying to do something fairly non-standard, be aware that running it via python probably isn't what you want to do. See the Fabric docs for a pretty good intro.
http://docs.fabfile.org/en/1.7/tutorial.html

Python equivalent of Perl Net::NBName to get Windows username?

I'm trying to re-code some Perl script I have to Python (and extend it). With Perl, using the Net library, I can give a hostname and get the Windows username. Here is a snippet of Perl code:
my $NetBios = Net::NBName->new;
my $nbName = $NetBios->node_status($hostname);
if ( $nbName ) {
if ( $nbName->as_string =~ /^(\S+)\s+/ ) {
($user = $1) =~ tr/A-Z/a-z/;
}
}
I'd like to do the same thing in Python, but I cannot seem to find the right library to do this. Is there an equivalent way?
For the background, I get the hostname of the user that is connected to a terminal server port. From that, if the hostname has "dhcp" or "vpn" in it, I want to use NetBIOS and try to get the username for that system (likely a PC).
although afaik you cannot pass it a domain
import getpass
print getpass.getuser()
platform uname may also be useful
import platform
platform.uname()
I found the following at activestate (although I can make no guarantees as to what it does)
http://code.activestate.com/recipes/66314-get-user-info-on-windows-for-current-user/
import win32api
import win32net
import win32netcon
def UserGetInfo():
dc=win32net.NetServerEnum(None,100,win32netcon.SV_TYPE_DOMAIN_CTRL)
user=win32api.GetUserName()
if dc[0]:
dcname=dc[0][0]['name']
return win32net.NetUserGetInfo("\\\\"+dcname,user,1)
else:
return win32net.NetUserGetInfo(None,user,1)
if __name__=="__main__":
print UserGetInfo()

Categories