Modbus记录器进入数据库和阵列处理策略

时间:2010-08-07 23:33:44

标签: ruby-on-rails ruby arrays database-design

我发现使用modbus读取64个连续的内存位置(元素)是使用rmodbus库通过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,并在仅记录更改之前与其自身进行比较,以便更改已被更改并已被要求记录的元素。元素应该存储在db和已经缩放的变量中,因此前端不必担心它。未记录的那些仍然保存在实例变量中,用于半实时抬头显示类型监视。然后,仅当UI请求时,才会针对图形和表解析其Events表中的已记录元素。

第一个问题:(最后!)使用数组中的数据并应用处理转换索引的图层会更有意义(并且当相应的元素值发生时)好吧,我使用v.collect{|i| i.to_s(16)}进行转换)或者将所有内容转移到哈希中更好,在这种哈希中,索引和值可以以最可用的形式幸福地生活在其中?

第一个问题编辑:鉴于我的问题的确定/演变只是将数据中的变化记录到一个简单的sqlite数据库中,并且我需要跟踪元素的变化以确定哪些变量在modbus读取之间切换,数组或散列是否更有效地进行比较?我应该关心吗?

第二个问题:在Rails中,假设一分钟的记录间隔,大约一千个数据点会更好地保存在独立字段中,还是应该将它们保留在64个元素块中并解析信息在去接口的路上?

第二个问题编辑:在数据库的一分钟“行”中运行大量未更改的数据似乎非常平淡。此外,它不允许轻松动态选择要记录的元素。以“记录器”事件而不是基于间隔为基础似乎更合适。这很好意味着第一个问题在这里更重要,因为它也可能成为状态检查机制。

我猜测我正在不必要地重新发明一个带有启示的轮子,因为这变得和现有的“伐木工人”差不多。阅读SO后发现,登录数据库与FS相比,这是一个古老的问题。由于日志本身是应用程序的基础,我倾向于登录数据库,很可能是sqlite,因为我读过的内容。

再次编辑第二个问题:现在这是一个规范化的问题,我正在阅读的所有内容都表明“可扩展性”往往需要非规范化。我记录的“事件”表将相对简单,时间戳,值和元素ID。它是否还应该从Elements表中对最常见的属性进行非规范化,或者是在这个相对较小的范围内的连接ok?

任何人都有任何喜欢的Ruby日志框架/ gems / bundles / plugins /等等吗?

2 个答案:

答案 0 :(得分:1)

我不认为这个问题已经在其他地方得到了回答:)你可能是唯一一个使用Rails和Modbus的人。我有Rails和Modbus经验,除了我的Modbus经验是在.net紧凑框架上使用nmodbus。我不知道我有什么明确的答案,但我可以分享我使用的方法。

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

现在为什么可能无法解耦 - 1000个数据点。那是个问题。为了论证,即使你能够将这些数据标准化为50个表,那就是50个表,每个表有20列......哎呀。我不知道记录1000个数据点的简单方法,但构建基本上是持久性哈希表的方法可能无法解决。

要求Rails知道如何解析寄存器值的坏处是现在你的Rails应用程序知道Modbus(不是在读取寄存器级别,而是在解析级别)。此外,如果您想使用除Rails之外的客户端,该应用程序还需要解析知识。也许这就是你的Rails应用程序的重点? Rails应用程序知道如何对Modbus读数进行切片和切块,并为用户/客户提供了一个很好的UI / Web服务。

这些都是很好的问题,但如果不了解您正在构建的内容,就很难提供具体的建议。至于规范化 - 试验和错误。两种方式都试一试。我不能说“如果你的sqlite表中有超过40个列就会分崩离析”这样的话 - 就像你必须遇到的那样......

答案 1 :(得分:0)

响应OP问题编号2.我使用一个简单的算法来获得最佳的传输请求数,而不是使用64个字块。

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