将Modbus记录器存入数据库并处理数组的策略

4

我发现使用rmodbus库读取64个连续内存位置(元素)是通过Modbus检索信息最有效的方式。

我的目标是将读取的信息记录在一个简单的数据库中,可以通过数据挖掘在网页上生成图表和数据表,并将最新值存储在实例变量中。

rmodbus库将数据读入一个数组中,其中每个元素的索引表示该元素的地址。然而,我想将索引转换为八进制,因为这与用户已经熟悉的元素寻址方案相对应,并且更容易在界面中引用。

编辑添加详细信息和细化:此时,我正在使用以下模式:

create_table "elements", :force => true do |t|
    t.string   "name"
    t.integer  "modbus_connection_id"
    t.string   "address"
    t.string   "eng_unit"
    t.integer  "base"
    t.string   "wiring"
    t.text     "note"
    t.boolean  "log"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "events", :force => true do |t|
    t.integer  "element_id"
    t.string   "value"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "modbus_connections", :force => true do |t|
    t.string   "name"
    t.string   "ip_address"
    t.integer  "port"
    t.integer  "client"
    t.text     "note"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

这个想法是,一个后台进程将可能会对modbus进行轮询并与自身进行比较,以便记录只有在被请求记录的情况下才发生变化的元素。元素应该存储在数据库和变量中,已经缩放,因此前端不必担心它。那些没有记录的元素仍然保存在实例变量中,用于半实时的提示显示类型监视。然后,在UI请求时,将解析其事件表中的记录元素以进行图形和表格。
第一个问题:(最后!)是否更合理地将数据保留在数组中,并应用一个处理程序来转换索引(以及恰好相应的元素值,我使用`v.collect {|i| i.to_s(16)}`进行转换),还是更好地将所有数据转移到哈希中,其中索引和值可以在最可用的形式下幸福地生活?
第一个问题编辑:鉴于我的问题趋向于仅记录更改的数据到简单的sqlite数据库,并且我需要跟踪元素的更改以确定哪些在modbus读取之间发生了更改,数组或哈希是否更有效地进行比较?我应该关心吗?
第二个问题:在Rails中,假设每分钟记录一次,大约一千个数据点是否更好地保留在独立字段中,还是应该将它们留在64个元素块中,并在传递给接口时解析信息?
第二个问题编辑:将大量未更改的数据运行到数据库的一个分钟“行”中似乎很平淡。此外,它不允许轻松动态选择要记录的元素。似乎将“记录器”事件基于事件而不是基于时间间隔更为适合。这意味着第一个问题在这里更为重要,因为它很可能会成为状态检查机制。
我猜我对这个启示进行了不必要的重新发明,因为这很像现有的“记录器”。阅读关于SO的内容揭示了一个古老的问题,即将日志记录到DB vs. FS。由于日志本身是应用程序的基础,我倾向于记录到DB,最可能是sqlite,考虑到我所读到的内容。
第二个问题再次编辑:现在是归一化的问题,我所读到的所有内容都表明,“可扩展性”往往需要非归一化。我的记录“Events”表将相对简单,包括时间戳、值和元素ID。它是否还应该将来自Elements表内部的最常见属性进行非归一化,或者在这个相对较小的规模上进行联接?
有人有任何喜欢的Ruby记录框架/ gem / bundle /插件/任何东西吗?

似乎我在这里的思考方式太过“平面化”了。我会适当编辑问题。 - arriflex
好的,既然我要么是在问一个已经在其他地方得到答案的问题,要么是自己已经解决了问题,那我就完全改变第二个问题。 - arriflex
这个项目开始变得有些比我预期的更加难以控制了。我认为是时候学习如何使用GIT,这样我就可以进行更少破坏性的实验了! - arriflex
2个回答

1

我认为这个问题在其他地方没有得到解答 :) 你可能是SO上唯一使用Rails和Modbus的人。我有Rails和Modbus的经验,但我的Modbus经验是在.net compact framework上使用nmodbus。我不知道我是否有任何明确的答案,但我可以分享我使用的方法。

当我们轮询设备时,我们立即对数据应用任何解析、缩放或转换(但我们没有1000个值)。然后将数据记录到数据库中。现在,任何想要使用数据库的客户端都不知道modbus,也不关心;问题从了解modbus转移到了应用程序真正关心的问题(电压!)。在您的情况下,我会尝试完全将此轮询应用程序与您的Rails应用程序分离。

现在为什么解耦可能不可行-1000个数据点。那是一个问题。就算你能够将这些数据规范化成50个表,每个表有20个列...恶心。我不知道记录1000个数据点的简单方法,但构建基本上是持久哈希表的东西可能行不通。

需要Rails来知道如何解析寄存器值的不好之处在于现在您的Rails应用程序具有Modbus的知识(不是在读取寄存器级别,而是在解析级别)。另外,如果您想使用除Rails以外的客户端,该应用程序也需要解析知识。也许这就是您的Rails应用程序的全部意义?Rails应用程序知道如何切片和解析Modbus读数,并为用户/客户提供了漂亮的UI / Web服务。

这些是好问题,但是没有更多关于您正在构建的内容的了解很难给出具体的建议。至于规范化-尝试和错误。两种方法都尝试一下。我不能说像“如果您的sqlite表中有40列以上,它会崩溃”的东西-您只能遇到这样的问题...


1
非常有趣。你的想法与我的相似并且在不断发展。 当我考虑仅记录更改而不是冗余值时,1000个数据点的问题变得不那么令人生畏。我可能没有表达清楚,正如你所提到的,我认为收集和存储的解耦是至关重要的。在一秒钟内可能只会有最多一百个值发生变化,以日志方式存储它们应该很容易。让Rails解析显示,速度不太重要。 很高兴我不是完全孤单的!谢谢。 - arriflex

0

回答OP的第二个问题。我使用了一个简单的算法来获取最优的传输请求数量,而不是使用64字块。

这个算法非常简单,你从地址1开始(假设你正在使用PLC),然后找出是否需要轮询该寄存器,在这种情况下将其用作起始地址并增加长度,直到达到125(这是modbus的最大值)。如果不需要,则转到下一个元素并查看是否需要轮询,并重复该过程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接