I am using an Epson TM-T20II thermal receipt printer, and I need to print receipt out with Danish characters (æ,ø,å). To ESCPOS code for character language selection is described here. My Python code is as below
import win32print
import six
#create some raw data
rawdata = b'\x1b\x40' #Instantiate the printer ESC #
rawdata = rawdata + b'\x1b\x52\x10' #Select the Danish II character set as in documentation ESC R
where n = 10
rawdata = bytes('Print æ,ø,å', 'utf-8') + b'\n' + b'\x1d\x56' + six.int2byte(66) + b'\x00' #print
some text and cut
#Creating the printing job in Windows 10 and send the raw text to the printer driver
printer = win32print.OpenPrinter('EPSON TM-T20II Receipt')
hJob = win32print.StartDocPrinter(printer, 1, ("Test print", None, "RAW"))
win32print.WritePrinter(printer, rawdata)
win32print.EndPagePrinter(printer)
win32print.ClosePrinter(printer)
My problem is that I get some strange character printed out. Also I have set the printer to Danish II by holding down the feed button and while power on the printer. What have I missed?
For the time being, what you might want to try is to change the encoding specification below from utf-8 to cp865.
rawdata = bytes('Print æ,ø,å', 'utf-8') + b'\n' + b'\x1d\x56' + six.int2byte(66) + b'\x00' #print
If that doesn't work, you should stop using win32print and switch to pyserial.
It is also necessary to switch the printer mode, uninstall the Advanced Printer Driver, and install the printer serial port driver.
Then the application program needs to create all the print data using the raw ESC/POS commands.
The reason is as follows.
You can get the Advanced Printer Driver of TM-T20II and manual & sample program here.
EPSON Advanced Printer Driver for TM-T20II
According to the sample program "Step 1 Printing Device Font", in order to send a raw ESC/POS command to the printer, it is necessary to select a specific device font.
Prints "Hello APD" with a device font and autocuts a receipt.
The core of the sample source in C ++ is as follows.
CDC dc;
/*
* Create the device context for the printer
*/
if(! dc.CreateDC(EPS_DRIVER_NAME, EPS_PRINTER_NAME, NULL, NULL) )
{
AfxMessageBox(_T("Printer is not available."));
return;
}
dc.StartDoc(&di);
/*
* Perform the printing of the text
*/
CFont font, *old;
font.CreatePointFont(95, "FontA11", &dc);
old = dc.SelectObject(&font);
dc.TextOut(20, 10, "Hello APD!");
dc.SelectObject(old);
font.DeleteObject();
dc.EndPage();
dc.EndDoc();
dc.DeleteDC();
Here's what it looks like in VB.
Dim printFont As New Font("Lucida Console", 8, FontStyle.Regular, GraphicsUnit.Point) ' Substituted to FontA Font
e.Graphics.PageUnit = GraphicsUnit.Point
' Print the string at 6,4 location using FontA font.
e.Graphics.DrawString("Hello APD!", printFont, Brushes.Black, 6, 4)
' Indicate that no more data to print, and the Print Document can now send the print data to the spooler.
e.HasMorePages = False
Isn't it very difficult or impossible to port these to Python's win32print?
The win32print API doesn't seem to have the ability to customize fonts in the middle of printing.
Module win32print
And StartDocPrinter and WritePrinter have the following explanation.
win32print.StartDocPrinter
Note that the printer driver might ignore the requested data type.
win32print.WritePrinter
Suitable for copying raw Postscript or HPGL files to a printer.
The ESC/POS command is not raw PostScript or HPGL, and EPSON's Advanced Printer Driver does not necessarily send such data with a win32print call.
Related
I'm developing a program to a shop. The program needs to print the receipt of the order using a termal printer.
I discovered that the printer follows the ESC/POS standard and I found out that there is a package that helps me having an interface with the printer caled python-esc/pos. However, to print throught a USB connected printer, I need to know the Vendor ID and Product ID. I've discovered a way to find this for all the connected printers on the sistem using the following code:
import usb
def is_printer(dev):
if dev.bDeviceClass == 7:
return True
for cfg in dev:
if usb.util.find_descriptor(cfg, bInterfaceClass=7) is not None:
return True
for printer in usb.core.find(find_all=True, custom_match = is_printer):
print('Decimal VendorID=' + str(printer.idVendor) + ' & ProductID=' + str(printer.idProduct) + '\n')
print('Hexadecimal VendorID=' + hex(printer.idVendor) + ' & ProductID=' + hex(printer.idProduct) + '\n\n')
However, I discovered that my client has multiple printers connected to his system. I want to be able to always print to the default printer. I would appreciate any help doing that since there are not many docs about default termal printers and all that
Edit: I should clarify that I do not have a thermal printer with me, so I'm working on the dark here, just hoping that it works in his hands.
I have light detector sensors connected to a data acquisition box and it is connected to my laptop via RS232 usb cable. I have stabilized serial communication to that port in python. But when I try to read the data it just keeps on running and it doesn't display any value. I have tried this same think in MATALB and it works properly, so I know that port and sensors are working fine. I am just not able to read the data in python. I have three ways(shown below in python code) but nothing works. Please help me.
Here is my python code:
import serial
from serial import Serial
s = serial.Serial('COM3') # open serial port
print(ser.name)
# Set the serial port to desired COM
s = serial.Serial(port = 'COM3', bytesize = serial.EIGHTBITS, parity = serial.PARITY_NONE, baudrate = 9600, stopbits = serial.STOPBITS_ONE)
# Read the data(method 1)
while 1:
while (s.inWaiting() > 0):
try:
inc = s.readline().strip()
print(inc)
# Read the data(method 2)
data = str(s.read(size = 1))
print(data)
# Read all the data(method 3)
while i <10:
b = s.readlines(100) # reading all the lines
in matlab it gave values with a space but in same line
That indicates there are no newline characters sent by the device.
I've never used your device or the Python serial module. But from the docs, this is what I would do:
from time import sleep
while s.is_open():
n = s.in_waiting()
if n == 0:
print "no data"
sleep(1)
continue
try:
inc = s.read(n)
print(inc)
catch serial.SerialException as oops:
print(oops)
catch serial.SerialTimeoutException as oops:
print(oops)
print("serial port closed")
This gives you feedback for each condition: port open/closed, data ready/not, and the data, if any. From there you can figure out what to do.
The documentation says inWaiting is deprecated, so I used in_waiting.
I wouldn't be surprised if the problem lies in configuring the serial port in the first place. Serial ports are tricky like that.
I would like to test some functions of my Märklin Digital model railway system. Basically it consists of a (Märklin) Central Unit and an (Märklin) Interface. This is the minimum configuration to send system commands from PC via ComPort to the Interface to set solenoids or control trains. Also information can be sent back from track detection modules via Interface ComPort to the PC. In this case two bytes are sent back. For this case an example in Basic is given in the instructions and I tried to translate it to Win Power Shell.
Basic example:
10 OPEN "COM1:2400,N,8,2"FOR OUTPUT AS #1
20 OPEN "COM1:2400,N,8,2"FOR INPUT AS #2
10 OPEN "COM1:2400,N,8,2"FOR OUTPUT AS #1
20 OPEN "COM1:2400,N,8,2"FOR INPUT AS #2
30 PRINT #1,CHR$(193);:a$=INPUT$(2,#2)
30 PRINT #1,CHR$(193);:a$=INPUT$(2,#2)
40 contact=ASC(LEFT$(a$,1)):PRINT contact
50 contact2=ASC(RIGHT$(a$,1)):PRINT contact2
My "translation":
$connectionproxy = new-object System.IO.Ports.SerialPort com1
$connectionproxy.BaudRate = 2400
$connectionproxy.stopbits = "two"
$connectionproxy.DataBits = 8
$connectionproxy.Parity = "None"
$connectionproxy.open()
do { $connectionproxy.write([char]([int]193)) $ShowBytes = $connectionproxy.ReadLine() Write-Host $ShowBytes } while($connectionproxy.IsOpen)
Problem: I am not able to safe in a file / show data which has been requested from the detection modules.
What is wrong / missing in my translation?
With some serious support (brother and a good friend) I can now deliver the requested functions. All functions have been tested with Märklin 6020/ 6023/6050/6088.
1.) "Windows 7 Power Shell", but without functionality of the Rückmeldemodul S88 (6088):
#---init command sets---
$commandset = #()
#---init connection---
$connectionproxy = new-object System.IO.Ports.SerialPort com1
$connectionproxy.BaudRate = 2400
$connectionproxy.stopbits = "two"
$connectionproxy.DataBits = 8
$connectionproxy.Parity = "None"
do {
$userimput = Read-Host -Prompt "Numbers seperated by space"
$currentcommand = $userimput.split(" ")
$connectionproxy.open()
for ($i=0;$i -lt $currentcommand.length;$i++) {
$connectionproxy.write([char]([int]$currentcommand[$i]))
start-sleep -milliseconds 10
}
$connectionproxy.close()
}while($true)
2.) "Ruby On Rails" for usage of Rückmeldemodul S88 (6088). This program reads the bytes sent back by S88 and shows its pin assignment:
require 'rubyserial'
class Integer
def to_bin(width)
'%0*b' % [width, self]
end
end
puts "open serial port..."
serialport = Serial.new "COM1", 2400, 8, :none, 2
puts serialport.inspect
puts "Reset command for S88:"
bytes_written = serialport.write 192.chr
puts bytes_written.to_s + " bytes written"
sleep(0.1)
puts "Read first S88:"
bytes_written = serialport.write 193.chr
puts bytes_written.to_s + " bytes written"
sleep(0.1)
b1 = serialport.getbyte.inspect
puts "Byte 1: " + b1 + " (" + b1.to_i.to_bin(8) + ")"
b2 = serialport.getbyte.inspect
puts "Byte 2: " + b2 + " (" + b2.to_i.to_bin(8) + ")"
Issue 1: Windows Power Shell is not able to recover any bytes upon request. If anyone knows a good solution, you are welcome to share it.
Issue 2: The Rückmeldemodul 6088 and its cable to the central station or interface have to be placed away from the rails, because of inteferences with the signals. (Shielding of the sixcore cable is absolutely miserable.)
I have been trying to send a value from a Python program via serial to an Arduino, but I have been unable to get the Arduino to store and echo back the value to Python. My code seems to match that I've found in examples online, but for whatever reason, it's not working.
I am using Python 3.5 on Windows 10 with an Arduino Uno. Any help would be appreciated.
Arduino code:
void readFromPython() {
if (Serial.available() > 0) {
incomingIntegrationTime = Serial.parseInt();
// Collect the incoming integer from PySerial
integration_time = incomingIntegrationTime;
Serial.print("X");
Serial.print("The integration time is now ");
// read the incoming integer from Python:
// Set the integration time to what you just collected IF it is not a zero
Serial.println(integration_time);
Serial.print("\n");
integration_time=min(incomingIntegrationTime,2147483648);
// Ensure the integration time isn't outside the range of integers
integration_time=max(incomingIntegrationTime, 1);
// Ensure the integration time isn't outside the range of integers
}
}
void loop() {
readFromPython();
// Check for incoming data from PySerial
delay(1);
// Pause the program for 1 millisecond
}
Python code:
(Note this is used with a PyQt button, but any value could be typed in instead of self.IntegrationTimeInputTextbox.text() and the value is still not receieved and echoed back by Arduino).
def SetIntegrationTime(self):
def main():
# global startMarker, endMarker
#This sets the com port in PySerial to the port with the Genuino as the variable arduino_ports
arduino_ports = [
p.device
for p in serial.tools.list_ports.comports()
if 'Genuino' in p.description
]
#Set the proper baud rate for your spectrometer
baud = 115200
#This prints out the port that was found with the Genuino on it
ports = list(serial.tools.list_ports.comports())
for p in ports:
print ('Device is connected to: ', p)
# --------------------------- Error Handling ---------------------------
#Tell the user if no Genuino was found
if not arduino_ports:
raise IOError("No Arduino found")
#Tell the user if multiple Genuinos were found
if len(arduino_ports) > 1:
warnings.warn('Multiple Arduinos found - using the first')
# ---------------------------- Error Handling ---------------------------
#=====================================
spectrometer = serial.Serial(arduino_ports[0], baud)
integrationTimeSend = self.IntegrationTimeInputTextbox.text()
print("test value is", integrationTimeSend.encode())
spectrometer.write(integrationTimeSend.encode())
for i in range(10): #Repeat the following 10 times
startMarker = "X"
xDecoded = "qq"
xEncoded = "qq"
while xDecoded != startMarker: #Wait for the start marker (X))
xEncoded = spectrometer.read() #Read the spectrometer until 'startMarker' is found so the right amound of data is read every time
xDecoded = xEncoded.decode("UTF-8");
print(xDecoded);
line = spectrometer.readline()
lineDecoded = line.decode("UTF-8")
print(lineDecoded)
#=====================================
spectrometer.close()
#===========================================
#WaitForArduinoData()
main()
First, this is a problem:
incomingValue = Serial.read();
Because read() returns the first byte of incoming serial data reference. On the Arduino the int is a signed 16-bit integer, so reading only one byte of it with a Serial.read() is going to give you unintended results.
Also, don't put writes in between checking if data is available and actual reading:
if (Serial.available() > 0) {
Serial.print("X"); // Print your startmarker
Serial.print("The value is now ");
incomingValue = Serial.read(); // Collect the incoming value from
That is bad. Instead do your read immediately as this example shows:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
That's two big issues there. Take care of those and let's take a look at it after those fundamental issues are corrected.
PART 2
Once those are corrected, the next thing to do is determine which side of the serial communication is faulty. Generally what I like to do is determine one side is sending properly by having its output show up in a terminal emulator. I like TeraTerm for this.
Set your python code to send only and see if your sent values show up properly in a terminal emulator. Once that is working and you have confidence in it, you can attend to the Arduino side.
I have a tplink-wr703n wireless router with OpenWrt.
I know I can capture all kinds of data when the adapter is in monitor mode.
I want to the adapter work in master mode, and I also want to capture probe request data sent from client or probe response data sent from my router.
I have tried to use libpcap to capture data, but I failed.
Can you tell me how I can get that data?
You can set up several modes on one radio card simultaneously.
Using the "iw" command you should be able to create a secondary wifi device interface with type monitor, I guess you could read all frame types from this one.
See http://wireless.kernel.org/en/users/Documentation/iw/vif/
I am also trying to prepare a scapy script to capture probe request only.
there is an Indian guy who made this nice video:https://www.youtube.com/watch?v=Z1MbpIkzQjU
His script seems to work in his enviroment but for some reason I cant get this to work for me.
I will appreciate your assistance.
The script is:
#!/usr/bin/python
import sys
from scapy.all import *
clientprobes = set()
def PacketHandler(pkt):
if pkt.haslayer(Dot11ProbeReq):
if len(pkt.info) > 0:
testcase = pkt.addr2 + '_ _ _' + pkt.info
if testcase not in clientprobes:
clientprobes.add(testcase)
print "New Probe Found: " + pkt.addr2 + ' ' + pkt.info
print "\n-----------Client Probes Table-------------\n"
counter = 1
for probe in clientprobes:
[client, ssid] = probe.split('---')
print counter, client, ssid
counter = counter + 1
print "\n--------------------------------------------\n"
sniff(iface = sys.argv[1], count = int(sys.argv[2]), prn = PacketHandler)