1

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.

UPDATE

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..."

UPDATE 2

I added this:

serialPort.ReadTimeout = 500;// made no difference

UPDATE 3

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"

UPDATE 4

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.

UPDATE 5

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...")

UPDATE 6

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.

UPDATE 7

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.

UPDATE 8

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()

UPDATE 9

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.

UPDATE 10

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...

UPDATE 11

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?

B. Clay Shannon-B. Crow Raven
  • 8,547
  • 144
  • 472
  • 862

2 Answers2

2

It is reading bytes. The buffer is where the bytes are read into (as modified by the offset and count), while the return value is the number of bytes read. Typical stream-type stuff.

The docos are here: http://msdn.microsoft.com/en-us/library/ms143549(v=vs.90).aspx

tcarvin
  • 10,715
  • 3
  • 31
  • 52
1

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);
ctacke
  • 66,480
  • 18
  • 94
  • 155
  • I *am* using the OpenNETCF library - that's the SerialPort I'm using. – B. Clay Shannon-B. Crow Raven Jun 11 '14 at 15:17
  • I disagree. The Codeplex serial library has a class called `Port` not `SerialPort`. It also doesn't have a `Read()` or a `Write` method. Based on the code you posted, you are using the `SerialPort` from SDF 1x, which is a totally separate code base with a completely different object model, and which the pseudocode above is designed for (though it would generally work with any implementation, since it's pseudocode). – ctacke Jun 11 '14 at 17:24
  • Okay, I stand corrected; I *thought* I was using OpenNETCF, and I am for something in that unit, because its using is not greyed out...please see Update 8. – B. Clay Shannon-B. Crow Raven Jun 11 '14 at 17:47
  • Strictly speaking, *both* are "OpenNETCF" since we wrote and published both, and both have our namespace. They are just different. It's like FTP, we have two completely separate libraries with different object model, but they both are ours. – ctacke Jun 11 '14 at 18:06