【问题标题】:How can I read a string from OpenNETCF.IO.Ports.SerialPort?如何从 OpenNETCF.IO.Ports.SerialPort 读取字符串?
【发布时间】:2014-06-10 18:45:27
【问题描述】:

我以这种方式使用 OpenNETCF.IO.Ports.SerialPort 将命令写入带式打印机:

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;
}

...现在我需要读取从“get val”调用返回的值,但我不知道如何,而且我无法找到如何做到这一点。我有以下开头,但不知道如何“填空”:

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 的 Read() 方法接受一个字节数组(“buffer”),后跟一个 int(“offset”)和另一个 int(“count”),然后返回一个 int。我不知道用什么作为 args 或如何处理结果 int。

更新

我试过了:

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;
    }
}

...但这让我不太满意,“System.NotSupportedException:OpenNETCF.IP.Ports.SerialPort.ReadTo(String value) at...”

更新 2

我添加了这个:

serialPort.ReadTimeout = 500;// made no difference

更新 3

基于this,我试图让它以这种方式工作:

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

...但我得到,“Method 'PDAClient.PrintUtils.Read()' referenced without parentheses”在这一行:

Thread readThread = new Thread(Read);

如果我给它括号:

Thread readThread = new Thread(ReadSetting());

...它告诉我,“参数 '1':无法从 'void' 转换为 System.Threading.ThreadStart'

-和:

"System.Threading.Thread.Thread(System.Threading.ThreadStart)' 的最佳重载方法匹配有一些无效参数"

更新 4

使用此代码:

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;
    }
}

我获得了 NRE。

更新 5

这次尝试:

serialPort.WriteLine(cmd);
setting = serialPort.ReadExisting();

...与第一次更新非常相似(“System.NotSupportedException:尚未在 OpenNETCF.IP.Ports.SerialPort.ReadExisting() at...”)

更新 6

好的,我在 ctacke 的评论中加入了伪代码,所以现在我有了这个:

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;
    }

...但它“挂起” - do...while 循环中似乎有一个无限循环。

更新 7

我在“ReadByte”之后添加了这个:

MessageBox.Show(c.ToString());

...它向我展示的只是什么(没有“内部文本”的 MessageBox);在我热启动设备之前,我让它弹出了 32 次。

更新 8

好的,那么,我的立场是正确的 - 我没有使用 OpenNETCF SerialPort,因为没有这样的东西。所以我正在尝试并拥有这个,基于提供的伪代码 ctacke。我现在正在尝试使用:

Port serialPort = new Port();
serialPort.Settings = whateverPortSettingsYouNeed;
serialPort.Open();
serialPort.Send(cmd);

...但是我不知道“whateverPortSettingsYouNeed”应该是什么,没有“Send”方法,也不知道用什么代替ReadByte()

更新 9

我现在有这个设置:

BasicPortSettings bps = new BasicPortSettings();
bps.BaudRate = 19200;
//bps.ByteSize = ?;
//bps.Parity = None;
//bps.StopBits = 1;
Port serialPort = new Port();
serialPort.Settings = bps;

...但是,如您所见,我不知道大多数值应该是什么。

更新 10

这样编译:

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;
    }
}

...现在我看看它是否真的有效...

更新 11

我发现(很难)在设置输出值之前我必须打开端口;现在是:

serialPort.Open();
byte[] outputBytes = Encoding.ASCII.GetBytes(cmd);
serialPort.Output = outputBytes;
byte[] inputBytes = serialPort.Input;
setting = inputBytes.ToString();

...但是读入设置​​的是“System.Byte[]”

我需要什么才能真正获得 inputBytes 中的值,而不仅仅是查看其类型的表示?

【问题讨论】:

  • 由于您更改了库,您之前的所有代码都变得毫无意义。只有你会知道的设置,但它看起来像 19200、无奇偶校验、1 个停止位等。要发送数据,请将其放在 Output 属性中。要读取数据,请读取 Input 属性。
  • 好的,我试试看。
  • 如何将奇偶校验设置为“无”或“无”?不接受这些值。它是一个枚举吗?另外,BaudRate 不接受 int...?
  • 好的,我得到了这个部分:bps.BaudRate = BaudRates.CBR_19200;
  • 要从byte 数组到String 来回转换,请使用System.Text.Encoding 类。所以使用setting = Encoding.ASCII.GetString(inputBytes);

标签: c# serial-port compact-framework windows-ce opennetcf


【解决方案1】:

它正在读取字节。缓冲区是读取字节的位置(由偏移量和计数修改),而返回值是读取的字节数。典型的流式东西。

文档在这里:http://msdn.microsoft.com/en-us/library/ms143549(v=vs.90).aspx

【讨论】:

  • 那些文档不适用于 OpenNETCF 的 SerialPort,它似乎没有任何文档。可以用同样的方式,但是没有示例代码,只有“理论”。
  • 啊,我明白了。没发现您正在使用 Opennet CF 的。我很确定它们遵循相同的 API 约定。
  • 正确,它遵循标准流约定。
【解决方案2】:

我注意到的第一件事是您使用了一个名为 SerialPort 的类,这意味着您使用的代码来自 SDF 1.x,最近的历史可以追溯到大约 2005 年。不确定我会对此过于热情。我在该代码之后创建了一个open source library that contains just a Port class,但它的工作方式不同 - 它是在 VB6 串行端口对象模型之后建模的。老实说,我什至不记得是谁在 SDF 1.x 中编写了代码——可能是我,也可能不是。我认为不仅仅是从我看到的代码风格来判断。

我想问你为什么不只使用内置的 CF 序列号,但如果你使用的是 SDF 1.x,你可能使用的是早于包含序列号的 CF 版本端口 API。

至于您现在使用的那个,我认为这在某种程度上取决于预期的数据返回方式,但伪代码看起来像这样:

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

【讨论】:

  • am 使用 OpenNETCF 库 - 这就是我正在使用的 SerialPort。
  • 我不同意。 Codeplex 串行库有一个名为 Port 而不是 SerialPort 的类。它也没有Read()Write 方法。根据您发布的代码,您正在使用来自 SDF 1x 的 SerialPort,这是一个完全独立的代码库,具有完全不同的对象模型,上面的伪代码是为它设计的(尽管它通常适用于任何实现,因为它是伪代码)。
  • 好的,我已经纠正了;我以为我在使用 OpenNETCF,并且我支持该单元中的某些内容,因为它的使用没有变灰...请参阅更新 8。
  • 严格来说,both 都是“OpenNETCF”,因为我们编写并发布了两者,并且都有我们的命名空间。他们只是不同。就像 FTP,我们有两个完全独立的库,具有不同的对象模型,但它们都是我们的。
猜你喜欢
  • 2013-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-08
  • 2013-09-09
  • 1970-01-01
  • 2013-01-16
  • 2017-08-10
相关资源
最近更新 更多