Is it possible to create a zpl file and send it to a thermal printer automatically from the report designer? The use case is that we need to print "tags" for our stock and serial items. We have a custom output report and need to be able to send that as a zpl file format to a tag printer.
Acumatica DeviceHub has a "raw mode" that's specially designed for label printers. I tested it extensively with Zebra printers and ZPL while working on the advanced fulfillment module.
A recent blog post by Sergey Marenich talks about DeviceHub; you will not find any information on how to use the raw mode, but it does explain the basics of Device Hub, print queues and how to send a job. Device Hub is now part of Acumatica 2018 R2 (it used to be available as a separate download with the advanced fulfillment pre-release module) and from the Source Code browser you can find quite a few examples of where it is used, including this one from SOShipmentEntry that works with labels. PX.SM.SMPrintJobMaint.CreatePrintJobForRawFile is the function you need to call.
if (lableFiles.Count > 0)
{
FileInfo mergedFile = MergeFiles(lableFiles);
if (upload.SaveFile(mergedFile))
{
if (PXAccess.FeatureInstalled<FeaturesSet.deviceHub>())
PX.SM.SMPrintJobMaint.CreatePrintJobForRawFile(adapter, new NotificationUtility(this).SearchPrinter, SONotificationSource.Customer, SOReports.PrintLabels, Accessinfo.BranchID, new Dictionary<string, string> { { "FILEID", mergedFile.UID.ToString() } },
PXMessages.LocalizeFormatNoPrefix(SOShipmentEntryActionsAttribute.Messages.PrintLabels, mergedFile.ToString()));
targetUrl = PXRedirectToFileException.BuildUrl(mergedFile.UID);
}
else
{
throw new PXException(Messages.FailedToSaveMergedFile);
}
}
Related
I have PAX A920 and i am trying to print receipt from chrome.
I wan to configure printer service in android for print receipt from my build in printer
I have write printer service for local printer and its is showing in preview, but I don't know how to configure build in printer.
This is code for local printer
final List<PrinterInfo> printers = new ArrayList<>();
final PrinterId printerId = generatePrinterId("Pax-printer:built-in");
Log.e("the", "the local printer id is " + printerId);
final PrinterInfo.Builder builder = new PrinterInfo.Builder(printerId, "POS Printer", PrinterInfo.STATUS_IDLE);
PrinterCapabilitiesInfo.Builder capBuilder = new PrinterCapabilitiesInfo.Builder(printerId);
capBuilder.addMediaSize(PrintAttributes.MediaSize.ISO_A6, true);
capBuilder.addMediaSize(PrintAttributes.MediaSize.ISO_A3, false);
capBuilder.addResolution(new PrintAttributes.Resolution("resolutionId", "default resolution", 600, 600), true);
capBuilder.setColorModes(PrintAttributes.COLOR_MODE_COLOR | PrintAttributes.COLOR_MODE_MONOCHROME, PrintAttributes.COLOR_MODE_COLOR);
builder.setCapabilities(capBuilder.build());
printers.add(builder.build());
addPrinters(printers);
I am also getting Document object
final PrintDocument document = printJob.getDocument();
but I can not utilize this document to set in customer printer, my customer printer accept payload of text and bitmap.
here is code for printing from PAX A920
PrintPayload payload = new PrintPayload();
payload.append(bmp).align(Alignment.CENTER);
print(payload);
How can i convert this document object to bitmap?
How can i configure build in printer with android PrintService
I hope I'm not too late.
If you take a look at this question, you would find some helpful code and insights into the way I've solved this very issue you were/are having. My solution was some kind of union between the code in this Zaki50 PrintService, and this Thermal Print Service Repo. If it is helping, you could comment to that affect, and I will post the behaviour from the answer to my question here as well, so that you would accept it as an answer.
I try to test my action in the Google Actions Simulator. Unfortunately, the simulator does not seems to recognize the difference between the phone surface and the smart speaker surface within the simulator.
I tried to console log the screentest variable. In the logs both the phone & speaker surface show 'true', which clearly is not correct. I also checked to 'conversation' data log. Both phone & speaker output contain SCREEN_OUTPUT.
app.intent('Default Welcome Intent', (conv) => {
let screentest = conv.available.surfaces.capabilities.has('actions.capability.SCREEN_OUTPUT')
console.log(screentest)
if (screentest === true) {
conv.add('Text with screen')
} else if (screentest === false) {
conv.add('Text without screen')
} else {
conv.add('impossible')
}
})
Expected results: when using the speaker surface inside the simulator, the output of the assistant should be 'Text without Screen'.
Actual results: Both phone & speaker surface inside the simulator generate the answer: 'Text with screen'.
The issue is that you're not quite checking for surfaces correctly.
There are two sets of capabilities reported:
The capabilities available on the surface the user is currently using. If you're using the actions-on-google library, these are available using conv.surface.capabilties.has()
The capabilities available on any surface that the user has connected to their account. These are available using conv.available.surfaces.capabilities.has() if you're using the actions-on-google library.
You're currently using the second one when you should be checking the first one to see what the user is currently using.
You'll want to use the second in case there is something that you want to display to make sure they can handle it before suggesting you switch to it.
I'm making a gym management web app that handles sign-ins. Members have a barcode on a tag that they scan when they arrive to the gym.
I've heard that most barcode scanners simply act as a keyboard. This would require the scanning-in page to be open and in the foreground when a barcode is scanned.
If it's just a keyboard, how would I send the barcode scanner input to a single background process running on the computer, and have it ignore by all processes that may be in focus?
You're right that most scanner can support HID in keyboard emulation, but that's just the start.
If you want to have a bit more control over the data you can use a scanners that support the OPOS driver model.
Take a look at Zebra's Windows SDK to have a overview of the things that you can do. It may be a better solution than try to steal the barcode data coming in the OS as a keyboard entry to the foreground app.
Disclaimer: I work for Zebra Technologies
Other Barcode scanner vendor support a similar driver model.
I found an interesting post with a simple solution:
On the form constructor
InitializeComponent():
this.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.Form1_KeyPress);
Handler & supporting items:
DateTime _lastKeystroke = new DateTime(0);
List<char> _barcode = new List<char>(10);
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
// check timing (keystrokes within 100 ms)
TimeSpan elapsed = (DateTime.Now - _lastKeystroke);
if (elapsed.TotalMilliseconds > 100)
_barcode.Clear();
// record keystroke & timestamp
_barcode.Add(e.KeyChar);
_lastKeystroke = DateTime.Now;
// process barcode
if (e.KeyChar == 13 && _barcode.Count > 0) {
string msg = new String(_barcode.ToArray());
MessageBox.Show(msg);
_barcode.Clear();
}
}
Credits: #ltiong_sh
Original post: Here
Use RawInput API (https://www.codeproject.com/Articles/17123/Using-Raw-Input-from-C-to-handle-multiple-keyboard#_Toc156395975) and check device ID for incoming keystrokes. Different devices have different IDs. You can also block keystrokes from scanner from reaching your application and interfering with input fields.
One thing you might want to add is option for user to identity which device is used as a barcode scanner. I did it by asking user to test-scan barcode with scanner on first application startup or in settings.
Works with any barcode scanner which outputs keystrokes.
I just noticed that the tabs API is only available for the desktop not for Android. In the past I have used this code to send messages to my content scripts:
sendMsgToTabs(msg) {
return browser.tabs.query({}).then(tabs => {
let msgPromises = []
for (let tab of tabs) {
let msgPromise = browser.tabs.sendMessage(tab.id, msg)
msgPromises.push(msgPromise)
}
return Promise.all(msgPromises)
})
}
But how am I supposed to do that when the tabs API is not available?
I mean the only thing I can think of is to constantly send empty messages from the content scripts to the background script and whenever the background script has new information then it can send a direct response to one of these messages. But that sounds horribly inefficient. There must be a better way, right?
As of Firefox 54, use .tabs.sendMessage()
As of Firefox 54, the tabs API is supported on Firefox for Android.
Alternative for versions of Firefox prior to Firefox 54.
The storage API is stated as supported in Firefox for Android. Thus, while I have not tested it, a method you could use to send data to content script would be to save a value using chrome.storage.local.set(). By listening to the chrome.storage.onChanged event in your content script(s), you can then be notified of that data being stored/changed. This will provide an event driven way to send a message (i.e. stored data) to the content script.
In order to differentiate between receiving the data in different tabs, you will need to establish a protocol for what the data you save means. This could be as simple as just a particular saved key/value meaning that all content scripts should send a message to the background script to get more information, or more complex where you send/store something like:
{
contentScriptMessage: {
tab: 14,
frame: 1234,
message: 'Some data'
}
}
In each content script's chrome.storage.onChanged listener, it can then ignore any changes that are not to the tab/frame in which it is running.
This methodology will require fleshing out as you try to implement it. Hopefully, at least part of the chrome.tabs API will be implemented for Android in the near future.
I have a document library setup to recieve emails. The emails coming in have a single picture and a csv file which I use for some processing.
The override emailrecieved works perfectly but of course as I override I lose the nice SharePoint functionaliy that saves the incomming email as configured in the settings.
It was my understanding that I could call MyBase.EmailRecieved in my event for the underlying functionality to still work. This however is not working and no record of the email coming in is getting retained.
For now I am explicitly creating an audit trail but I would like to rely on SharePoints existing functionality as I believe it will be more robust.
What am I doing wrong with the MyBase.EmailRecieved call? Or what can I do instead if this doesnt work?
Thanks in advance.
When writing your own EmailReceived event receiver you will loose the default functionality.
What you will have to do is to implement this default functionality yourself. Let me give you a simple example. The following example saves all mail attachments to the list if they are *.csv files. You can do the same with the emailMessage and save it to the list as well. As you can see it is as easy as to add Files.Add to add a file to a document library.
public override void EmailReceived(SPList list, SPEmailMessage emailMessage, string receiverData)
{
SPFolder folder = list.RootFolder;
//save attachments to list
foreach (SPEmailAttachment attachment in emailMessage.Attachments)
{
if (attachment.FileName.EndsWith(".csv"))
{
var attachmentFileName = attachment.FileName;
folder.Files.Add(folder.Url + "/" + attachmentFileName, attachment.ContentStream, true);
}
}
list.Update();
}