I write commands to a belt printer using OpenNETCF.IO.Ports.SerialPort this way:
public static bool SendCommandToPrinter(string cmd)
{
bool success; // init'd to false by default
try
{
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
serialPort.Close();
success = true;
}
catch // may not need a try/catch block, as success defaults to false
{
success = false;
}
return success;
}
...now I need to read a value returned from a "get val" call, but I don't know how, and I haven't been able to find how, to do that. I have the following start, but don't know how to "fill in the blank":
string getDeviceLang = string.Format("! U1 getvar {0}device.languages{0}", quote);
public static string GetSettingFromPrinter(string cmd)
{
string settingVal = string.Empty;
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd); // do I even need this call to write?
settingVal = serialPort.Read() // ???
serialPort.Close();
return settingVal;
}
OpenNETCF.IO.Ports.SerialPort's Read() method takes an array of bytes ("buffer"), followed by an int ("offset") and another int ("count"), and returns an int. I don't know what to use as args or what to do with the result int.
I tried this:
public static string GetSettingFromPrinter(string cmd)
{
string settingVal = string.Empty;
try
{
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
// testing...
settingVal = serialPort.ReadLine();
serialPort.Close();
return settingVal;
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
return settingVal;
}
}
...but that rewards me with the less-than-satisfactory, "System.NotSupportedException: not yet at OpenNETCF.IP.Ports.SerialPort.ReadTo(String value) at..."
I added this:
serialPort.ReadTimeout = 500;// made no difference
Based on this, I tried to get it to work this way:
public class PrintUtils
{
static SerialPort _serialPort;
static bool keepReading = true;
static string settingVal = string.Empty;
. . .
public static string GetSettingFromPrinter(string cmd)
{
Thread readThread = new Thread(ReadSetting());
try
{
_serialPort = new SerialPort();
_serialPort.BaudRate = 19200;
_serialPort.Handshake = Handshake.XOnXOff;
_serialPort.Open();
while (keepReading)
{
_serialPort.WriteLine(cmd);
}
_serialPort.Close();
return settingVal;
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
return settingVal;
}
}
public static void ReadSetting()
{
while (keepReading)
{
try
{
settingVal = _serialPort.ReadLine();
keepReading = settingVal.Equals(string.Empty);
}
catch (Exception ex) { MessageBox.Show(ex.ToString());}
}
}
...but I get, "Method 'PDAClient.PrintUtils.Read()' referenced without parentheses" on this line:
Thread readThread = new Thread(Read);
If I do give it parens:
Thread readThread = new Thread(ReadSetting());
...it tells me, "Argument '1': cannot convert from 'void' to System.Threading.ThreadStart'"
-and:
"The best overloaded method match for System.Threading.Thread.Thread(System.Threading.ThreadStart)' has some invalid arguments"
And with this code:
public static string GetSettingFromPrinter(string cmd)
{
string setting = string.Empty;
byte[] buffer = null;
try
{
SerialPort serialPort = new SerialPort();
serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.ReadTimeout = 500;
serialPort.Open();
serialPort.Write(cmd);
setting = Convert.ToString(serialPort.Read(buffer, 0, buffer.Length));
serialPort.Close();
return setting;
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
return setting;
}
}
I get an NRE.
This attempt:
serialPort.WriteLine(cmd);
setting = serialPort.ReadExisting();
...ends very similary to the first Update ("System.NotSupportedException: not yet at OpenNETCF.IP.Ports.SerialPort.ReadExisting() at...")
Okay, I incorporated the pseudocode in ctacke's comment, and so now I've got this:
const string quote = "\"";
. . .
string getDeviceLang = string.Format("! U1 getvar {0}device.languages{0}", quote);
. . .
String deviceLanguage = PrintUtils.GetSettingFromPrinter(getDeviceLang);
public static string GetSettingFromPrinter(string cmd)
{
string setting = string.Empty;
try
{
SerialPort serialPort = new SerialPort();
serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.ReadTimeout = 500;
serialPort.Open();
serialPort.WriteLine(cmd); // or Write()
// get a synchronous, newline-delimited response
StringBuilder response = new StringBuilder();
char c;
do
{
c = (char)serialPort.ReadByte();
response.Append(c);
} while(c != '\n');
serialPort.Close();
return setting;
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
return setting;
}
...but it "hangs" - there seems to be an infinite loop in the do...while loop.
I added this after the "ReadByte":
MessageBox.Show(c.ToString());
...and all it shows me is nothing (a MessageBox with no "inner text"); I let it pop up 32 times before I warm-booted the device.
Okay, then, I stand corrected - I was not using the OpenNETCF SerialPort, as there is no such thing. So I am trying to and have this, based on the pseudocode ctacke provided. I'm now trying to use:
Port serialPort = new Port();
serialPort.Settings = whateverPortSettingsYouNeed;
serialPort.Open();
serialPort.Send(cmd);
...but I don't know what "whateverPortSettingsYouNeed" should be, there is not "Send" method, and I don't know what to use in place of ReadByte()
I have this now for settings:
BasicPortSettings bps = new BasicPortSettings();
bps.BaudRate = 19200;
//bps.ByteSize = ?;
//bps.Parity = None;
//bps.StopBits = 1;
Port serialPort = new Port();
serialPort.Settings = bps;
...but, as you can see, I don't know what most of the values should be.
This compiles:
public static string GetSettingFromPrinter(string cmd)
{
string setting = string.Empty;
try
{
BasicPortSettings bps = new BasicPortSettings();
bps.BaudRate = BaudRates.CBR_19200;
bps.Parity = OpenNETCF.IO.Serial.Parity.none;
bps.StopBits = OpenNETCF.IO.Serial.StopBits.one; //bps.StopBits.one;
Port serialPort = new Port("COM1:", bps);
byte[] outputBytes = System.Text.Encoding.ASCII.GetBytes(cmd);
serialPort.Output = outputBytes;
serialPort.Open();
byte[] bites = serialPort.Input;
setting = bites.ToString();
serialPort.Close();
return setting;
}
catch (Exception x)
{
MessageBox.Show(x.ToString());
return setting;
}
}
...Now I'll see if it actually works...
I found out (the hard way) that I had to Open the port before setting the Output val; it's now:
serialPort.Open();
byte[] outputBytes = Encoding.ASCII.GetBytes(cmd);
serialPort.Output = outputBytes;
byte[] inputBytes = serialPort.Input;
setting = inputBytes.ToString();
...but what is read into setting is "System.Byte[]"
What do I need to actually get at the value in inputBytes, rather than just see a representation of its type?
The first thing I notice is that you're using a class called SerialPort
which means you're using code from SDF 1.x which dates to circa 2005 at the most recent. Not sure I'd be overly enthused about that. I created an open source library that contains just a Port
class after that code but it works way different - it was modeled after the VB6 serial port object model. I honestly don't even recall who wrote the code in SDF 1.x - might have been me, might not have. I think not just judging by the code style I see.
I was going to question why you didn't just use the built-in CF serial stuff, but if you're using SDF 1.x, you're likely using a CF version that pre-dates inclusion of a serial port API.
As for the one you're using now, I would think that it somewhat depends on how the data coming back is expected, but the pseudocode would look something like this:
var port = new SerialPort;
port.Settings = whateverPortSettingsYouNeed;
port.Open();
....
// send the command
port.Send(myCommand);
// get a synchronous, newline-delimited response
var response = new StringBuilder();
char c;
do
{
c = (char)port.ReadByte();
// see if it actually read anything
if(c == '\0')
{
// wait a little bit, then try again - you will want to put in a timeout here
Thread.Sleep(10);
continue;
}
response.Append(c);
// you may want to check for response "reasonableness" here
} while(c != \n');
DoSomethingWithResponse(response);