【问题标题】:Class to construct SCPI strings构造 SCPI 字符串的类
【发布时间】:2019-01-11 16:40:56
【问题描述】:

我正在尝试编写一个类来形成SCPI commands。我希望用法看起来像这样(类似于 Keysight 的 DLL 所做的):

Instrument.SCPI.DISPlay.TEXT.Command("HELLO");

然后它将构造字符串“DISP:TEXT HELLO”,我可以通过 Instrument 类中指定的连接发送该字符串。

我认为像这样的静态抽象类可能会起作用。对于我希望支持的任何乐器,我都可以使用新命令来扩展该类。基于抽象 SCPI 类的“仪器”类可以将生成的字符串传递给串行端口或 TCPIP 或其他任何东西。

public static class SCPI
{
    // Mandated commands
    public const string CLS = "*CLS";
    public const string ESE = "*ESE";
    public const string ESR = "*ESR";
    public const string IDN = "*IDN?";
    public const string OPC = "*OPC";
    public const string PSC = "*PSC";

    // Display command
    public static class DISPlay
    {
        public const string TEXT = "DISP:TEXT";
    }
}

但是,如果我想添加命令“TEXT:CLEar”,它会立即变得不清楚如何继续,因为我无法在 DISPlay 中嵌套另一个名为“TEXT”的类。我该如何正确地做到这一点?具体来说:

  • 如何使命令字符串相互构建?
  • 如何创建一种方法来接受一个或多个附加到字符串的参数?
  • 有没有一种方便的方法可以在字符串之间添加所需的冒号?
  • 有没有一种方便的方法可以在查询的末尾添加问号?

【问题讨论】:

  • 您在这里面临的问题是,我认为您需要将字符串生成与字符串定义分开,而要做到这一点,我认为您可能不得不放弃static 方法。
  • 哦,哇!我不知道方法链是如何工作的,甚至不知道它叫什么。
  • 另见构建器模式和流畅接口。这应该足以让你开始。这是一个有趣的问题,可惜我现在没有时间解决这个问题。

标签: c# class abstract-class abstract


【解决方案1】:
  1. 第一个解决方案:在这种情况下,您可以使用装饰器模式。检查以下链接:
    decorator pattern tutorial

    简要说明它如何适用于您的案例: SCPI 协议,您可以放置​​根命令和分支并对其进行扩展,直到您拥有明确定义的 SCPI 命令:
ROOT:BRANCH1:BRANCH2 ... <parameters>  

以下伪代码显示了如何应用该模式。基本上你需要假设每个命令都是一个包含另一个命令并返回一个字符串的类,如下所示:

class COMMAND:  /* to be used as an interface for each SCPI command */
    COMMAND ref_to_deeper_commands = NULL 
    string command_str = ""
    string get_command(){
        if(ref_to_deeper_commands == NULL)
            return command_str
        else
            return command_str + ref_to_deeper_commands.get_string()
    }

class ROOT:COMMAND /*implementation of ROOT command*/
    ROOT(){
        command_str = ":ROOT"; 
    }

    ROOT(sub_commands){
        command_str = ":ROOT" 
        ref_to_deeper_commands = sub_commands 
    }


class BRANCH1:COMMAND /*implementation of BRANCH1 command*/
    ROOT(){
        command_str = ":BRANCH1"; 
    }

    ROOT(sub_commands){
        command_str = ":BRANCH1" 
        ref_to_deeper_commands = sub_commands 
    }

class BRANCH2:COMMAND /*implementation of BRANCH2 command*/
    ROOT(){
        command_str = ":BRANCH2"; 
    }

    ROOT(sub_commands){
        command_str = ":BRANCH2" 
        ref_to_deeper_commands = sub_commands 
    }   

然后你可以实现如下的主要功能:

main_function(){
    COMMAND cmd = ROOT(BRANCH1(BRANCH2()))
    print cmd
}

在主代码中调用打印函数会给你:

ROOT:BRANCH1:BRANCH2

正如您在上面的代码中看到的,您可以灵活地进行不同的命令组合。参数也可以传递给最里面的对象实例化。

  1. 第二种解决方案:鉴于 SCPI 命令的数量有限(它们并没有那么有限,但您只需要执行一次),您可以创建一个库,其中包含返回正确字符串的函数,并且您只需要传入参数。优点是您不需要实现检查命令有效性的机制,而在解决方案 1 中,您最终可能会生成未为您的测量设备定义的非法字符串。

【讨论】:

    猜你喜欢
    • 2020-07-26
    • 2014-11-21
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多