Ruby 物联网编程闲话

简介: Ruby 物联网编程闲话

首先从硬件本身聊起。

硬件领域基本都是 C 语言或者汇编语言的天下,其他语言基本上也就是划划水的存在。

大家都知道,ruby 除了我们常用的 CRuby 版本外,还有 JRuby 等等各种实现版本,估计比较少人知道的是mruby

直接使用mruby 还是有点难的,下面的下面会介绍一下。

Arduino

Arduino 系列是针对硬件爱好者的开发的,通过这个项目mruby-arduino 可以用 Ruby 开发。

曾经试了一下,因为 Arduino 本身提供的语法也很简单,所以基本上就相当于玩了一下而已。

ESP

ESP 系列本身在工业领域用的比较多,现在也有一些类似于玩具一样的产品,比如说 ESP-EYE 等,可玩性很强。可以运行 TensorFlow Lite,实现离线人脸识别,除了速度慢没别的缺点。

有个开源的项目,mrubyc-esp32-arduino 可以实现在 ESP 系列硬件上用 ruby 编程,不过环境安装在国内实在是费劲。

但是 ESP 系列的可玩性很强,有个 micro-python 的项目,和 Ruby 相比起来更有优势。

micro:bit

另外还有针对BBC micro:bit v2的项目。

再说说物联网的协议

现在比较流行的有 NB-IoT 和 Lora 两种,当然还有其他的,有兴趣的可以自行百度一下。

NB-IoT

NB-IoT,全称是 Narrow Band Internet of Things,窄带物联网,它的原型是 2014 年 5 月华为和沃达丰联合提出的 NB M2M 技术,随后在 2015 年 5 月与高通提出的 NB OFDMA 技术融合成为 NB-CIOT 技术,之后又于 2015 年 9 月与爱立信公司提出的 NB-LTE 技术融合,形成了我们现在认识的 NB-IoT,并在 3GPP 上正式立项。至 2016 年 6 月,NB-IoT 核心标准冻结,但相关特性仍在持续演进中。

NB-IoT 的优点是不需要自己组网,直接依托运营商网络就可以。缺点就很显然,数据都到了运营商手里了,当然也可以自行对数据进行加密。之前在一家公司负责和华强北对接,他们就对自己的数据进行了封装,运营商如果没有协议是很难自行破解的(其实也很简单,估计就是数据没什么价值,因为除了自定义协议外并没有进行数据加密)。

和华强北合作的项目用的是电信的 NB-IoT 平台,可以通过 REST 接口拉取,也可以用 Apache Pulsar Client SDK 自行拉取。

很多城市的电动车防盗就是通过 NB-IoT 实现的,利润你懂得~

国家准备在未来几年,健全 NB-IoT 网络,覆盖城乡农村,加强在农业等领域应用。

Lora 也是流行的一种物联网协议。

Lora 的好处是 Lora 所用的无线电频率连业余频率都不是,所以组建 Lora 网络不需要相关部门批准。缺点就是自己组网成本较高。

一台 Lora 发射器成本不到一千元,可以覆盖大约空旷地带 10 公里的范围,实际上受建筑物的影响,可能每层都需要一台中继,所以实现的成本还是很高的。

目前在燃气抄表等领域,都有应用 Lora 的案例,和 NB-IoT 相比应用比较小。

优点是完全自主可控。

4G/5G/Wifi直连

这没啥好说的

Ruby 物联网实现

我们使用的是EventMachine,好像之前停了一段时间之后又活了。

核心的原理就是物联网硬件通过 TCP Socket 发送到指定服务器,服务器通过 Nginx 做了一个负载均衡

因为物联网硬件是通过 4G 网络连接的,所以物联网硬件的 IP 是动态的。为了保持服务器和硬件之间的连接,需要定时发送心跳。

屏幕截图 2023-09-06 114408.png

然后通过EventMachine来保存连接,需要的时候发送指令等。

以下的代码好久没看了,仅供参考:)

require 'eventmachine'
class SaleServer < EM::Connection
  include Wanfeng
  extend Wanfeng
  @@connections = {}
  @@logger = Logger.new("#{Rails.root}/log/vending_machines.log")
  def initialize
    @@last_heart  = Time.zone.now
  end
  def self.connections
    @@connections
  end
  def self.deliver_goods_data(machine, row, column, count, password="111111")
    sale(machine, rand(100), row, column, count, password).pack("C*")
  end
  def post_init
    @@logger.info "connected  "
  end
  def receive_data data
    @received_data = data.unpack('H*').first
    if valid_imei?
      add_clients
      log_received_data
      show_connections
      reply_heart
    end
  end
  def unbind
    @@connections.delete(self)
    @@logger.info "#{imei} disconnected\n"
  end
 private
 def imei
   get_machine_code(@received_data)
 end
 def valid_imei?
   !!(imei =~ /\A\d+\z/) && (imei&.size == 15)
 end
 def add_clients
   $redis.hmset('vending_machines', imei, Time.zone.now )
   @@connections[imei] = self
 end
 def log_received_data
   last_time =  "#{Time.now - @@last_heart} seconds"
   @@last_heart = Time.now
   @@logger.info "Received:\t#{last_time}\t#{@received_data}"
 end
 def reply_heart
   unless imei.present?
     @@connections[imei].send_data(heart(imei, "111111").pack("C*"))
   end
 end
 def show_connections
   @@connections.each do |k, v|
     @@logger.info "Connection: #{k}: #{v} "
   end
 end
end

这个是一段控制售货机的代码,出货指令是通过ActiveJob 实现的:

class AutosaleJob < ApplicationJob
  queue_as :default
  def perform(machine, row, column, count)
    SaleServer.connections[machine].send_data(
      SaleServer.deliver_goods_data(machine, row, column, count)
    )
  end
end

如果用的是 Passenger 的话,需要在config/application.rb 中这样启动EventMachine,没有这个if defined?(PhusionPassenger)逻辑会报什么错,我已经忘了 :

# config/application.rb
    ...
    config.after_initialize do
      if defined?(PhusionPassenger)
        PhusionPassenger.on_event(:starting_worker_process) do |forked|
          if forked && EM.reactor_running?
            EM.stop
          end
          Thread.new {
            EM.run {
              EM.start_server '0.0.0.0', 4000, SaleServer
            }
          }
          Signal.trap("INT")  { EM.stop }
          Signal.trap("TERM") { EM.stop }
        end
      end
    end
   ....

出货调用逻辑:

AutosaleJob.perform_now(params[:code], row, column, amount)

这样你就能在夏天喝上王老吉了:)

总结

在开发单片机原型的时候,用 Ruby 快速验证是可以的,不过你必须要懂点 C 才行,不然寸步难行。

在服务器开发方面,用 Ruby 实现是没有问题,而且运行也非常稳定。

服务器性能优化,最重要的是找到影响性能的瓶颈。

曾经做过一个中国全海域风能评估的项目,绝大部分代码是用 Ruby 写的,只有统计的一小点用的是 C。

这样既满足了需求,也大大提高了开发的速度和效率。

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
2月前
|
网络协议 Ruby
|
2月前
|
存储 JavaScript 编译器
这款国产中文编程火了!通过文言文编译生成Python、JS、Ruby代码!
这款国产中文编程火了!通过文言文编译生成Python、JS、Ruby代码!
214 0
|
2月前
|
移动开发 网络协议 Ruby
|
2月前
|
Ruby
|
2月前
|
Ruby
|
10月前
|
数据库 开发者 Ruby
使用 Ruby 进行快速原型开发和敏捷编程
在当今的软件开发领域,敏捷方法已经成为广泛采用的开发方式。而作为一门灵活且功能强大的动态编程语言,Ruby 提供了许多工具和技巧,使它成为进行快速原型开发和敏捷编程的理想选择。
68 0
|
11月前
|
传感器 IDE 物联网
物联网操作系统与开发:连接智能世界的编程之旅
本篇深入研究了物联网中的操作系统选择与比较,嵌入式软件开发环境,以及物联网应用程序的开发与调试。我们比较了常见的物联网操作系统,并通过Zephyr操作系统的示例代码展示了如何控制LED灯。读者将了解嵌入式开发环境的设置,包括交叉编译器和IDE的配置,以及如何开发物联网应用程序,从传感器数据采集到与云平台通信。通过本篇内容,读者将更加了解物联网操作系统与应用开发的关键知识,为连接智能世界的编程之旅奠定了基础。
160 0
|
芯片
【物联网智能网关-05】扫描键盘编程设计
.NET Micro Framework模拟器提供了5个模拟按键(上、下、左、右和确认按键),所以一般.NET MF开发板也只需要提供5个按键就可以了,而这5个键,也是直接和CPU的pin脚相连,用GPIO的输入相关的函数就可以操作了,使用非常简单。
562 0
|
安全 物联网 测试技术
书籍:python物联网编程项目 Internet of Things Programming Projects - 2018
简介 利用Raspberry Pi 3和Python的组合,充分发挥物联网的潜力 使用IoT构建复杂的基于Python的应用程序 从事各种物联网项目,了解电子产品的基础知识 物联网(IOT)已成功吸引了研究人员和技术爱好者的注意力,因为它将经典网络与仪器和设备完美结合。