iT邦幫忙

2021 iThome 鐵人賽

DAY 20
0
Software Development

在麥塊的農場裡寫 Lua系列 第 20

Day20 讓電腦透過數據機和有線、無線網路傳遞訊息

  • 分享至 

  • xImage
  •  

上一回講的是透過數據機連結各種電腦週邊
今天來分享數據機更強大的功能,傳遞訊息
可以先查詢 modems 說明文件

help modems

可以看到 modem 的指令很簡單,只有幾個如下

  • open( channel )
  • isOpen( channel )
  • close( channel )
  • closeAll()
  • transmit( channel, replyChannel, message )
  • isWireless()
    以及一個 modem_message 事件

我們先試試用 Wired Modem 連接兩台電腦
並且跟上次一樣,兩端的數據機都要按下滑鼠右鍵,讓它出現紅色框表示連結成功
接著可以自定義誰是傳送端電腦,誰是接收端電腦
以下是我的參考程式碼

傳送端

傳送端的 channel 不需要 open,這是實測結果,我也不知道為什麼
至於 replyChannel 則是可有可無,如果有打算接收回應,就需要 open,否則會收不到回應訊息
從程式碼可看出,我這台電腦接了左右兩台數據機,並各自連接一台電腦
也就是說,我可以同時傳送訊息給多台電腦

senderChannel = 123     -- channel 自定義 0 ~ 65535
replyChannel = 456
-- modem.open(senderChannel)
print('modem is open: ' .. tostring(modem.isOpen(senderChannel)))
print('modem is wireless: ' .. tostring(modem.isWireless(senderChannel)))
modemLeft = peripheral.wrap('left');
modemRight = peripheral.wrap('right');
modemLeft.open(replyChannel)
modemRight.open(replyChannel)
modemLeft.transmit(senderChannel, replyChannel, "hello do you hear me ?")
modemRight.transmit(senderChannel, replyChannel, "how are you ?")

接收端

這是接收端的程式碼,接收訊息的 channel 一定要打開,否則收不到訊息

senderChannel = 123
modem = peripheral.wrap('left');
modem.open(senderChannel)
print('modem is open: ' .. tostring(modem.isOpen(senderChannel)))
print('modem is wireless: ' .. tostring(modem.isWireless(senderChannel)))

event, side, senderChannel, replyChannel, msg, distance = os.pullEvent("modem_message")

print("event: " .. event)   -- 事件名稱:modem_message
print("side: " .. side)     -- 哪個方向的數據機收到訊息:left, right, front, back, top, bottom
print("sender channel: " .. senderChannel)  -- 收到訊息的 channel: 123
print("reply channel: " .. replyChannel)    -- 可以回應訊息的 channel: 456
print("message: " .. msg)                   -- 收到的訊息內容
print("distance: " .. distance)             -- 兩台數據機的距離

回應訊息

同樣的,如果要回應訊息,就使用 transmit API 即可,不過 channel 順序要對調

-- Reply message
modem.transmit(replyChannel, senderChannel, "I heared you")
-- 不打算繼續收訊息,可以關掉特定數據機的 channel
peripheral.wrap(side).close(senderChannel)
-- 或是直接關閉所有 channel
peripheral.wrap(side).closeAll()

那麼,可以傳送和回應都用一個 channel 就好嗎?
當然可以~ 這部分其實就是玩家自定義規則即可,CC: Tweaked 只是留這個彈性給大家發揮

傳輸 table 結構資料

這部分,電腦也自動幫我們做好序列化、反序列化了,真是太強大了!
傳輸不需要任何加工,收到的時候也還是個 table 結構

modem.transmit(senderChannel, replyChannel, { 1, 2, 3 })

但是問題來了,如果每次要傳送到遠端的電腦,就要拉線,那不累死嗎 ...
這跟實體世界的概念是一樣的,都什麼時代了還在到處佈線

Wireless Modem 登場

我們來試試 Wireless Modem,它的 API 用法跟 Wired Modem 其實是完全一樣的
但是具有這樣的優點

  1. Wireless Modem 不用佈線
  2. 傳送端只需要安裝一台 Wireless Modem,就可以傳送訊息給多個接收端

而它的無線傳輸可以多遠呢?
我實際做了測試,如下圖,接收端電腦在遙遠的彼方 ... (遠目)
CC: Tweaked Computer and Wireless Modem

在接收端收到訊息後,我將距離印出來,可以得知最遠的傳輸距離,應該不會超過 64 格方塊
CC: Tweaked Wireless Modem transmit distance

如果是原本的麥塊世界,要拉 64 格距離的遙控
要一堆紅石,中間還要穿插約 5, 6 個中繼器,多累啊!
但是說到紅石,我們可以透過紅石機關操控麥塊世界的全自動、半自動化
那電腦呢?總不能真的只是在麥塊世界打電腦寫 Code .....
這點 CC: Tweaked 也準備好了,可以參考
/rom/programs/redstone.lua
參考它一小段語法即可,也就是

redstone.setOutput('right', true)   -- 將電腦右方輸出紅石訊號!

我們可以在接收端電腦收到網路訊號後,接著啟動紅石訊號
接下來的應用就很豐富了,對吧!
CC: Tweaked Computer Redstone


上一篇
Day19 將電腦接上數據機和網路線
下一篇
Day21 用更高階的網路框架實現更多功能
系列文
在麥塊的農場裡寫 Lua30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言