Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
dRuby over BLE
Search
makicamel
June 08, 2026
Programming
45
1
Share
dRuby over BLE
dRuby over BLE: Device-to-Device Remote Method Calls
2026.06.06. 松江Ruby会議12
makicamel
June 08, 2026
More Decks by makicamel
See All by makicamel
Road to RubyKaigi: Play Hard(ware)
makicamel
1
640
First step to PicoRuby
makicamel
2
550
PicoRuby on Rails
makicamel
4
280
Take a small step beyond the api
makicamel
2
210
Road to RubyKaigi: Making Tinny Chiptunes with Ruby
makicamel
4
1.8k
Road to RubyKaigi
makicamel
4
690
Rails アプリ地図考 Flush Cut
makicamel
1
230
ErdMap: Thinking about a map for Rails applications
makicamel
2
4.1k
dRuby 入門者によるあなたの身近にあるdRuby 入門
makicamel
4
1.7k
Other Decks in Programming
See All in Programming
TypeScriptだけでAIエージェントを作る フロント・エージェント・インフラのフルスタック実践
har1101
6
1.2k
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
330
Transactional Change Stream Processing With Debezium and Apache Flink
gunnarmorling
1
140
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
200
Inside Stream API
skrb
1
480
New "Type" system on PicoRuby
pocke
1
400
SPMマルチモジュールで テストカバレッジを取得する技法
yosshi4486
0
140
AI 時代のソフトウェア設計の学び方
masuda220
PRO
29
11k
AIチームを指揮するOSS「TAKT」活用術 / How to Use “TAKT,” an OSS Tool for Orchestrating AI Teams
nrslib
6
760
新規プロダクトを高速で生み出すハーネスエンジニアリング
seanchas116
19
7.7k
Spec-Driven Development with AI-Agents: From High-Level Requirements to Working Software
antonarhipov
2
400
色即是空、空即是色、データサイエンス
kamoneggi
1
260
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
340
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
The Illustrated Children's Guide to Kubernetes
chrisshort
51
52k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
370
Darren the Foodie - Storyboard
khoart
PRO
3
3.4k
Color Theory Basics | Prateek | Gurzu
gurzu
0
320
Rails Girls Zürich Keynote
gr2m
96
14k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
190
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.2k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Transcript
E3VCZPWFS#-& %FWJDFUP%FWJDF3FNPUF.FUIPE$BMMT !NBLJDBNFM দߐ3VCZձٞ 1 / 65
ࣗݾհ 🔴 !NBLJDBNFMݪສق 🔴 3VCZ💎ͱϏʔϧ🍻ͱ͓ञ͕͖ 🔴 1JDP1JDP3VCZͬͯ·͢ 🔴 3PBEUP3VCZ,BJHJͷ࡞ऀ 2
/ 65
3PBEUP3VCZ,BJHJ NBLJDBNFMSPBE@UP@SVCZLBJHJ IUUQTHJUIVCDPNNBLJDBNFMSPBE@UP@SVCZLBJHJ 3 / 65
3PBEUP3VCZ,BJHJ 🔴 3VCZJTUʹΑΔ3VCZJTUͷͨΊͷ3VCZͷήʔϜ 🔴 λʔϛφϧ্Ͱ༡ͿԣεΫϩʔϧΞΫγϣϯήʔϜ 🔴 όάΛ͠ʒ͔ΒಀΕͯ3VCZ,BJHJࢀՃΛࢦ͢ 4 / 65
3PBEUP3VCZ,BJHJ⭐ 🔴 !3VCZ,BJHJ-5 🔴 1JDP3VCZͱ ՃηϯαʔͰͭ͘Δ ήʔϜίϯτϩʔϥ 3PBEUP3VCZ,BJHJ1MBZ)BSE XBSF !NBLJDBNFM
IUUQTTQFBLFSEFDLDPNNBLJDBNFMSPBEUPSVCZLBJHJQMBZIBSEXBSF 5 / 65
ొਓ 1JDP3VCZ ΈࠐΈ͚3VCZ ηϯαʔͳͲͱଓͯ͠ ͖ͳσόΠεΛͭ͘ΕΔ QJDPSVCZQJDPSVCZ IUUQTHJUIVCDPNQJDPSVCZQJDPSVCZ 6 / 65
ొਓ 1JDP3VCZ ʢ3BTQCFSSZ1J1JDP8ʣ ΈࠐΈ͚3VCZ ηϯαʔͳͲͱଓͯ͠ ͖ͳσόΠεΛͭ͘ΕΔ QJDPSVCZQJDPSVCZ IUUQTHJUIVCDPNQJDPSVCZQJDPSVCZ 7 /
65
ొਓ ίϯτϩʔϥ 8 / 65
ొਓ Ճηϯα 9 / 65
ొਓ Ճηϯα ՃηϯαͷΛ 3PBEUP3VCZ,BJHJʹ͍ͨ͠ 3PBEUP3VCZ,BJHJ 10 / 65
ొਓ 1JDP3VCZ Ճηϯα 1JDP3VCZͰ ՃηϯαͷΛಡΈऔΓ 3PBEUP3VCZ,BJHJ 11 / 65
ొਓ 1JDP3VCZ #MVFUPPUIͰ 3PBEUP3VCZ,BJHJʹૹ৴ 3PBEUP3VCZ,BJHJ 12 / 65
ొਓ 1JDP3VCZ #MVFUPPUIͰ 3PBEUP3VCZ,BJHJʹૹ৴ Ͱ͖ͳ͍ 3PBEUP3VCZ,BJHJ 13 / 65
ొਓ 1JDP3VCZ #MVFUPPUIͷ ΫϩεϓϥοτϑΥʔϜͳ 3VCZΫϥΠΞϯτ͕ͳ͍ #MVFUPPUIͰ 3PBEUP3VCZ,BJHJʹૹ৴ Ͱ͖ͳ͍ 3PBEUP3VCZ,BJHJ 14
/ 65
ొਓ ϒϥβ 8FC#MVFUPPUI"1* 8FC#MVFUPPUI"1*8FC"1*c.%/ IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC"1*8FC@#MVFUPPUI@"1* 15 / 65
ొਓ ϒϥβ 8FC#MVFUPPUI"1* 8&#SJDLαʔό 3PBEUP3VCZ,BJHJ 16 / 65
ొਓ 1JDP3VCZ #MVFUPPUI ϒϥβ 8&#SJDLαʔό 3PBEUP3VCZ,BJHJ 17 / 65
ొਓ 1JDP3VCZ #MVFUPPUI ϒϥβ )551 8&#SJDLαʔό 3PBEUP3VCZ,BJHJʹ ૹ৴Ͱ͖ͨ 3PBEUP3VCZ,BJHJ 18
/ 65
#MVFUPPUI 19 / 65
#-& 🔴 #MVFUPPUI-PX&OFSHZ 🔴 লిྗ͚#MVFUPPUIن֨ 🔴 3BTQCFSSZ1J1JDP 8ʹແઢνοϓ͕͍ͬͯΔ 🔴
1JDP3VCZ͔Βѻ͑Δ ֓೦ɾ͓࡞๏͕ Ή͔͍ͣ͠ 20 / 65
#-&6"35 🔴 6"35 🔴 ػثΛཧઢͰͭͳ͍ͰํʹόΠτΛૹΔ௨ ৴ํࣜ 🔴 #-&6"35 🔴 6"35Λ#-&ͰԾతʹ࣮ݱ͢Δ1JDP3VCZͷ࣮
🔴 *0ͷΑ͏ͳΠϯλʔϑΣʔεͰѻ͑Δ #-&6"35QJDPSVCZQJDPSVCZ IUUQTHJUIVCDPNQJDPSVCZQJDPSVCZUSFFNBTUFSNSCHFNTQJDPSVCZCMFVBSU 21 / 65
#-&6"35 # ૹ৴ଆ(PicoRuby) ble_uart = BLE::UART.new ble_uart.start do if ble_uart.connected?
ble_uart.puts('Hello, BLE::UART!') end end 3VCZͬΆ͍ʂ 22 / 65
#-&6"35 # ड৴ଆ(PicoRuby.WASM) # ηοτΞοϓ @buffer = '' server =
@device.connect service = server.service(@svc_uuid) @rx_char = service.characteristic(@rx_uuid) @rx_char.on_change { |data| @buffer << data } @rx_char.start_notify 23 / 65
#-&6"35 # ड৴ଆ(PicoRuby.WASM) # @bufferΛҰఆ࣌ؒຖʹνΣοΫ͢Δ while (idx = @buffer.index(SEPARATOR)) line
= @buffer.slice!(0..idx).strip line.split(SAMPLE_SEPARATOR) .each { |sample| send_data(sample) } end 3VCZͬΆ͍ʜʜʁ 24 / 65
#-&6"35 🔴 )551 🔴 ϦΫΤετϝοηʔδ 🔴 #-&6"35 🔴 όΠτετϦʔϜ 🔴
ड৴ϝοηʔδ 🔴 FH ෳϝοηʔδɺϝοηʔδ్͕தͰ͖ΕΔ 🔴 ηύϨʔλͰ۠Γͯࣗ͠ͰΈཱͯΔ 25 / 65
#-&6"35 3VCZͬΆ͘ॻ͖͍ͨʂ 26 / 65
E3VCZ 27 / 65
E3VCZ 🔴 EJTUSJCVUJPO3VCZ 🔴 ࢄ3VCZ 🔴 ࢄΦϒδΣΫτγεςϜΛ࣮ݱ͢ΔϥΠϒϥϦ 🔴 ؔকढ़͞Μ࡞ MJCSBSZESC
3VCZϦϑΝϨϯεϚχϡΞϧ IUUQTEPDTSVCZMBOHPSHKBMBUFTUMJCSBSZESCIUNM 28 / 65
E3VCZ 🔴 ϓϩηεωοτϫʔΫΛ͑ͯϝοηʔδΛૹΔ 🔴 ଞϓϩηεͷΦϒδΣΫτͷϝιουΛݺΔ 29 / 65
E3VCZ { greeting: 'Hello, Matsue!' } E3VCZೖऀʹΑΔ͋ͳͨͷۙʹ͋ΔE3VCZೖ!NBLJDBNFM IUUQTTQFBLFSEFDLDPNNBLJDBNFMESVCZBUUSBDUJPO 30 /
65
E3VCZ { greeting: 'Hello, Matsue!' object[:greeting] } E3VCZೖऀʹΑΔ͋ͳͨͷۙʹ͋ΔE3VCZೖ!NBLJDBNFM IUUQTTQFBLFSEFDLDPNNBLJDBNFMESVCZBUUSBDUJPO 31
/ 65
E3VCZ { greeting: 'Hello, Matsue!' object[:greeting] } # => 'Hello,
Matsue!' E3VCZೖऀʹΑΔ͋ͳͨͷۙʹ͋ΔE3VCZೖ!NBLJDBNFM IUUQTTQFBLFSEFDLDPNNBLJDBNFMESVCZBUUSBDUJPO 32 / 65
E3VCZ 🔴 3VCZͬΆ͍ʂ 🔴 #-&͝͠ʹผϓϩηεͷΦϒδΣΫτΛ͞ΘΓ͍ͨ 33 / 65
E3VCZPWFS#-& 34 / 65
E3VCZPWFS#-& E3VCZϓϩτίϧ͕ࠩ͠ସ͑Մೳ 🔴 ϏϧτΠϯ 🔴 Ϣʔβʔ֦ு 🔴 5$1 🔴 8FC4PDLFU
🔴 6/*9υϝΠϯιέοτ 🔴 44- 35 / 65
E3VCZPWFS#-& E3VCZϓϩτίϧ͕ࠩ͠ସ͑Մೳ 🔴 ϏϧτΠϯ 🔴 Ϣʔβʔ֦ு 🔴 5$1 🔴 8FC4PDLFU
🔴 6/*9υϝΠϯιέοτ 🔴 #-&🆕 GPS1JDP3VCZ1JDP3VCZ8"4. 🔴 44- 36 / 65
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶃΦϒδΣΫτΛެ։ front = Calc.new DRb.start_service( "ble://picoruby", front)
37 / 65
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") "ble://picoruby", front) 38 / 65
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") "ble://picoruby", front) ᶅϝοηʔδૹ৴ obj.add(1, 2) όΠτྻมͯ͠ૹ৴ όΠτྻΛૹड৴ 39 / 65
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") "ble://picoruby", front) ᶅϝοηʔδૹ৴ ᶆϝιουίʔϧ obj.add(1, 2) όΠτྻΛมͯ͠ϝιουίʔϧ όΠτྻมͯ͠ૹ৴ front.send(msg_id, *args) όΠτྻΛૹड৴ 40 / 65
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") "ble://picoruby", front) ᶅϝοηʔδૹ৴ ᶆϝιουίʔϧ obj.add(1, 2) όΠτྻΛมͯ͠ϝιουίʔϧ όΠτྻมͯ͠ૹ৴ front.send(msg_id, *args) όΠτྻΛૹड৴ ᶇ݁ՌΛฦ͢ # => 3 41 / 65
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") "ble://picoruby", front) ᶅϝοηʔδૹ৴ ᶆϝιουίʔϧ obj.add(1, 2) όΠτྻΛมͯ͠ϝιουίʔϧ όΠτྻมͯ͠ૹ৴ front.send(msg_id, *args) όΠτྻΛૹड৴ ᶈ݁ՌΛड͚औΔ ᶇ݁ՌΛฦ͢ # => 3 # => 3 42 / 65
όΠτྻͷૹड৴ 🔴 DRbMessage 🔴 ϝιουίʔϧɾΓˡˠόΠτྻͷมΛߦ͏ 🔴 ௨৴࿏ʹͤΒΕΔͷόΠτྻ͚ͩ 🔴 τϥϯεϙʔτͱૄ݁߹ 43
/ 65
όΠτྻͷૹड৴ 🔴 τϥϯεϙʔτ 🔴 FH 🔴 5$1 🔴 8FC4PDLFU 🔴
#-& 🔴 1JDP3VCZɾ4%,Ͱ࣮͞Ε͍ͯΔ 44 / 65
όΠτྻͷૹड৴ 🔴 DRbMessage τϥϯεϙʔτ 🔴 "1*ͷཁ݅ͱ࣮ଶʹ͕ࠩ͋Δ DRbMessage#recv_message | | |
BLE::UART#read_nonblock 45 / 65
όΠτྻͷૹड৴ 🔴 DRbMessage ιέοττϥϯεϙʔτ 🔴 "1*ͷཁ݅ͱ࣮ଶͷࠩΛٵऩ͢ΔιέοτΛ࣮͢Δ DRbMessage#recv_message | Adapter#read |
BLE::UART#read_nonblock 46 / 65
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") #-&༻ιέοτΛ "ble://picoruby", front) ࣮͢Δ͚ͩ ᶅϝοηʔδૹ৴ ᶆϝιουίʔϧ obj.add(1, 2) όΠτྻΛมͯ͠ϝιουίʔϧ όΠτྻมͯ͠ૹ৴ front.send(msg_id, *args) όΠτྻΛૹड৴ 47 / 65
%3C#-&"EBQUFS 🔴 όΠτྻʹର͢Δૢ࡞छྨ 🔴 read 🔴 write DRb::BLE::Adapter#close࣮͠·͕͢ࠓճׂѪ 48 /
65
%3C#-&"EBQUFS 🔴 DRbMessage 🔴 BLE::UART #recv_message(n) #read_nonblock(n) 🔴 ϒϩοΩϯάඞཁ 🔴
ϒϩοΩϯά͠ͳ͍ 🔴 ஸOόΠτ΄͍͠ 🔴 ʙOόΠτΛฦ͢ ͜ͷࠩΛ DRb::BLE::Adapter#read Ͱٵऩ͢Δ 49 / 65
%3C#-&"EBQUFS def read(n) ड৴όοϑΝʹ until @uart.available >= n OόΠτ #
... ཷ·Δ·Ͱͭ ϒϩοΩϯά sleep_ms 10 end end 50 / 65
%3C#-&"EBQUFS def read(n) until @uart.available >= n # ... @uart.poll_once
ड৴ύέοτΛ sleep_ms 10 όοϑΝʹੵΉ end end 51 / 65
%3C#-&"EBQUFS def read(n) until @uart.available >= n # ... @uart.poll_once
sleep_ms 10 end OόΠτཷ·ͬͨΒ @uart.read_nonblock(n) औΓग़ͯ͠ฦ͢ end 52 / 65
%3C#-&"EBQUFS 🔴 DRbMessage 🔴 BLE::UART #send_request(data) #write(data) ࣗͷλΠϛϯάͰόΠτΛૹΕΑ͍ 53 /
65
%3C#-&"EBQUFS ͦͷ··సૹ͢Δ def write(data) @uart.write(data) end 54 / 65
%3C#-& 🔴 ιέοτ͕Ͱ͖ͨ🙌 🔴 αʔόͷ࣮ 🔴 Πϯελϯε࡞ͬͨΓ 🔴 ϝοηʔδΛड͚औͬͯϝιουίʔϧͯ͠ฦ͠ ͨΓ͢Δ͚ͩ
55 / 65
ΞϓϦଆίʔυ 🔴 CFGPSF # ड৴ଆ(PicoRuby.WASM) # ηοτΞοϓ @buffer = ''
server = @device.connect service = server.service(@svc_uuid) @rx_char = service.characteristic(@rx_uuid) @rx_char.on_change { |data| @buffer << data } @rx_char.start_notify # @bufferΛҰఆ࣌ؒຖʹνΣοΫ͢Δ while (idx = @buffer.index(SEPARATOR)) line = @buffer.slice!(0..idx).strip line.split(SAMPLE_SEPARATOR) .each { |sample| send_data(sample) } end Ή͔͍ͣ͠ʜʜ 56 / 65
ΞϓϦଆίʔυ 🔴 BGUFS # ड৴ଆ(PicoRuby.WASM) # ηοτΞοϓ @obj = DRb::DRbObject.new_with_uri(uri)
# @obj.readΛҰఆ࣌ؒຖʹίʔϧ͢Δ @obj.read.each { |sample| send_data(sample) } 3VCZͬΆ͍ʂ 57 / 65
σϞ 58 / 65
σϞ 🔴 ಈ͍ͯͳ͍ʜʜʁ 🔴 ඵؒαϯϓϧ͕Γ͍ͯͳ͍ 59 / 65
༨ஊ 🔴 ϙʔϦϯάϨʔτԼ 🔴 CFGPSF 🔴 αϯϓϧඵ 🔴 BGUFS 🔴
αϯϓϧඵ 😇 60 / 65
༨ஊ 🔴 ϙʔϦϯάϨʔτԼ ʮήʔϜίϯτϩʔϥΈ͍ͨͳͷʹ ɹSFRVFTUSFQMZܕͷ௨৴͖·ͤΜʯ ʮ😇ʯ 61 / 65
༨ஊ 🔴 E3VCZ 🔴 QVTI 🔴 SFRVFTUSFQMZܕ 🔴 ҰํͷετϦʔϜ 🔴
ຖճ 🔴 ߴසʹૹΕͯԆ ૹ৴ɾػɾड৴ 🔴 ฦࣄෆཁ 🔴 ௨৴ճ͕૿͑Δ 🔴 ฦࣄΛͭ͘ͳΔ ༻్ʹ͋ͬͨํ๏ Λબ΅͏ ήʔϜίϯτϩʔϥQVTIܕ͖ 62 / 65
͓͠Βͤ 63 / 65
1JDP3VCZ,BJHJ "TTFNCMFΓ·͢ 64 / 65
1JDP3VCZ,BJHJ "TTFNCMFΓ·͢ 🔴 1JDP3VCZΛͭ͘Δɺ1JDP3VCZͰͭ͘Δ 🔴 ϓϩϙʔβϧืूࠓ݄։͖·͢ 🔴 🔴
!ळ༿ݪ 🔴 IUUQTQJDPSVCZLBJHJPSH 65 / 65