问题
I am trying to programatically configure a Zebra QLn220 printer to set its "media.sense_mode" to either "bar" or "gap" (depending on what the user selects).
The reliability of these commands working, though, seems very low (sometimes it works, sometimes it doesn't).
To test the various possible commands, I used the Zebra Setup Utilities, with the PC plugged into the printer, of course.
I sent this command from the util:
! U1 setvar "media.sense_mode" "gap"
It worked; I know this, because testing it with:
! U1 getvar "media.sense_mode"
...showed me the expected/hoped for "gap" (it had been "bar" prior to sending the command above).
But trying to accomplish the same thing in code works for "bar" (almost always) but hardly ever for "gap"
Here's the code:
const string quote = "\"";
string advanceToBlackBar = string.Format("! U1 setvar {0}media.sense_mode{0} {0}bar{0}\r\n", quote);
string advanceToGap = string.Format("! U1 setvar {0}media.sense_mode{0} {0}gap{0}\r\n", quote);
. . .
if (radbtnBar.Checked)
{
PrintUtils.SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
PrintUtils.SendCommandToPrinter(advanceToGap);
}
So as you can see, the code is precisely the same except for "bar" vs. "gap"
Is it possible that the appended "\r\n" is causing a problem? It seems adding those were necessary or made the commands more reliable, but I'm open to anything at this point of frustration.
I always tested alternative commands for accomplishing the same thing, to see if they would be any more reliable, but neither of the other two alternatives worked, namely not this one:
! U1 setvar "ezpl.media_type" "web"
-nor this one:
{} {"media.sense_mode" "gap"}
...checking the val via getvar continued to show "bar" following the sending of those commands to the printer (after setting back to "bar" the value of "media.sense_mode" remains "bar" after sending these two commands).
Might it be that certain other printer settings need to be set for the printer to be more responsive to commands sent it? Not only is setting the commands programmatically unreliable, but even via the Zebra Setup Utility, it will sometimes "hourglass" for a LONG time before the command has been sent and returns - and other times it's quicker than Johnny Quick and Flash combined.
Looking through the voluminous output of this command:
! U1 getvar "allcv"
....the following are the most interesting/likely candidates. Which, if any, need to be changed, and to what values?
wlan.ip.dhcp.request_timeout : 2 , Choices: 2-30
wlan.ip.dhcp.session_interval : 10 , Choices: 0-60
. . .
wlan.ip.timeout.enable : on , Choices: on,off
wlan.ip.timeout.value : 300 , Choices: 1-3600
. . .
wlan.keep_alive.enable : on , Choices: on,off
wlan.keep_alive.timeout : 15 , Choices: 5-300
. . .
netmanage.avalanche.interval : 60000 , Choices: 0-4294967295
netmanage.avalanche.startup_update : off , Choices: on,off
netmanage.avalanche.interval_update : off , Choices: on,off
. . .
netmanage.avalanche.udp_timeout : 3000 , Choices: 0-4294967295
netmanage.avalanche.tcp_connection_timeout : 3000 , Choices: 0-4294967295
. . .
netmanage.avalanche.realtime_update_int : 300 , Choices: 0-4294967295
. . .
zpl.zpl_mode : zpl II , Choices: zpl II,zpl
. . .
internal_wired.ip.arp_interval : 0 , Choices: 0-30
. . .
internal_wired.ip.dhcp.requests_per_session : 2 , Choices: 1-10
internal_wired.ip.dhcp.request_timeout : 2 , Choices: 2-30
internal_wired.ip.dhcp.session_interval : 10 , Choices: 0-60
. . .
internal_wired.ip.timeout.enable : on , Choices: on,off
internal_wired.ip.timeout.value : 300 , Choices: 1-3600
. . .
internal_wired.ip.wins.permanent_source : off , Choices: on,off
. . .
interface.network.active.arp_interval : 0
. . .
interface.network.active.speed : 0
. . .
weblink.printer_reset_required : no
. . .
weblink.ip.conn1.retry_interval : 10 , Choices: 1-600
. . .
weblink.ip.conn1.maximum_simultaneous_connections : 10 , Choices: 1-100
. . .
weblink.ip.conn1.test.retry_interval : 900 , Choices: 1-1800
weblink.ip.conn1.num_connections : 0
. . .
capture.channel1.port : off , Choices: serial,usb,bt,parallel,off
capture.channel1.count : 0 , Choices: 0-4294967295
Anyone out there with a clue?
UPDATE
Here is the code that sends the commands:
public static bool SendCommandToPrinter(string cmd)
{
bool success; // init'd to false by default
try
{
using (SerialPort serialPort = new SerialPort())
{
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
serialPort.Close(); // <= should be redundant within a using statement, but still getting "File 55" err...
}
success = true;
}
catch // may not need a try/catch block, as success defaults to false
{
success = false;
}
MessageBox.Show(success.ToString()); //TODO: Remove after testing
return success;
}
The SerialPort in question is from OpenNETCF.IO.Ports.SerialPort
NOTE: SerialPort.Write() returns void.
The command:
! U1 getvar "appl.name"
returns "V68.19.7Z" in the Zebra Setup Utility.
So does this mean my firmware is up-to-date (V68.19.7Z > v68.18.0Z), or does it mean since my "appl" is newer, I need to upgrade the firmware to V68.19.7Z? If I do need to update the firmware, how do I do that? Is it a matter of locating and downloading the latest firmware to my PC, then running its install app while the PC and Printer are connected via USB, or...???
UPDATE 2
From here, searching for QLn220, I see V68.18.0Z as the only firmware version available for download. So since I seem to have a newer version on my printer, I'm confused...why do they not offer what would seem to be the newer version (V68.19.7Z)?
UPDATE 3
If I click the "self-extracting archive" link at the page referenced above, I simply get a page with some generic but unactionable (so it seems) directions.
If I click the download link there, I get a page that says, "This webpage has a redirect loop"
UPDATE 4
It works after adding some debug strings; in the print code:
MessageBox.Show(success.ToString()); //TODO: Remove after testing
return success;
...and in the setting code:
if (radbtnBar.Checked)
{
MessageBox.Show(advanceToBlackBar);
PrintUtils.SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
MessageBox.Show(advanceToGap);
PrintUtils.SendCommandToPrinter(advanceToGap);
}
Could it be that this little "break in the action" is beneficial somehow?
UPDATE 5
Note: There is no "SerialPort.Flush" Maybe:
serialPort.Close();
...is accomplishing the same thing?
回答1:
The SGD commands are well-formed. The intermittent behavior that you describe makes me think the problem originates in how consistently the printer actually receives the command, and not the syntax of the command itself. And generally speaking, no, you do not have to change other commands in order to make this command work. Since you can successfully send the command via Zebra Setup Utilities and get the desired behavior, then you should be able to do the same through your code.
Are you programmatically sending the commands over USB or over something else (Bluetooth, TCP, etc.)? You mentioned USB while using Zebra Setup Utilities, but what about in your code?
Can you provide the code underneath the hood of PrintUtils.SendCommandToPrinter()? I am not familiar with this API. Which API is it?
At the lowest levels of a connection you will often be calling 'write()' or 'writeData()' or something like that. Sometimes 'write' commands return the number of bytes written. If you can dig into your code a bit, perhaps there is a 'write' command that returns that value and you can verify yourself that the return value equals the length of the intended message (including new line characters).
Depending on the lower level API, there also may be a flush() command lying around that forcibly pushes all data in a stream to the other end. Again, this depends on what API you're using underneat the hood of 'PrintUtils'.
In the past I have seen inconsistent behavior with USB communication. You should make sure that your firmware is as up-to-date as possible. Your QLn220 is currently on v68.18.0Z: http://www.zebra.com/id/zebra/na/en/index/drivers_downloads/firmware/results.html?productType=6. You can check your current version by sending:
! U1 getvar "appl.name"
At the end of the day, you could always immediately query the printer for its gap/bar mode after setting it. This will cause as an additional delay in your program execution, but it is a good way of making sure that whatever you sent has actually taken effect.
回答2:
for those with issues with labels printing too long, we had to set all our printer widths correctly via the zebra pc util.. send these commands to the printer.. PW means printer width, and JUS means Save the settings...
^XA
^PW832
^JUS
^XZ
Also this command helped with double labels printing
Sensor Calibration Command (source: Functional List of ZPL Commands) zpl_manual.pdf
~JC
回答3:
It works after adding some debug strings; in the print code:
MessageBox.Show(success.ToString()); //TODO: Remove after testing
return success;
...and in the setting code:
if (radbtnBar.Checked)
{
MessageBox.Show(advanceToBlackBar);
PrintUtils.SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
MessageBox.Show(advanceToGap);
PrintUtils.SendCommandToPrinter(advanceToGap);
}
WHY it works, I don't know, so I'm still wary. But, for now at least, it is working with this tweak.
来源:https://stackoverflow.com/questions/25070743/what-zebra-qln220-settings-do-i-need-to-set-and-to-what-values-to-get-a-sett