65.9K
CodeProject 正在变化。 阅读更多。
Home

BetaBrite LED 显示屏 API

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (19投票s)

2005年3月21日

8分钟阅读

viewsIcon

205123

downloadIcon

2226

一个简单的 API,用于通过 RS-232 串行命令控制 BetaBrite LED 广告牌。

引言

秉承 熔岩灯构建监控自动化持续集成和环境球 的精神,我购买了一个 BetaBrite 单行电子 LED 广告牌。这个两英尺长的 LED 显示屏比那些复古风格的趣味构建状态指示器好多了。BetaBrite 支持八种颜色和 12 种不同的字体样式显示完整的文本构建状态信息——包括动画!它非常酷;我还没见过有人走过我的桌子而不被其迷人的动画和颜色所吸引。而且它并不算太贵。 Sam's Club 的 BetaBrite 广告牌 售价为 160 美元,其中包括串行通信线缆、手持遥控器和软件。

BetaBrite 可以通过红外遥控器完全编程,但用遥控器输入长消息非常麻烦。通过 RS-232 串行转 RJ-12 线缆 将 BetaBrite 连接到您的 PC,然后使用捆绑的 Windows 软件 来编程广告牌要容易得多。

Windows 软件工作正常,但 **我真正想要的是一个原生的 .NET API**。因此,在拥有协议文档和运行中的 BetaBrite 连接之后,我开始着手编写一个易于使用的 .NET API 来控制 BetaBrite。

理解 BetaBrite LED 广告牌

BetaBrite 理解 Alpha 广告牌通信协议 的一个子集。我们谈论的是 RS-232 串行通信,设备拥有高达 32KB 的内部内存——算不上超级计算机。因此,正如您可能预期的那样,该协议有些原始,有时令人困惑。我花了一周时间仔细研究了文档;以下是我的发现:

  • BetaBrite 只支持 Alpha 协议的 1.0 版本

    Alpha 协议文档 中提到 2.0 或 3.0 功能的任何内容都不适用于 BetaBrite。其中一些是显而易见的,例如多行命令——BetaBrite 只有一行——而另一些则不太明显。

  • 所有通信都采用标准数据包格式

    广告牌通过 9600,N,8,1 的 RS-232 串行端口连接与 PC 通信。发送到广告牌的所有消息都将采用标准数据包格式。

    为简化通信,所有消息都以纯文本 ASCII 发送,不包含不可打印的高位 ASCII 字符。如果需要高位 ASCII,它将以双字节格式编码,如下文所示。

  • 广告牌将“文件”存储在由单个 ASCII 字符标记的槽中

    从 20h(空格)到 7Eh(1/2 空格)的任何 ASCII 字符都可以用作文件标签,您可以分配任意组合的文件标签,但不能超过广告牌 32KB 的内部内存限制。请注意,文件标签“0”是所谓的“优先级标签”,处理方式略有不同,但除此之外,它们都只是用于存储文本、字符串或图片的命名文件标签。

  • 所有内存必须提前分配

    我想我被 .NET 的自动内存管理和垃圾回收器惯坏了,因为花了我一些时间才理解这一点。任何时候对广告牌进行编程,都必须提前分配所需的所有内存。任何尝试稍后分配更多内存的行为都会销毁所有现有的内存分配!确保在将任何内容写入广告牌 *之前* 分配好所需的所有内存。这在实践中不是什么大问题,但无法抽象化,所以您必须意识到这一点。

架构

早期,我决定将 API 实现为三个类

  • BetaBrite.Sign

    这是广告牌的主要 `Public` 接口。它在后台驱动 `Protocol` 和 `RS232` 类,因此用户可以免受 Alpha 广告牌通信协议和 RS-232 串行通信复杂性的影响。这里快速看一下:

  • BetaBrite.Protocol

    这个 `Private` 类工厂定义了与广告牌通信所需的所有底层命令,所有命令都可以通过 `ToBytes()` 方法渲染成字节流。此外,如果您想预览命令的“美化打印”版本,可以调用该命令的重写 `ToString()` 方法。所有命令都继承自 `BaseCommand` 类,该类实现了标准的 Alpha 数据包格式。子命令必须重写 `FormDataField` 方法,该方法返回特定于该命令类的文本字符串。`Sign.SetDateAndTime` 方法说明了这一点的工作原理:

    ''' <summary>
    ''' Sets the date and time on the sign to any arbitrary date/time
    ''' </summary>
    Public Sub SetDateAndTime(ByVal dt As DateTime)
        Dim dc As New BetaBrite.Protocol.SetDateTimeCommand(dt)
        If _IsDebug Then
            Debug.Write(dc.ToString)
        End If
        Write(dc.ToBytes)
    End Sub

    请注意,`Protocol` 的几个 `Enum` 被暴露在 `Sign` 方法中——用于过渡等——因为这些是由底层协议不可避免地决定的。

  • BetaBrite.RS232

    这个 `Private` 类定义了 PC 与广告牌之间的通信方法。它几乎完全是 `Private` 的,但是,您仍然需要为 `Sign` 对象提供一个通信端口号。在内部,所有 `Protocol` 命令都被渲染成字节流,并通过 Cory SmithDBComm 类 自动传输到广告牌。除了我添加的一些归功于 Cory 的标题注释外,它没有修改。我将其编译进来,以便整个 BetaBrite DLL 可以用作独立的接口 API,没有任何其他依赖项。

使用 BetaBrite.Sign

正如承诺的那样,这个 API 非常简单易用。这是典型的“Hello, World”示例——假设您的 BetaBrite 连接在第一个串行端口上:

  Dim bb As New BetaBrite.Sign(1)
  bb.Open()
  bb.Display("I <extchar=heart> BetaBrite!")
  bb.Close()

现在,这个示例有点取巧,因为 `Display()` 方法非常简单。此方法只能显示 **单个消息**(尽管它可以是非常 *长* 的消息,最多 32KB)。为了超越“Hello World”,我将展示三种可以在 BetaBrite 广告牌上显示的内容的示例。

**文本** 项目是最常用的,代表格式化文本后跟一个过渡状态:

Dim bb As New BetaBrite.Sign(1)
With bb
  .Open()
  .UseMemoryText("D"c, 128)
  .UseMemoryText("E"c, 128)
  .UseMemoryText("F"c, 128)
  .AllocateMemory()

  .SetText("D"c, _
    "<font=five><color=green>This is <font=seven>file D", _
    Transition.Rotate)
  .SetText("E"c, _
    "<font=five><color=yellow>This is <font=seven>file E", _
    Transition.WipeLeft)
  SetText("F"c, _
    "<font=five><color=red>time is <calltime>", _
    Transition.RollDown)

  .SetRunSequence("EDF")
  .Close()
End With

如果您运行此代码,您应该会看到三条不同的消息,具有不同的颜色、字体和消息之间的过渡。请注意显式内存分配——请确保您分配的内存足以容纳文本以及每个标签的一两个字节的格式代码。您可能已经注意到,文本消息字符串支持一套 **轻量级的 HTML 风格格式代码**,您可以在 `Protocol` 类的文本格式化区域找到它们:查找 `Protocol.ControlChars`、`Protocol.Color`、`Protocol.Font`、`Protocol.ExtChar` 和 `Protocol.CharAttrib`。我将不在此列出所有内容,因为演示解决方案展示了每个示例。然而,重要的是要记住,与 HTML 不同,这些标签 **不支持** 结束标签——所以如果您更改了颜色,它将保持更改状态,直到您的其余消息!请确保在完成后将颜色改回来。

**字符串** 项目是文本的一个子集,它充当变量:

Dim bb As New BetaBrite.Sign(1)
With bb
  .Open()
  .UseMemoryText("A"c, 128)
  .UseMemoryString("B"c, 32)
  .AllocateMemory()

  .SetText("A"c, "You are customer number <callstring=B>")
  .Close()
End With

我没有在这里指定运行顺序,因为文件 *A* 始终默认运行。字符串的主要优点是 **它们可以在不使广告牌“闪烁”的情况下动态更新**,所以将它们视为变量。它们支持文本消息所支持的部分格式代码,因此除非您需要变量,否则请坚持使用文本消息。

**图片** 项目代表一个高达 80x7 像素的 8 色位图:

Dim bb as New BetaBrite.Sign(1)
With bb
  .Open()
  .UseMemoryText("A"c, 128)
  .UseMemoryPicture("B"c)
  .UseMemoryPicture("C"c)
  .UseMemoryPicture("D"c)
  .AllocateMemory()

  .SetPicture("B"c, "betabrite_picture_triangle.bmp", 35, 7)
  .SetPicture("C"c, "betabrite_picture_smiley.bmp", 10, 7)
  .SetPicture("D"c, "betabrite_picture_demo.bmp")

  .SetText("A"c, _
    "<callpic=C><callpic=C><callpic=B><callpic=C>" & _
    "<callpic=C><newline><callpic=D>", _
    Transition.RollUp)

   .Close()
End With

请注意,除非您另有说明,否则最大图片内存(80x7)将在该文件标签中分配。运行后您应该会看到这个:

这会向上滚动,然后被我创作的一些“现代艺术”的全尺寸 80x7 图片替换。现在,我知道您在想:**是的,您可以将任何任意的 80x7 像素图像加载到 BetaBrite 中**,以 .NET 支持的任何格式。但是,不要期望它看起来很好!80x7 是一个非常小的像素数,而 BetaBrite 的调色板非常有限:基本上是两种红色、两种绿色和四种黄色(参见 `Protocol.PixelColor`)。您可以尝试一下,但不要说我没警告过您。我建议坚持使用我在演示解决方案中创建的 8 色位图模板;在 `\bin` 文件夹中查找它们。

动画图像(如 .gif 动画)不受原生支持,但可以通过 `` 或 `` 标签和一系列巧妙设计的图片文件进行“黑客攻击”。演示解决方案中也有一个模拟动画的例子。

一些限制

我对这个 API 的最终效果很满意,但我认为值得一提的是我决定不做的一些事情。其中一些可能作为未来的增强功能是有意义的,而另一些则是故意避免的。

  • **它仅限于 BetaBrite。** 我曾考虑让 API 足够通用,可以与任何 Alpha 广告牌一起使用,但很快就认为这是一个坏主意,因为我没有其他 Alpha 广告牌可以进行测试。
  • **它是只写的**。我只实现了写入命令,但每个写入都有一个读取。在我看来,对于连接到 PC 的广告牌来说,让 API 读写不是必需的,但它可能有用。
  • **它不公开高级运行功能**。在设置广告牌上的日期和时间后,您可以让某些文件标签在一天中的特定时间运行。运行顺序可以在上午 9 点到中午 12 点显示“GOOD MORNING”,在下午 6 点到上午 9 点显示“GOOD EVENING”。尽管 `BetaBrite.Protocol` 类支持这一点,但我没有将其公开在 `BetaBrite.Sign` 中。这并不难做到,但我认为它对于 PC 连接的广告牌来说并不太有用——我预计 PC 每隔几分钟就会覆盖一次广告牌。对于独立运行的广告牌来说,它会更有用。

结论

如果您拥有 BetaBrite LED 广告牌,我相信您会喜欢这些类;它们使编写支持 BetaBrite 广告牌的 .NET 应用程序变得容易。在文章顶部的演示解决方案中有更多细节和注释,所以请查看一下。

希望您喜欢这篇文章。请随时提供反馈,无论是好是坏!如果您喜欢这篇文章,您可能也会喜欢 我的其他文章

历史

  • 2005 年 3 月 20 日,星期日 - 发布。
  • 2005 年 4 月 21 日,星期四 - 版本 1.1
    • 修改了图片方法,以支持直接传递 `Bitmap`。
© . All rights reserved.