Printing to a POS Thermal Printer using Python - python

Good day,
I'm working on a simple Python project and I need to print a receipt to an Epson TM-T82X thermal printer. I have checked the python-escpos library and it has good documentation.
Example is this one:
from escpos.printer import Usb
""" Seiko Epson Corp. Receipt Printer (EPSON TM-T88III) """
p = Usb(0x04b8, 0x0202, 0, profile="TM-T88III")
p.text("Hello World\n")
p.image("logo.gif")
p.barcode('1324354657687', 'EAN13', 64, 2, '', '')
p.cut()
My problem is where to get the two Usb parameters '0x04b8' and '0x0202'. I know that they are device and manufacturer IDs. Checking the documentation further, it said that the IDs can be acquired by checking the printer's Device Instance Path or Hardware ID. I've checked that as well and it gives something like this:
SWD\PRINTENUM\{67FDD9C0-3ADC-4191-9B80-1711BCA4B9DF}
I am running on Windows 10 and Windows 11. Please help. Thank you.

Related

How to get connected USB device list from windows by using python or cmd

I need to get connected USB device list from windows by using python or cmd.
for python i'm trying this.
import win32com.client
def get_usb_device():
try:
usb_list = []
wmi = win32com.client.GetObject("winmgmts:")
for usb in wmi.InstancesOf("Win32_USBHub"):
print(usb.DeviceID)
print(usb.description)
usb_list.append(usb.description)
print(usb_list)
return usb_list
except Exception as error:
print('error', error)
get_usb_device()
as a result i get this:
['USB Root Hub (USB 3.0)', 'USB Composite Device', 'USB Composite Device']
but i don't get a meaning full name.
and for cmd i'm trying this also:
wmic path CIM_LogicalDevice where "Description like 'USB%'" get /value
and again i don't get any meaning full name for connected usb devices.
when I'm connect a mouse, keyboard, pen drive or printer through the usb i want this kind of name. like 'a4tech mouse' or even if i get 'mouse' only that's also be fine. This type of name appears in the device section of the settings of windows 10. but i get 'USB Root Hub (USB 3.0)', 'USB Composite Device', which means nothing actually.
Is it possible with python?
If any one know this answer please help. Its very important for me.
Not sure if it's what you are looking for, but using Python 3 on Windows 10 with pywin32, you could use this to get all your drive letters and types:
import os
import win32api
import win32file
os.system("cls")
drive_types = {
win32file.DRIVE_UNKNOWN : "Unknown\nDrive type can't be determined.",
win32file.DRIVE_REMOVABLE : "Removable\nDrive has removable media. This includes all floppy drives and many other varieties of storage devices.",
win32file.DRIVE_FIXED : "Fixed\nDrive has fixed (nonremovable) media. This includes all hard drives, including hard drives that are removable.",
win32file.DRIVE_REMOTE : "Remote\nNetwork drives. This includes drives shared anywhere on a network.",
win32file.DRIVE_CDROM : "CDROM\nDrive is a CD-ROM. No distinction is made between read-only and read/write CD-ROM drives.",
win32file.DRIVE_RAMDISK : "RAMDisk\nDrive is a block of random access memory (RAM) on the local computer that behaves like a disk drive.",
win32file.DRIVE_NO_ROOT_DIR : "The root directory does not exist."
}
drives = win32api.GetLogicalDriveStrings().split('\x00')[:-1]
for device in drives:
type = win32file.GetDriveType(device)
print("Drive: %s" % device)
print(drive_types[type])
print("-"*72)
os.system('pause')
Your USB devices have the type win32file.DRIVE_REMOVABLE - so this is what you're looking for. Instead of printing all drives and types, you could insert an if condition to only process such removable devices.
Please note: SD-Cards and other removable storage media has the same drive type.
HTH!
Update, 13. July 2020:
To get further Inforrmations about connected Devices, have a look at the WMI Module for Python.
Check this example outputs, they list different informations about devices, including Manufacturer Descriptions, Serial Numbers and so on:
import wmi
c = wmi.WMI()
for item in c.Win32_PhysicalMedia():
print(item)
for drive in c.Win32_DiskDrive():
print(drive)
for disk in c.Win32_LogicalDisk():
print(disk)
os.system('pause')
To access a specific Information listed in this output, use the displayed Terms for direct access. Example:
for disk in c.Win32_LogicalDisk():
print(disk.Name)
when I'm connect a mouse, keyboard, pen drive or printer through the usb i want this kind of name...
It's called "Friendly Name" and you can use:
import subprocess, json
out = subprocess.getoutput("PowerShell -Command \"& {Get-PnpDevice | Select-Object Status,Class,FriendlyName,InstanceId | ConvertTo-Json}\"")
j = json.loads(out)
for dev in j:
print(dev['Status'], dev['Class'], dev['FriendlyName'], dev['InstanceId'] )
Unknown HIDClass HID-compliant system controller HID\VID_046D&PID_C52B&MI_01&COL03\9&232FD3F1&0&0002
OK DiskDrive WD My Passport 0827 USB Device USBSTOR\DISK&VEN_WD&PROD_MY_PASSPORT_0827&REV_1012\575836314142354559545058&0
...

Digital trigger for analog output

I want to trigger an analog output from a digital trigger on NI PCI 6713
http://www.ni.com/pdf/manuals/371011c.pdf
According to the datasheet I can use PFI <0..9> and those pins are indeed shown in green in NI MAX with ao/StartTrigger
My code is the following:
task = nidaqmx.Task()
task.ao_channels.add_ao_voltage_chan("Dev12/ao0")
task.triggers.start_trigger.cfg_dig_edge_start_trig("Dev12/PFI0")
task.timing.cfg_samp_clk_timing(rate=1)
task.start()
task.write([1,2,3,4,5,6,7,8,9,10,0])
I recieve the following error:
DaqError: Source terminal to be routed could not be found on the device.
Make sure the terminal name is valid for the specified device. Refer to Measurement & Automation Explorer for valid terminal names.
Property: DAQmx_DigEdge_StartTrig_Src
Property: DAQmx_DigEdge_StartTrig_Edge
Source Device: Dev12
Source Terminal: Dev12/PFI0
Channel Name: Dev12/ao0
Task Name: _unnamedTask<1C>
Status Code: -89120
I use Python 3.7
When specifying names for channels, the format is device_name/channel_name.
For physical terminals, the format is /device_name/terminal.
Note the leading slash for terminals:
task.ao_channels.add_ao_voltage_chan("Dev12/ao0")
task.triggers.start_trigger.cfg_dig_edge_start_trig("/Dev12/PFI0")
^
Here

Python: Get device "model" using pyvisa or pyserial

I wrote a data acquisition program/script that works with a device developed by our collaboration. The problem is that I can only read from this device. No writing is possible, so it's not possible to use a serial "?IDN*" command to know what device this is.
The only thing that defines this device is its "Model" that can be seen in "Devices and Printers" in Control Panel of Windows. The following figure shows it:
The guy who designed the device was able to create a labview simple program that extracts this name from the device through NI-VISA through something called "Intf Inst Name", which is called "Interface Information:Interface Description".
If I get this model name and compare it with the pyvisa device name, I'll be able to automatically detect the presence of our device, which is an important thing to have, in case a USB disconnect happens. This is because VISA opens the device through a name that can be different on every computer, but this name "GPS DATA LOGGER" is the same everywhere and always.
I need this solution to be cross-platform. That's why I need to use pyvisa or pyserial. Though any cross-platform alternative is OK.
So my question in brief: How can I use pyvisa/pyserial to find the model name corresponding to the device model (in my case "GPS DATA LOGGER")?
Please ask for any additional information you may require.
Update
I learned that there's an "attribute" pyvisa with the name "VI_ATTR_INTF_INST_NAME" that would get this name, but I don't know how to use it. Does anyone know how to read these attributes?
I found the way to do it. Unfortunately it involves opening every VISA device you have in your computer. I wrote a small pyvisa function that will do the task for you with comments. The function returns all the devices that contain the model name/descriptor mentioned as a parameter:
import pyvisa
def findInstrumentByDescriptor(descriptor):
devName = descriptor
rm = pyvisa.ResourceManager()
com_names=rm.list_resources()
devicesFound = []
#loop over all devices, open them, and check the descriptor
for com in range(len(com_names)):
try:
#try to open instrument, if failed, just skip to the next device
my_instrument=rm.open_resource(com_names[com])
except:
print("Failed to open " + com_names[com])
continue
try:
# VI_ATTR_INTF_INST_NAME is 3221160169, it contains the model name "GPS DATA LOGGER" (check pyvisa manual for other VISA attributes)
modelStr = my_instrument.get_visa_attribute(3221160169)
#search for the string you need inside the VISA attribute
if modelStr.find(devName) >= 0:
#if found, will be added to the array devicesFound
devicesFound.append(com_names[com])
my_instrument.close()
except:
#if exception is thrown here, then the device should be closed
my_instrument.close()
#return the list of devices that contain the VISA attribute required
return devicesFound
#here's the main call
print(findInstrumentByDescriptor("GPS DATA LOGGER"))
pyvisa has an optional query parameter for list_resources(), which you can use to narrow the scope of your search to just your device. The syntax for this is like a regular expression.
Try this:
from string import Template
VI_ATTR_INTF_INST_NAME = 3221160169
device_name = "GPS DATA LOGGER"
entries = dict(
ATTR = VI_ATTR_INTF_INST_NAME,
NAME = device_name )
query_template = Template(u'ASRL?*INSTR{$ATTR == "$NAME"}')
query = query_template.substitute(entries)
rm = visa.ResourceManager()
rm.list_resources(query)

Windows Media Player COM Automation works from VBS but not from Python

I try to use Windows Media Player to play audio files via COM.
The following code works fine in VBS:
Set wmp = CreateObject("WMPlayer.OCX")
wmp.settings.autoStart = True
wmp.settings.volume = 50
wmp.URL = "C:\Windows\Media\tada.wav"
while wmp.Playstate <> 1
WSH.Sleep 100
wend
Unfortunately, the identical code doesn't play any sound in Python:
import win32com.client
import time
wmp = win32com.client.dynamic.Dispatch("WMPlayer.OCX")
wmp.settings.autoStart = True
wmp.settings.volume = 50
wmp.URL = r"C:\Windows\Media\tada.wav"
while wmp.Playstate != 1:
time.sleep(0.1)
COM interaction seems to work tough, as I can create new media objects and query info about them. It's just that no sound is ever audible.
>>> media = wmp.newMedia(r"C:\Windows\Media\tada.wav")
>>> media.durationString
'00:01'
>>> wmp.currentMedia = media
>>> wmp.play() # No sound audible.
>>> wmp.PlayState
9 # wmppsTransitioning
PlayState is always reported to be wmppsTransitioning, no matter what I do.
The problem appears with Python2.7, 3.2 and 3.3 with the last two PyWin32 versions (218 and 219). OS is Windows 7 x64, the Python interpreters are all compiled for 32 bits. WMPlayer.OCX can be loaded successfully and COM works, so I don't think this is a 32bit/64bit DLL issue.
Any idea why it works with VBS and not with Python? How could I further debug this?
It seems the problem is that time.sleep doesn't pump window messages. Use some other timeout function that pumps window messages.
The reason is that Windows Media Player is an STA components, most probably because it's most commonly used as a graphical component. Some of its internals depend on regular message pumping, most probably a high-precision multimedia timer thread that sends window messages for communication, or it might depend on actual WM_TIMER messages.

pySerial list_port accuracy

I want to use pySerial's serial.tools.list_ports.comports() to list available COM ports.
Reading the documentation:
The function returns an iterable that yields tuples of three strings:
port name as it can be passed to serial.Serial or serial.serial_for_url()
description in human readable form
sort of hardware ID. E.g. may contain VID:PID of USB-serial adapters.
I'm particulary interested in the third string to search for a specific USB-serial adapter with a VID:PID pair. I would like it (ideally) to work in Windows XP and later, Mac OS X, and Linux. I've tried with pySerial 2.7 in Ubuntu 13.10 and Windows 7 and works like a charm, but the docs also say:
Also note that the reported strings are different across platforms
and operating systems, even for the same device.
Note: Support is limited to a number of operating systems. On some
systems description and hardware ID will not be available.
Do you have any real-world experience with respect these ambiguities? More detailed info? Any non-working example? Variations on the hardware ID strings across systems?
Thanks a lot!
I guess if you want a counter-example of it working not as expected, here's what I get:
>>> serial.tools.list_ports.comports()
[('/dev/tty.Bluetooth-Incoming-Port', '/dev/tty.Bluetooth-Incoming-Port', '/dev/tty.Bluetooth-Incoming-Port'), ('/dev/tty.Bluetooth-Modem', '/dev/tty.Bluetooth-Modem', '/dev/tty.Bluetooth-Modem'), ('/dev/tty.usbserial-A1024XBO', '/dev/tty.usbserial-A1024XBO', '/dev/tty.usbserial-A1024XBO')]
where a FTDI USB-Serial adapter is plugged in. Which is expectable, because here's the comports() function:
def comports():
"""scan for available ports. return a list of device names."""
devices = glob.glob('/dev/tty.*')
return [(d, d, d) for d in devices]
which is the same for cygwin, BSD, NetBSD, IRIX, HP-UX, Solaris/SunOS, AIX…
How come that result can happen? Well, because my pyserial is version 2.6, which is only six months old :-)
After upgrading to latest version (2.7) from pypi, here's what I get:
>>> serial.tools.list_ports.comports()
[['/dev/cu.Bluetooth-Incoming-Port', 'n/a', 'n/a'], ['/dev/cu.Bluetooth-Modem', 'n/a', 'n/a'], ['/dev/cu.usbserial-A1024XBO', 'FT232R USB UART', 'USB VID:PID=403:6001 SNR=A1024XBO']]
so basically, add a version check to the latest version of pyserial in your setup.py, or you may get problems. Though support is still not added for other unix flavors. It looks like the VID:PID string is handled directly by parsing OS specific stuff to make that string generic enough. So basically I guess you can safely get it with something like : vid, pid = sp[2].split(' ')[1].split('=')[-1].split(':') (which is quite stupid, why parse values to build a string that has to be parsed again afterwards?!, I mean they do szHardwareID_str = 'USB VID:PID=%s:%s SNR=%s' % (m.group(1), m.group(2), m.group(4)) we couldn't be happier with just a tuple!)
And finally, pyserial looks inconsistent with its documentation, as it says: On some systems description and hardware ID will not be available (None)., whereas it does really return 'n/a'. I guess that will be fixed in pyserial 2.8 :-)
It's been some time since my original question, but current versions of pyserial (3.0+, I believe) have solved this in a neat way. No more clever parsing.
serial.tools.list_ports.comports(...) now returns a list containing ListPortInfo objects.
ListPortInfo objects contain vid and pid attributes (integer) as well as other useful USB-related attributes (see docs) which "are all None if it is not an USB device (or the platform does not support extended info)" and this seems to be supported on the main 3 platforms ("Under Linux, OSX and Windows, extended information will be available for USB devices").
So you can do something like the following:
for port in serial.tools.list_ports.comports():
if port.vid is not None and port.pid is not None:
# It's a USB port on a platform that supports the extended info
# Do something with it.
print("Port={},VID={:#06x},PID={:#06x}".format(port.device, port.vid, port.pid))

Categories

Resources