I am using .NET CF and my task is to print fiscal and non-fiscal receipt.
So I need to connect to the FML 10 KL via bluetooth.
I am using SerialPort to do this, but after sending commands nothing happens.
I tried sending the commands like this :
byte[] buf = new byte[218];
using (StreamWriter writer = new StreamWriter(inPort.BaseStream))
{
writer.Write(buf);
//inPort.NewLine = "\n";
//var msg = inPort.ReadLine();
}
I populate "buf" with my command.
After that I try to read the responce but everytime I get timeout.Also I tried to "write" with text and not byte array, but I get the same result.
If anyone can give me some advice that would be great.
Most serial devices including Bluetooth SPP and Socket controlled devices do not support Unicode. If you have a string, you need to use Encoding ASCII (or UTF8) getBytes to get a byte arry suitable for the serial or direct socket connection. If you do not care for this, you may get a byte sequence of {0x00, 0x41} (Unicode) for an 'A' instead of the needed {0x41} only.
If you try to print something, verify that the code you send is valid by writing the data to a file and send the file as it is using a terminal application (former HyperTerminal).
Most printers support a Dump mode. Verify that the code you build is transmitted un-altered to the printer by using the dump mode and compare with the validated code that you used to print.
The Operating System and the target device may use a buffer. Ensure the buffer is flushed and then close the Stream before disconnecting.
With the Serial Port class ensure the device and the class use the same parameters, ie both 8Bit etc. For Bluetooth SPP the baud rate is adopted, you may use 115200 or 57600 without failing.
I found a Class that supports the Datecs Fiscal Printing Protocol: https://github.com/wqweto/UcsFiscalPrinters/blob/master/Samples/Demo1/Program.cs you should probably use this or look at how the class does print on the Datecs.
I figured out my problem.It was the connection to the mobile printer.
I am connecting and writing like this:
SerialPort inport = new SerialPort("COM5", 115200, Parity.None, 8,
StopBits.One);
inport.Write(buf, 0, buf.Length);
Thread.Sleep(1000);
I need to use Thread.Sleep because the buffer is getting full and some of data is not getting printed.
Related
I need to display a live video stream in a UWP application.
The video stream comes from a GoPro. It is transported by UDP messages. It is a MPEG-2 TS stream. I can play it successfully using FFPlay with the following command line :
ffplay -fflags nobuffer -f:v mpegts udp://:8554
I would like to play it with MediaPlayerElement without using a third party library.
According to the following page :
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/supported-codecs
UWP should be able to play it. (I installed the "Microsoft DVD" application in the Windows Store).
I receive the MPEG-2 TS stream with a UdpClient. It works well.
I receive in each UdpReceiveResult a 12 bytes header, followed by 4, 5, 6, or 7 MPEGTS packets (each packet is 188 bytes, beginning with 0x47).
I created a MseStreamSource :
_mseStreamSource = new MseStreamSource();
_mseStreamSource.Opened += (_, __) =>
{
_mseSourceBuffer = _mseStreamSource.AddSourceBuffer("video/mp2t");
_mseSourceBuffer.Mode = MseAppendMode.Sequence;
};
_mediaPlayerElement.MediaSource = MediaSource.CreateFromMseStreamSource(_mseStreamSource);
This is how I send the messages to the MseStreamSource :
UdpReceiveResult receiveResult = await _udpClient.ReceiveAsync();
byte[] bytes = receiveResult.Buffer;
mseSourceBuffer.AppendBuffer(bytes.AsBuffer());
The MediaPlayerElement displays the message "video not supported or incorrect file name". (not sure of the message, my Windows is in French).
Is it a good idea to use the MseAppendMode.Sequence mode ?
What should I pass to the AppendBuffer method ? The raw udp message including the 12 bytes header or each MPEGTS 188 bytes packet ?
I finally got the video working !
Here are the steps I follow to extract the MPEG-TS packets and correctly send them to the MseStreamSource :
The MseSourceBuffer needs to be in "Sequence" mode :
_mseSourceBuffer.Mode = MseAppendMode.Sequence;
For each received UDP datagram, I extract the MPEG-TS packets. To do that, I ignore the first 12 bytes of the UDP datagram. Then I extract each 188 bytes packet in a separate array (each packet starts with 0x47).
I send each packet to a synchronized queue.
I dequeue the packets from the queue and send them grouped to the MseSourceBuffer. I create a new group for each PAT packet (pid = 0) :
byte[] bytes;
// [...] combine the packets of the group
mseSourceBuffer.AppendBuffer(bytes.AsBuffer());
I tried to use a MemoryStream and call the AppendStream() method, but with no success.
Also care about threads synchronization : packets order should not be lost. That is the reason for the synchronized queue.
Hope it can help someone else.
This wikipedia MPEG-TS page helped me a lot.
Using the simple serial program created awhile back(http://csharp.simpleserial.com/) but I am having trouble sending ASCII control commands to my serial device. I need to send: 01P00104##. Is there a certain way to modify the code so that it sends out these “ASCII unprintable character commands” for C#?
I tried:
private void linkLabel_HC1_100_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
if serialPort1.IsOpen()
{
serialPort1.Write( (char)2 + “01P00104##” + (char)3);
}
}
Where (char)2 and (char)3 are supposedly the character representations for the start and end of text commands. I also tried using escape codes such as \u0002 or even sendKeys.Send(“^(b)”) or ^(c) but it wont seem to work. When I use Hyperterminal or PuTTy software, I can copy and past the full command in from a notepad.txt file and it sends correctly but when I copy and past the same code into this application, I don’t get a response from the serial device. This app uses .net 2.0. The stx and etx commands in the notepad look like a small 7 and small L
You could use the SerialPort.Write(Byte[], Int32, Int32) method.
var content = new List<byte>();
content.Add(2); // ASCII STX
content.AddRange(Encoding.ASCII.GetBytes("01P00104##"));
content.Add(3); // ASCII ETX
byte[] buffer = content.ToArray();
serialPort1.Write(buffer, 0, buffer.Length);
I'm trying to send a file to print without opening it trough Adobe as suggested by several Answers here; instead, I'm using the PrintQueue library (from System.Drawing.Printing).
What I've accomplished so far:
I have the correct PrintQueue referenced as pq:
PrintQueue pq; //Assume it's correct. The way to get here it isn't easy and it is not needed for the question.
// Call AddJob
PrintSystemJobInfo myPrintJob = pq.AddJob();
// Write a Byte buffer to the JobStream and close the stream
Stream myStream = myPrintJob.JobStream;
Byte[] myByteBuffer = ObjectIHave.ToArray(); //Ignore the ObjectIhave, it actually is Linq object which is correct as well.
myStream.Write(myByteBuffer, 0, myByteBuffer.Length);
myStream.Close();
As I understood from the Microsoft Library it's correctly done but it is not working. Any ideas?
EDIT: Debugging the code I can see that something is being send to the printer but it seems the file is not sent.
You need to render your PDF to the printer. Calling the shell print verb on the file would be the ideal means to do that. If you insist on doing the low level rendering yourself then I recommend using a library like Ghostscript.NET and choose the mswinpr2 device as output.
The mswinpr2 device uses MS Windows printer drivers, and thus should work with any printer with device-independent bitmap (DIB) raster capabilities. The printer resolution cannot be selected directly using PostScript commands from Ghostscript: use the printer setup in the Control Panel instead.
See SendToPrinterSample.cs for example:
string printerName = "YourPrinterName";
string inputFile = #"E:\__test_data\test.pdf";
using (GhostscriptProcessor processor = new GhostscriptProcessor())
{
List<string> switches = new List<string>();
switches.Add("-empty");
switches.Add("-dPrinted");
switches.Add("-dBATCH");
switches.Add("-dNOPAUSE");
switches.Add("-dNOSAFER");
switches.Add("-dNumCopies=1");
switches.Add("-sDEVICE=mswinpr2");
switches.Add("-sOutputFile=%printer%" + printerName);
switches.Add("-f");
switches.Add(inputFile);
processor.StartProcessing(switches.ToArray(), null);
}
If the file has to be printed in both sides you just need to add:
switches.Add("-dDuplex");
switches.Add("-dTumble=0");
You can not just write PDF bytes to a print job. The printer doesn't know how to handle it. The RAW data you send to the printer must describe the document in a printer language specific to the printer. That's what the printer driver does.
You can not print a PDF by just sending it to the printer. You need some piece of software that renders the PDF and then sends the rendered image to the printer.
As the documentation states:
Use this method to write device specific information, to a spool file, that is not automatically included by the Microsoft Windows spooler.
I enhanced the important part of this information.
I must send a Font file to my printer Zebra RW420 via bluetooth. Im using Zebra Windows Mobile SDK, but can't find any way to send and store it on printer. I could do it manually by Label Vista but It must be done in 200+ printers.
Anyone have any suggestion or know what method from the SDK I could use?
Thanks in advance.
CISDF is the correct answer, it's probably the checksum value that you are computing that is incorrect. I put a port sniffer on my RW420 attached to a USB port and found this to work. I actually sent some PCX images to the printer, then used them in a label later on.
! CISDF
<filename>
<size>
<cksum>
<data>
There is a CRLF at the end of the 1st four lines. Using 0000 as the checksum causes the printer to ignore any checksum verification (I found some really obscure references to this in some ZPL manuals, tried it and it worked). <filename> is the 8.3 name of the file as it will be stored in the file system on the printer and <size> is the size of the file, 8 characters long and formatted as a hexadecimal number. <cksum> is the two's complement of the sum of the data bytes as the checksum. <data> is, of course, the contents of the file to be stored on the printer.
Here is the actual C# code that I used to send my sample images to the printer:
// calculate the checksum for the file
// get the sum of all the bytes in the data stream
UInt16 sum = 0;
for (int i = 0; i < Properties.Resources.cmlogo.Length; i++)
{
sum += Convert.ToUInt16(Properties.Resources.cmlogo[ i]);
}
// compute the two's complement of the checksum
sum = (Uint16)~sum;
sum += 1;
// create a new printer
MP2Bluetooth bt = new MP2Bluetooth();
// connect to the printer
bt.ConnectPrinter("<MAC ADDRESS>", "<PIN>");
// write the header and data to the printer
bt.Write("! CISDF\r\n");
bt.Write("cmlogo.pcx\r\n");
bt.Write(String.Format("{0:X8}\r\n", Properties.Resources.cmlogo.Length));
bt.Write(String.Format("{0:X4}\r\n", sum)); // checksum, 0000 => ignore checksum
bt.Write(Properties.Resources.cmlogo);
// gracefully close our connection and disconnect
bt.Close();
bt.DisconnectPrinter();
MP2Bluetooth is a class we use internally to abstract BT connections and communications - you have your own as well, I'm sure!
You can use the SDK to send any kind of data. A Zebra font is just a font file with a header on it. So if you capture the output cpf file from Label Vista, you can send that file from the SDK. Just create a connection, and call write(byte[]) with the contents of the file
How can a C# app easily communicate with an instance of itself present on another computer, which is on the same network, and transfer files and data?
Assuming the computers on the network have fixed local IP addresses, and they each know each others IPs. Would there also be a way to communicate if the IPs are unknown? based on some discovery protocol?
I heard the "Bonjour" service from Apple was a good protocol. Can we communicate via it from our Windows apps? Or do you have to use "sockets". I'm primarily looking for libraries or sample code that can fulfill my need easily, I don't want to develop my own TCP-based protocol or anything hardcore!
You can use System.Net.Sockets class to communicate and it have a method for sending file Socket.SendFile.
Update:
this is a good example for file sharing and sending file from C# help
The great thing about files and sockets in C# is that they're both exposed as streams. Copying a large file from one stream to another is pretty simple:
byte[] data = new byte[1024];
while(true) {
int bytesRead = filestream.read(data,0,data.Length);
if (bytesRead==0) break;
netstream.write(data,0,bytesRead);
}
Then just close the socket when you're done.
If you want to send metadata (filenames, sizes) or don't want to close the connection, you need some sort of protocol to handle this. FTP uses two seperate sockets(one for metadata, one for data; this is called out-of-band communication). If you're on a LAN with no firewalls, that can be perfectly acceptable. On the other hand, if you want to do internet transfer, getting a single port open is a difficult-enough task, and two is unbearable. If you don't care too much about performance, you could encode the bytes in base64 encoding, which makes sure that they're within a certain byte range. With base64, you can seperate messages with newlines or other non-alphanumeric characters. Then in the first message include the filename, size, or whatever, then send the data as a second message, then send a "that's the whole file" message so the client knows it's done.
Another tactic for messages is using an escape sequence. For instance, take your bytestream and replace each instance of '\0' with '\0\0'. Now use '\0\1' to signal the end-of-message, which is guaranteed not to be contained in your data message. Decode the '\0\0' back to '\0' on the receiving end. This works well enough in C, but I find that, in practice, looping through each byte can be slower than reading whole buffers in C#.
The best way is to adopt some sort of adaptive-length protocol. For instance, send the data in chunks of a certain size (say 512 bytes). Before each chunk, send a 32bit int representing the size of the chunk via System.BitConverter. So messages look like this (english):
Here's 512 bytes:
[data]
Here's 512 bytes:
[data]
Here's 32 bytes:
[data]
Here's 4 bytes:
That was the whole file
The advantage here is that you can make the copy/read buffers work for you (reading 512 bytes at a time), meaning your throughput is limited by your network stack instead of your C# code. The client reads the fixed-length 32-bit int that lets it know the size of the buffer it should use for the next [data] segment.
Here's some code to write messages like that:
logger.logger.debug("Sending message of length " + length);
byte[] clength = System.BitConverter.GetBytes(buffer.Length);
plaintextStream.Write(clength,0,clength.Length);
plaintextStream.Write(buffer,0,buffer.Length);
plaintextStream.Flush();
And here's some code to read them:
byte[] intbuf = new byte[int_32_size];
int offset = 0;
while (offset < int_32_size)
{
int read = 0;
read = d.plaintextStream.Read(intbuf,offset,int_32_size - offset);
offset += read;
}
int msg_size = System.BitConverter.ToInt32(intbuf,0);
//allocate a new buffer to fill the message
byte[] msg_buffer = new byte[msg_size];
offset = 0;
while (offset < msg_size)
{
int read = 0;
read = d.plaintextStream.Read(msg_buffer,offset,msg_size - offset);
offset += read;
}
return msg_buffer;
For transferring the files / data, you can use the TcpClient/TcpListener classes, which is nice abstractions over the grittier socket functionality. Or, you could simply have the application as a HTTP server using the HttpListener class, if that is easier/more appropiate for your application.
For discovery, if you are able to have a central server; then you could have each client connect to the server at startup, to register itself and retrieve a list of other online clients and their IP's. Subsequent communication can then take place directly between the clients.
A variation of this scheme, is to let the central server act as a proxy, which all traffic between the clients flow through. This would be mostly helpful to overcome firewall or routing issues if the clients is not on the same network (so it's propably not needed for your scenario).
To copy files you may also want to look at File Synchronization Provider that is part of Microsoft Sync Framework. http://msdn.microsoft.com/en-us/sync/bb887623.