SlideShare a Scribd company logo
用 Ruby 開發 IoT 應用
以RubyConf.tw打卡系統為例
曾亮齊 (Henry Tseng)
$ whoami
曾亮齊(Henry Tseng)
A.K.A. lctseng (Github, Twitter…)
5xRuby DevOps
Rails Girl Taipei 教練
中研院資科所短期研究助理
國立臺灣大學 資訊工程系
獨立遊戲『軍官之歌』Programmer
(80,000+ lines of Ruby)
這是一個好不容易做出系統後,
又全部打掉重練的故事…
緣起
Rubyconf.tw 2015
Python 版的打卡機 (Codeme)
使用 Raspberry PI + RFID Reader
沒有繼續維護
功能有限,難以擴充
緣起
Ruby 圈仍無類似的作品
公司買了幾台 PI 與讀卡設備
以 Ruby 重刻打卡系統
為 2016 RubyconfTW 做準備
打卡設備
打卡設備
Raspberry PI 3
RFID Reader (MFRC522)
蜂鳴器 (DC buzzer)
設計理念
當初是以打卡系統為設計方向
掌握會眾流向與人數
可以傳送 Sensor 資料並回報結果
例如打卡紀錄
希望裝置可以由中央掌控
Conf 用打卡系統運作流程
會眾於報到時發給一張 RFID 晶片卡貼紙,綁定個人資料
會眾於各場次入場時,可在門口的打卡機進行打卡
各贊助商攤位上也有一台屬於該攤位的打卡機
會眾可以透過打卡的動作,將聯絡資料留給攤商
不必再使用傳統的紙本資料
實際Demo
功能設計
可以傳送 Sensor 資料並回報結果
報到時,檢查該張卡片是否重複使用
打卡時,檢查該張卡片是否已報到過
根據不同的結果發出不同聲響
功能設計
希望可以由中央掌控
Agent: 打卡機;Manager: 中控程式
Agent 難免會斷線或需要重啟
不可能隨時連線進去分散在各處的 Agent
掌握 Agent 存活的狀況
Manager 向 Agent 下達指令
(重啟、關機、發出聲響)
連線設計
使用 HTTP 而不是 Raw TCP
可套用現存的 SSL(HTTPS)
可輕易整合到 Rails 中 (HTTP API)
連線設計
雙向連線
非同步指令
(重啟、關機)
Agent
打卡結果
(卡號)
連線設計
傳統 HTTP API
非同步指令
Polling
Agent
打卡結果
偵測到卡片再發出
request
setTimeout()
連線設計
WebSocket 的使用
HTTP + 雙向連線
可以在 Javascript 端寫 callback,讓 server 端送資料來呼叫
Rails 中已有 WebSocket 的實作
Action Cable
不必注重連線管理
專注於資料交換
連線設計
使用 Action Cable
專替 Web Application 設計
官方 Client 為 Javascript
當時並無找到 Ruby 的 Client 端實作
模組化:分離連線端與晶片控制端
未來若有更好的 Client 端可隨時抽換
連線設計
暫時的解決方法
用 Ruby 包裹 browser 執行 JS
為了提供完整的 JS 環境,使用 browser 是最直接的
Agent
Check-in Server
(Manager)
連線設計
在指令介面中使用瀏覽器?
如何在CLI中啟動以GUI為主的瀏覽器
如何以指令的方式控制瀏覽器的行為
解決方法:
Xvfb + headless
Xvfb + headless
Virtual framebuffer X server for X Version 11
在沒有圖形介面的情況下,執行任何需要圖形
介面的程式
用於測試
例如可在純指令介面的情況下進行網站的整合
測試 (Selenium, Watir)
Xvfb + headless
headless
Ruby gem
https://github.com/leonid-shevtsov/headless
Ruby interface for Xvfb
使用 headless 啟動瀏覽器
以文字操作的方式送指令來執行 Javascript
Xvfb + headless
require 'headless'
require 'watir-webdriver'
# 啟動虛擬視窗
@headless = Headless.new
@headless.start
# 在虛擬視窗中執行瀏覽器(如Firefox)
@browser = Watir::Browser.new
# 前往網頁URL
@browser.goto(url)
Xvfb + headless
# 檢查 ActionCable 是否有連上?
def check_website_connected?
@browser.driver.execute_async_script(%{arguments[argum
ents.length - 1](typeof(App) != 'undefined')})
end
Xvfb + headless
# 透過 ActionCable 傳送字串(str)
def write_string(str)
@browser.driver.execute_async_script(%{arguments[argumen
ts.length - 1](App.device.connect(#{str.to_json}))})
end
# 讀取來自 Manager 的資料
# 此範例中資料被紀錄在 windoow 的某個 property 中,透過函式來取得
def read_string
@browser.driver.execute_async_script(%{arguments[argumen
ts.length - 1](window.retrieve_data())})
end
Xvfb + headless
# 關閉瀏覽器
@browser.close
# 關閉虛擬視窗
@headless.destroy
連線設計
後來並沒有採用上述的方法
單純為了連線而跑 browser 實在不合理
action_cable_client
開發數個月後出現的gem
純 Ruby 的 Action Cable client library
連線設計
Manager 端的設計
直接使用 Action Cable 的 Server 端 API
作為打卡系統的一部分寫在 Rails 中
管理 Agent 與驗證卡號的邏輯寫在一起
實際部署
Rubyconf.tw 2016
約17台 Agent
基本上該有的功能都有完成
當初設計時有些缺失
導致常常為了設備問題東奔西跑
問題
action_cable_client 反應不夠靈敏
尤其是網路不穩時
會場網路偶爾會斷線
Timeout 時間太長,Agent 沒有寫斷線回報機制
斷線常常需要人為檢查
問題
action_cable_client gem 仍在發階段
偶爾會發生連線卡死 (網路正常,就是連不上Server)
有時網路中斷恢復後,除非重開整支程式,否則連線無法恢復
雪上加霜:所有工作都在同一個thread
斷線時整個程式都要重開
Refactor
重新設計連線相關的組件
仍使用 WebSocket,但不再依賴 Action Cable
不再依賴有潛在問題的 gem
更加即時的連線檢查與重新連線
分離 Manager 與 Rails app
不需要 Action Cable,因此可與 Rails 切割開
Agent 重新設計
元件化
每個元件(網路連線、讀卡機、蜂鳴器)各成組件
每個組件由各自的 thread 跑 event loop
定義 event 作為元件間的溝通
系統指令、讀卡訊號、聲音(蜂鳴器)訊號、連線狀態等
當有元件出錯時,重開該 thread 即可達到重啟效果
權責分明:容易加入/移除元件
Agent 架構圖
Master (管理所有組件、廣播 event)
Buzzer 蜂鳴器組件
• 接收 event: 聲響控制
Card Reader 讀卡機組件
• 發出 event: 卡號資料
Connection 連線組件
• 透過網路轉送 event 給 Manager,或從 Manager 接收 event
Manager 重新設計
分離自 Rails,可獨立運行
分離打卡邏輯與裝置管理
專注於裝置管理
Rack-based
保留與 Rails 結合的空間 (讓 Rails app 處理打卡邏輯)
如同 ActionCable,可 mount 至 Rails app 中
HTTP / Web Socket
request
Rails app
Manager
Router
Manager 重新設計
Rack socket hijacking
當 request URL 滿足指定 path 時,交給 Manager 處理
其餘則交給 Rails app
根據 URL 判斷
mount Tamashii::Manager::Server =>
'/tamashii'
config/routes.rb
Manager 架構 (standalone)
Channel Pool
Channel
Client
Check-in Server
Channel Channel
Manager 架構 (with Rails)
當前進度
新架構名為 tamashii
目前共有三個 gem
tamashii-agent:Agent 端,安裝於 PI 上
tamashii-manager:Manager 端 (獨立於 Rails)
tamashii-common:Agent、Manager 共用組件
Test framework: rspec
使用 tamashii-agent
設備:Raspberry PI 3、已安裝 Ruby (MRI)
包含RFID與蜂鳴器
安裝 gem
$ gem install tamashii-agent
使用 tamashii-agent
單次執行 (one-start)
需要能夠存取 GPIO 的權限 (如 root)
作為系統背景程式 (daemonize)
$ tamashii-agent -C agent_config.rb
$ tamashii-agent --install--systemd
Tamashii::Agent.config do
env 'development'
auth :token
token 'abc123'
end
使用 tamashii-manager
安裝 gem
Standalone Server
$ gem install tamashii-manager
$ tamashii-manager -C manager_config.rb -p 3000
Tamashii::Manager.config do
env 'development'
auth :token
token 'abc123'
end
使用 tamashii-manager
Mount 在 Rails app 中
假設希望在 /tamashi 這個路徑上執行 Manager
在 config/routes.rb 中加入
manager_config.rb 則是改放到 config/initializers
mount Tamashii::Manager::Server => '/tamashii'
使用 tamashii-manager
Manager 收到來自 Agent 的訊息後,會直接執行預設
的 handler
例如:廣播封包到整個 channel
並不會直接交給 Rails app 來處理
ManagerAgent Check-in
使用 tamashii-manager
這個設計理念是基於 Manager 應該與 Rails app 脫鉤
若要以脫鉤的概念來看,Rails app 應該也要加入 channel
利用 channel 廣播的特性,傳送訊息給 Agent
Channel Pool
Channel
Client
Check-in
Channel Channel
使用 tamashii-manager
Hook
若 Manager 與 Rails app 同在一個 Rack 底下
可透過此方式『監聽』甚至『攔截』訊息
透過 Manager API 發出訊息
ManagerAgent Check-in
Hook
使用 tamashii-manager
使用 Hook (類似 middleware)
新增一個 Hook Class
設定 config/initializers/manager_config.rb
class TamashiiRailsHook < Tamashii::Hook
def call(pkt)
if some_condition?
true # 此訊息會被攔截,不執行 handler
else
false # 此訊息會執行預設的 handler
end
end
end
Tamashii::Resolver.config do
hook TamashiiRailsHook
end
使用 tamashii-manager
使用 Manager API 傳送訊息給 client (agent)
class TamashiiRailsHook < Tamashii::Hook
def initialize(*args)
super
@client = @env[:client]
end
def call(pkt)
# …
pkt = Tamashii::Packet.new(...)
@client.send(pkt.dump)
end
end
測試模式 (Agent)
非測試模式下,Agent 需要真的硬體設備才可以運作
否則硬體元件相關的程式碼會初始化失敗
使用測試模式
脫離硬體元件
測試邏輯
跑 rspec
測試模式 (Agent)
使用測試模式
偽讀卡機與偽蜂鳴器
模擬硬體設備的行為
偽讀卡機:隨機一段時間後,造出一個卡號訊息
偽蜂鳴器:以文字顯示的方式取代發出聲音
Tamashii::Agent.config do
env 'test'
auth :token
token 'abc123'
end
測試模式 (Agent)
Master
Buzzer
Adapter
Buzzer
GPIO Buzzer
FakeBuzzer
CardReader
Adapter
CardReader
MFRC522
Fake
CardReader
Connection
Non-test
mode
Test
mode
測試模式 (Agent)
部署測試模式
使用 Standalone Manager
使用預設 handler (廣播封包)
$ tamashii-manager -C manager_config.rb -p 3333
Tamashii::Manager.config do
env 'test'
auth :token
token 'abc123'
end
測試模式 (Agent)
部署測試模式
使 Agent 連上 Manager
$ tamashii-agent -C agent_config.rb
Tamashii::Agent.config do
manager_host '127.0.0.1'
manager_port 3333
env 'test'
auth :token
token 'abc123'
end
測試模式 – Agent 端
測試模式 – Manager 端
測試模式
剛才的範例中,Agent 似乎有 error
測試模式
Error 原因:沒有建立 handler
Manager 端只有單純廣播訊息
並沒有告知 Agent 該張卡片的驗證結果
Agent 端等待一段時間仍沒有得到回覆,視為發生
error
測試模式
範例:在 Standalone模式下實作簡易 handler
接收 Agent 的卡號資訊,將驗證結果廣播回去
驗證結果僅簡單使用一對一錯的方式
第一組卡號:no
第二組卡號:ok
測試模式
直接在 manager_config.rb 中實作
class MyPacketHandler < Tamashii::Handler
def self.init_counter
@@counter = 0
end
# 一定要實作的方法
def resolve(request_json)
request_data = JSON.parse request_json
@@counter += 1
client = @env[:client]
packet_id = request_data["id"]
card_id = request_data["ev_body"]
測試模式
pkt_type = Tamashii::Type::RFID_RESPONSE_JSON
result = {
auth: @@counter % 2 == 0,
reason: "You are: #{card_id}“
}
# packet data 一定要是字串
pkt_data = {
id: packet_id,
ev_body: result.to_json
}.to_json
pkt = Tamashii::Packet.new(
pkt_type, client.tag, pkt_data)
client.channel.broadcast(pkt.dump)
end
end
測試模式
最後記得註冊這一個 handler
MyPacketHandler.init_counter
Tamashii::Resolver.config do
handle Tamashii::Type::RFID_NUMBER, MyPacketHandler
end
測試模式
Agent 端收到的結果
未來方向
支援其他設備,如 LCD 顯示板、相機等
目前僅以打卡系統為雛型設計
對於其他應用可能仍須更進一步 refactor
Agent 端的元件設計還是寫得有點死 (不夠彈性)
Agent 與 Manager 之間的認證
目前是寫死的 token
其他認證:非對稱金鑰 (SSH)
用 Ruby 開發 IoT 應用 - 以 RubyConf.tw 打卡系統為例

More Related Content

Viewers also liked

Presentacion de pasos sobre de hacer ejercicios de cables
Presentacion de pasos sobre de hacer ejercicios de cablesPresentacion de pasos sobre de hacer ejercicios de cables
Presentacion de pasos sobre de hacer ejercicios de cables
Crisbel93
 
Segredos Sombrios
Segredos SombriosSegredos Sombrios
Segredos Sombrios
400200
 
Неделя профилактики наркозависимости «Независимое детство»
Неделя профилактики наркозависимости «Независимое детство»Неделя профилактики наркозависимости «Независимое детство»
Неделя профилактики наркозависимости «Независимое детство»
Irina Kutuzova
 
Arc2625 logsheet
Arc2625 logsheet Arc2625 logsheet
Arc2625 logsheet
Lynnstyles
 
Ahmed Saleh (1)
Ahmed Saleh  (1)Ahmed Saleh  (1)
Ahmed Saleh (1)
Ahmed Saleh Metwali
 
10 наурыз 2017
10 наурыз 201710 наурыз 2017
10 наурыз 2017
Қазығұрт Тынысы
 
Ahmed Saleh (2)
Ahmed Saleh  (2)Ahmed Saleh  (2)
Ahmed Saleh (2)
Ahmed Saleh Metwali
 

Viewers also liked (7)

Presentacion de pasos sobre de hacer ejercicios de cables
Presentacion de pasos sobre de hacer ejercicios de cablesPresentacion de pasos sobre de hacer ejercicios de cables
Presentacion de pasos sobre de hacer ejercicios de cables
 
Segredos Sombrios
Segredos SombriosSegredos Sombrios
Segredos Sombrios
 
Неделя профилактики наркозависимости «Независимое детство»
Неделя профилактики наркозависимости «Независимое детство»Неделя профилактики наркозависимости «Независимое детство»
Неделя профилактики наркозависимости «Независимое детство»
 
Arc2625 logsheet
Arc2625 logsheet Arc2625 logsheet
Arc2625 logsheet
 
Ahmed Saleh (1)
Ahmed Saleh  (1)Ahmed Saleh  (1)
Ahmed Saleh (1)
 
10 наурыз 2017
10 наурыз 201710 наурыз 2017
10 наурыз 2017
 
Ahmed Saleh (2)
Ahmed Saleh  (2)Ahmed Saleh  (2)
Ahmed Saleh (2)
 

Similar to 用 Ruby 開發 IoT 應用 - 以 RubyConf.tw 打卡系統為例

Weibo lamp improvements
Weibo lamp improvementsWeibo lamp improvements
Weibo lamp improvements
Xinchen Hui
 
夸父通讯中间件
夸父通讯中间件夸父通讯中间件
夸父通讯中间件
Open Party
 
美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术团队
 
轻量级Flash服务器开发框架(刘恒)
轻量级Flash服务器开发框架(刘恒)轻量级Flash服务器开发框架(刘恒)
轻量级Flash服务器开发框架(刘恒)FLASH开发者交流会
 
Lamp高性能设计
Lamp高性能设计Lamp高性能设计
Lamp高性能设计锐 张
 
lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用hugo
 
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型Jackson Tian
 
Phalcon phpconftw2012
Phalcon phpconftw2012Phalcon phpconftw2012
Phalcon phpconftw2012
Rack Lin
 
⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨
Wen-Tien Chang
 
高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕ideawu
 
Open whisk makes your cloud serverless 20180320
Open whisk makes your cloud serverless 20180320Open whisk makes your cloud serverless 20180320
Open whisk makes your cloud serverless 20180320
Ying Chun Guo
 
Rpc原理与实现
Rpc原理与实现Rpc原理与实现
Rpc原理与实现
wavefly
 
Non-MVC Web Framework
Non-MVC Web FrameworkNon-MVC Web Framework
Non-MVC Web Framework
Fred Chien
 
Using google appengine_final
Using google appengine_finalUsing google appengine_final
Using google appengine_finalWei Sun
 
J Ruby和Rails 让Ruby语言融入Java项目
J Ruby和Rails 让Ruby语言融入Java项目J Ruby和Rails 让Ruby语言融入Java项目
J Ruby和Rails 让Ruby语言融入Java项目George Ang
 
Erlang游戏开发
Erlang游戏开发Erlang游戏开发
Erlang游戏开发
litaocheng
 
Ruby rails分享
Ruby rails分享Ruby rails分享
Ruby rails分享
Cam Song
 
D2_Node在淘宝的应用实践
D2_Node在淘宝的应用实践D2_Node在淘宝的应用实践
D2_Node在淘宝的应用实践Jackson Tian
 
twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC
 

Similar to 用 Ruby 開發 IoT 應用 - 以 RubyConf.tw 打卡系統為例 (20)

Weibo lamp improvements
Weibo lamp improvementsWeibo lamp improvements
Weibo lamp improvements
 
夸父通讯中间件
夸父通讯中间件夸父通讯中间件
夸父通讯中间件
 
美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用美团点评技术沙龙05 - 前后端联调方案探索与应用
美团点评技术沙龙05 - 前后端联调方案探索与应用
 
Ali-tomcat
Ali-tomcatAli-tomcat
Ali-tomcat
 
轻量级Flash服务器开发框架(刘恒)
轻量级Flash服务器开发框架(刘恒)轻量级Flash服务器开发框架(刘恒)
轻量级Flash服务器开发框架(刘恒)
 
Lamp高性能设计
Lamp高性能设计Lamp高性能设计
Lamp高性能设计
 
lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用
 
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
从无阻塞并行脚本加载(Lab.js)到浏览器消息模型
 
Phalcon phpconftw2012
Phalcon phpconftw2012Phalcon phpconftw2012
Phalcon phpconftw2012
 
⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨⼤語⾔模型 LLM 應⽤開發入⾨
⼤語⾔模型 LLM 應⽤開發入⾨
 
高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕
 
Open whisk makes your cloud serverless 20180320
Open whisk makes your cloud serverless 20180320Open whisk makes your cloud serverless 20180320
Open whisk makes your cloud serverless 20180320
 
Rpc原理与实现
Rpc原理与实现Rpc原理与实现
Rpc原理与实现
 
Non-MVC Web Framework
Non-MVC Web FrameworkNon-MVC Web Framework
Non-MVC Web Framework
 
Using google appengine_final
Using google appengine_finalUsing google appengine_final
Using google appengine_final
 
J Ruby和Rails 让Ruby语言融入Java项目
J Ruby和Rails 让Ruby语言融入Java项目J Ruby和Rails 让Ruby语言融入Java项目
J Ruby和Rails 让Ruby语言融入Java项目
 
Erlang游戏开发
Erlang游戏开发Erlang游戏开发
Erlang游戏开发
 
Ruby rails分享
Ruby rails分享Ruby rails分享
Ruby rails分享
 
D2_Node在淘宝的应用实践
D2_Node在淘宝的应用实践D2_Node在淘宝的应用实践
D2_Node在淘宝的应用实践
 
twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸twMVC#01 | ASP.NET MVC 的第一次親密接觸
twMVC#01 | ASP.NET MVC 的第一次親密接觸
 

用 Ruby 開發 IoT 應用 - 以 RubyConf.tw 打卡系統為例

Editor's Notes

  1. - 2015 RubyconfTW 有看到 Python 版的打卡機,當時已設計在pi上 - 沒有繼續維護,該團隊沒下文 - 功能有限,但礙於語言隔閡與架構,難以擴充 - Ruby 圈仍無類似的作品 - 公司買了幾台 PI 與讀卡設備 - 以 Ruby 重刻打卡系統,為 2016 RubyconfTW 做準備
  2. - 2015 RubyconfTW 有看到 Python 版的打卡機,當時已設計在pi上 - 沒有繼續維護,該團隊沒下文 - 功能有限,但礙於語言隔閡與架構,難以擴充 - Ruby 圈仍無類似的作品 - 公司買了幾台 PI 與讀卡設備 - 以 Ruby 重刻打卡系統,為 2016 RubyconfTW 做準備
  3. 詢問有無參加conf 2016
  4. 等等會細講
  5. - 使用 HTTP 而不是 Raw TCP - 可套用現存的 SSL(HTTPS)來加密 - 可輕易整合到 Rails 中 - 雙向連線 - Agent->Manager: 打卡結果 - Manager->Agent: 非同步指令 - 傳統 HTTP API 只能達到 Agent->Manager - 若要 Manager->Agent,就得用昂貴的 polling
  6. - 使用 HTTP 而不是 Raw TCP - 可套用現存的 SSL(HTTPS)來加密 - 可輕易整合到 Rails 中 - 雙向連線 - Agent->Manager: 打卡結果 - Manager->Agent: 非同步指令 - 傳統 HTTP API 只能達到 Agent->Manager - 若要 Manager->Agent,就得用昂貴的 polling
  7. - 使用 HTTP 而不是 Raw TCP - 可套用現存的 SSL(HTTPS)來加密 - 可輕易整合到 Rails 中 - 雙向連線 - Agent->Manager: 打卡結果 - Manager->Agent: 非同步指令 - 傳統 HTTP API 只能達到 Agent->Manager - 若要 Manager->Agent,就得用昂貴的 polling
  8. - WebSocket 的使用 - HTTP + 雙向連線 (簡單介紹一下) - Rails 中已有 WebSocket 的實作:Action Cable - 不必重新實作 WebSocket Server 邏輯與連線管理 - 只需要注重資料交換就好 - 使用 Action Cable - Action Cable 是替 Web Application 設計的 - 官方提供的 client 端使用 Javascript - 推出之初並沒有找到 Ruby 的 client 端 - 我們相信不久後會有 Ruby 的解決方案 - 但當下為了開發進度,仍必須要有連線的手段 - 模組化:分離連線端與晶片控制端 - 方便之後抽換
  9. 使用 Action Cable - Action Cable 是替 Web Application 設計的 - 官方提供的 client 端使用 Javascript - 推出之初並沒有找到 Ruby 的 client 端 - 我們相信不久後會有 Ruby 的解決方案 - 但當下為了開發進度,仍必須要有連線的手段 - 模組化:分離連線端與晶片控制端 - 方便之後抽換
  10. - 暫時的解決方法:用 Ruby 包裹 browser 執行 JS - 為了提供完整的 JS 環境,使用 browser 是最直接的 - 問題: - 如何在CLI中啟動以GUI為主的瀏覽器 - 如何以指令的方式控制瀏覽器的行為 - 解決方法:使用 headless + xhvd - (範例code) - 以文字操作的方式送指令來執行JS
  11. - 暫時的解決方法:用 Ruby 包裹 browser 執行 JS - 為了提供完整的 JS 環境,使用 browser 是最直接的 - 問題: - 如何在CLI中啟動以GUI為主的瀏覽器 - 如何以指令的方式控制瀏覽器的行為 - 解決方法:使用 headless + Xvfb - (範例code) - 以文字操作的方式送指令來執行JS
  12. - 注意!這裡帶過就好 - 暫時的解決方法:用 Ruby 包裹 browser 執行 JS - 為了提供完整的 JS 環境,使用 browser 是最直接的 - 問題: - 如何在CLI中啟動以GUI為主的瀏覽器 - 如何以指令的方式控制瀏覽器的行為 - 解決方法:使用 headless + Xvfb - (範例code) - 以文字操作的方式送指令來執行JS
  13. - 暫時的解決方法:用 Ruby 包裹 browser 執行 JS - 為了提供完整的 JS 環境,使用 browser 是最直接的 - 問題: - 如何在CLI中啟動以GUI為主的瀏覽器 - 如何以指令的方式控制瀏覽器的行為 - 解決方法:使用 headless + Xvfb - (範例code) - 以文字操作的方式送指令來執行JS
  14. - 後來的解決方法 - 開發一段時間後,有關 Action Cable 的 gem 也越來越多 - 最後發現了一個 gem: action_cable_client - 如字面上所述,就是一個純 Ruby 的 Action Cable client library - 以純 Ruby 的方式實作了 Action Cable 的 protocol - 經過測試後,抽換掉當初的連線模組
  15. ## 部署遭遇到的問題 - action_cable_client 在網路不穩時反應不夠靈敏 - 會場網路偶爾會斷線 - Timeout 時間太長,Agent 沒有寫斷線回報機制 - 斷線常常需要人為檢查 - 該 gem 仍在開發階段,某些情況下會造成連線卡死 - 有時網路中斷恢復後,除非重開整支程式,否則連線無法恢復 - Agent 端雖切割模組,但仍在同一個 thread 底下,需整個重啟 - Agent 管理(Manager)與打卡應用沒有切割乾淨,牽一髮動全身 - Manager 如果要出事就得連 Rails app一同重啟
  16. ## 部署遭遇到的問題 - action_cable_client 在網路不穩時反應不夠靈敏 - 會場網路偶爾會斷線 - Timeout 時間太長,Agent 沒有寫斷線回報機制 - 斷線常常需要人為檢查 - 該 gem 仍在開發階段,某些情況下會造成連線卡死 - 有時網路中斷恢復後,除非重開整支程式,否則連線無法恢復 - Agent 端雖切割模組,但仍在同一個 thread 底下,需整個重啟 - Agent 管理(Manager)與打卡應用沒有切割乾淨,牽一髮動全身 - Manager 如果要出事就得連 Rails app一同重啟
  17. - 分離 Manager 與 Rails app - 不需要 Action Cable,因此可與 Rails 切割開 - Rack-based:可 mount 到 Rails 中的組件 - Action Cable 也是 Rack-based - Manager設計: - Rack-based - Rack socket hijacking - 利用 url 判斷,當滿足指定的路徑(如 /cable ),就將 socket 取出自行管理 - 從 Action Cable 的原始碼中擷取部分概念,並予以改良 - Manager 架構圖
  18. - 分離 Manager 與 Rails app - 不需要 Action Cable,因此可與 Rails 切割開 - Rack-based:可 mount 到 Rails 中的組件 - Action Cable 也是 Rack-based - Manager設計: - Rack-based - Rack socket hijacking - 利用 url 判斷,當滿足指定的路徑(如 /cable ),就將 socket 取出自行管理 - 從 Action Cable 的原始碼中擷取部分概念,並予以改良 - Manager 架構圖
  19. 這是脫離Rails運行時,Rails app 需要加入 channel 以便與client溝通
  20. 這是脫離Rails運行時,Rails app 需要加入 channel 以便與client溝通
  21. 一開始demo的那個其實就是新系統
  22. 看到Error message:之後會講解
  23. - 支援其他設備,如 LCD 顯示板等 - 目前僅以打卡系統為雛型設計 - Agent 與 Manager 之間的認證 - Manager 不應該接受任意的 Agent 註冊,而要認證 - 當前的認證方式是對稱的 token,亦即寫死在兩端的設定檔 - 未來可能會新增其他認證,如 SSH 等非對稱金鑰認證