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
340
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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
680
First step to PicoRuby
makicamel
2
570
PicoRuby on Rails
makicamel
4
290
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
700
Rails アプリ地図考 Flush Cut
makicamel
1
230
ErdMap: Thinking about a map for Rails applications
makicamel
2
4.2k
dRuby 入門者によるあなたの身近にあるdRuby 入門
makicamel
4
1.8k
Other Decks in Programming
See All in Programming
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
250
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
140
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
120
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
9
5.4k
メソッドのジェネリクスでGoの夢は広がるか? / Kyoto.go #65
utgwkk
3
780
OSもどきOS
arkw
0
570
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
260
AIで効率化できた業務・日常
ochtum
0
140
JJUG CCC 2026 Spring: JSpecify で実現する Kotlin フレンドリーな Java API 設計
ternbusty
1
170
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
240
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
250
ふつうのFeature Flag実践入門
irof
7
4k
Featured
See All Featured
The Language of Interfaces
destraynor
162
27k
Abbi's Birthday
coloredviolet
2
8.1k
A Soul's Torment
seathinner
6
2.9k
Marketing Yourself as an Engineer | Alaka | Gurzu
gurzu
0
240
How to train your dragon (web standard)
notwaldorf
97
6.7k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
1
350
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
330
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.6k
Designing for Timeless Needs
cassininazir
1
260
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
Paper Plane (Part 1)
katiecoart
PRO
0
9k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
940
Transcript
E3VCZPWFS#-& %FWJDFUP%FWJDF3FNPUF.FUIPE$BMMT !NBLJDBNFM দߐ3VCZձٞ 1 / 64
ࣗݾհ ! !NBLJDBNFMݪສق ! 3VCZ!ͱϏʔϧ"ͱ͓ञ͕͖ ! 1JDP1JDP3VCZͬͯ·͢ ! 3PBEUP3VCZ,BJHJͷ࡞ऀ 2
/ 64
3PBEUP3VCZ,BJHJ NBLJDBNFMSPBE@UP@SVCZLBJHJ IUUQTHJUIVCDPNNBLJDBNFMSPBE@UP@SVCZLBJHJ 3 / 64
3PBEUP3VCZ,BJHJ ! 3VCZJTUʹΑΔ3VCZJTUͷͨΊͷ3VCZͷήʔϜ ! λʔϛφϧ্Ͱ༡ͿԣεΫϩʔϧΞΫγϣϯήʔϜ ! όάΛ͠ʒ͔ΒಀΕͯ3VCZ,BJHJࢀՃΛࢦ͢ 4 / 64
3PBEUP3VCZ,BJHJ⭐ ! !3VCZ,BJHJ-5 ! 1JDP3VCZͱ ՃηϯαʔͰͭ͘Δ ήʔϜίϯτϩʔϥ 3PBEUP3VCZ,BJHJ1MBZ)BSE XBSF !NBLJDBNFM
IUUQTTQFBLFSEFDLDPNNBLJDBNFMSPBEUPSVCZLBJHJQMBZIBSEXBSF 5 / 64
ొਓ 1JDP3VCZ ΈࠐΈ͚3VCZ ηϯαʔͳͲͱଓͯ͠ ͖ͳσόΠεΛͭ͘ΕΔ QJDPSVCZQJDPSVCZ IUUQTHJUIVCDPNQJDPSVCZQJDPSVCZ 6 / 64
ొਓ 1JDP3VCZ ʢ3BTQCFSSZ1J1JDP8ʣ ΈࠐΈ͚3VCZ ηϯαʔͳͲͱଓͯ͠ ͖ͳσόΠεΛͭ͘ΕΔ QJDPSVCZQJDPSVCZ IUUQTHJUIVCDPNQJDPSVCZQJDPSVCZ 7 /
64
ొਓ ίϯτϩʔϥ 8 / 64
ొਓ Ճηϯα 9 / 64
ొਓ Ճηϯα ՃηϯαͷΛ 3PBEUP3VCZ,BJHJʹ͍ͨ͠ 3PBEUP3VCZ,BJHJ 10 / 64
ొਓ 1JDP3VCZ Ճηϯα 1JDP3VCZͰ ՃηϯαͷΛಡΈऔΓ 3PBEUP3VCZ,BJHJ 11 / 64
ొਓ 1JDP3VCZ #MVFUPPUIͰ 3PBEUP3VCZ,BJHJʹૹ৴ 3PBEUP3VCZ,BJHJ 12 / 64
ొਓ 1JDP3VCZ #MVFUPPUIͰ 3PBEUP3VCZ,BJHJʹૹ৴ Ͱ͖ͳ͍ 3PBEUP3VCZ,BJHJ 13 / 64
ొਓ 1JDP3VCZ #MVFUPPUIͷ ΫϩεϓϥοτϑΥʔϜͳ 3VCZΫϥΠΞϯτ͕ͳ͍ #MVFUPPUIͰ 3PBEUP3VCZ,BJHJʹૹ৴ Ͱ͖ͳ͍ 3PBEUP3VCZ,BJHJ 14
/ 64
ొਓ ϒϥβ 8FC#MVFUPPUI"1* 8FC#MVFUPPUI"1*8FC"1*c.%/ IUUQTEFWFMPQFSNP[JMMBPSHKBEPDT8FC"1*8FC@#MVFUPPUI@"1* 15 / 64
ొਓ ϒϥβ 8FC#MVFUPPUI"1* 8&#SJDLαʔό 3PBEUP3VCZ,BJHJ 16 / 64
ొਓ 1JDP3VCZ #MVFUPPUI ϒϥβ 8&#SJDLαʔό 3PBEUP3VCZ,BJHJ 17 / 64
ొਓ 1JDP3VCZ #MVFUPPUI ϒϥβ )551 8&#SJDLαʔό 3PBEUP3VCZ,BJHJʹ ૹ৴Ͱ͖ͨ 3PBEUP3VCZ,BJHJ 18
/ 64
#MVFUPPUI 19 / 64
#-& ! #MVFUPPUI-PX&OFSHZ ! লిྗ͚#MVFUPPUIن֨ ! 3BTQCFSSZ1J1JDP 8ʹແઢνοϓ͕͍ͬͯΔ !
1JDP3VCZ͔Βѻ͑Δ ֓೦ɾ͓࡞๏͕ Ή͔͍ͣ͠ 20 / 64
#-&6"35 ! 6"35 ! ػثΛཧઢͰͭͳ͍ͰํʹόΠτΛૹΔ௨ ৴ํࣜ ! #-&6"35 ! 6"35Λ#-&ͰԾతʹ࣮ݱ͢Δ1JDP3VCZͷ࣮
! *0ͷΑ͏ͳΠϯλʔϑΣʔεͰѻ͑Δ #-&6"35QJDPSVCZQJDPSVCZ IUUQTHJUIVCDPNQJDPSVCZQJDPSVCZUSFFNBTUFSNSCHFNTQJDPSVCZCMFVBSU 21 / 64
#-&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 / 64
#-&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 / 64
#-&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 / 64
#-&6"35 ! )551 ! ϦΫΤετϝοηʔδ ! #-&6"35 ! όΠτετϦʔϜ !
ड৴ϝοηʔδ ! FH ෳϝοηʔδɺϝοηʔδ్͕தͰ͖ΕΔ ! ηύϨʔλͰ۠Γͯࣗ͠ͰΈཱͯΔ 25 / 64
#-&6"35 3VCZͬΆ͘ॻ͖͍ͨʂ 26 / 64
E3VCZ 27 / 64
E3VCZ ! EJTUSJCVUJPO3VCZ ! ࢄ3VCZ ! ࢄΦϒδΣΫτγεςϜΛ࣮ݱ͢ΔϥΠϒϥϦ ! ؔকढ़͞Μ࡞ MJCSBSZESC
3VCZϦϑΝϨϯεϚχϡΞϧ IUUQTEPDTSVCZMBOHPSHKBMBUFTUMJCSBSZESCIUNM 28 / 64
E3VCZ ! ϓϩηεωοτϫʔΫΛ͑ͯϝοηʔδΛૹΔ ! ଞϓϩηεͷΦϒδΣΫτͷϝιουΛݺΔ 29 / 64
E3VCZ { greeting: 'Hello, Matsue!' } E3VCZೖऀʹΑΔ͋ͳͨͷۙʹ͋ΔE3VCZೖ!NBLJDBNFM IUUQTTQFBLFSEFDLDPNNBLJDBNFMESVCZBUUSBDUJPO 30 /
64
E3VCZ { greeting: 'Hello, Matsue!' object[:greeting] } E3VCZೖऀʹΑΔ͋ͳͨͷۙʹ͋ΔE3VCZೖ!NBLJDBNFM IUUQTTQFBLFSEFDLDPNNBLJDBNFMESVCZBUUSBDUJPO 31
/ 64
E3VCZ { greeting: 'Hello, Matsue!' object[:greeting] } # => 'Hello,
Matsue!' E3VCZೖऀʹΑΔ͋ͳͨͷۙʹ͋ΔE3VCZೖ!NBLJDBNFM IUUQTTQFBLFSEFDLDPNNBLJDBNFMESVCZBUUSBDUJPO 32 / 64
E3VCZ ! 3VCZͬΆ͍ʂ ! #-&͝͠ʹผϓϩηεͷΦϒδΣΫτΛ͞ΘΓ͍ͨ 33 / 64
E3VCZPWFS#-& 34 / 64
E3VCZPWFS#-& E3VCZϓϩτίϧ͕ࠩ͠ସ͑Մೳ ! ϏϧτΠϯ ! Ϣʔβʔ֦ு ! 5$1 ! 8FC4PDLFU
! 6/*9υϝΠϯιέοτ ! 44- 35 / 64
E3VCZPWFS#-& E3VCZϓϩτίϧ͕ࠩ͠ସ͑Մೳ ! ϏϧτΠϯ ! Ϣʔβʔ֦ு ! 5$1 ! 8FC4PDLFU
! 6/*9υϝΠϯιέοτ ! #-&! GPS1JDP3VCZ1JDP3VCZ8"4. ! 44- 36 / 64
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶃΦϒδΣΫτΛެ։ front = Calc.new DRb.start_service( "ble://picoruby", front)
37 / 64
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") "ble://picoruby", front) 38 / 64
E3VCZGPS1JDP3VCZ ΫϥΠΞϯτ αʔό ᶄελϒΛ࡞Δ ᶃΦϒδΣΫτΛެ։ αʔόͷΞυϨεΛࢦఆ front = Calc.new obj
= DRbObject.new( DRb.start_service( "ble://picoruby") "ble://picoruby", front) ᶅϝοηʔδૹ৴ obj.add(1, 2) όΠτྻมͯ͠ૹ৴ όΠτྻΛૹड৴ 39 / 64
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 / 64
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 / 64
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 / 64
όΠτྻͷૹड৴ ! DRbMessage ! ϝιουίʔϧɾΓˡˠόΠτྻͷมΛߦ͏ ! ௨৴࿏ʹͤΒΕΔͷόΠτྻ͚ͩ ! τϥϯεϙʔτͱૄ݁߹ 43
/ 64
όΠτྻͷૹड৴ ! τϥϯεϙʔτ ! FH ! 5$1 ! 8FC4PDLFU !
#-& ! 1JDP3VCZɾ4%,Ͱ࣮͞Ε͍ͯΔ 44 / 64
όΠτྻͷૹड৴ ! DRbMessage τϥϯεϙʔτ ! "1*ͷཁ݅ͱ࣮ଶʹ͕ࠩ͋Δ DRbMessage#recv_message | | |
BLE::UART#read_nonblock 45 / 64
όΠτྻͷૹड৴ ! DRbMessage ιέοττϥϯεϙʔτ ! "1*ͷཁ݅ͱ࣮ଶͷࠩΛٵऩ͢ΔιέοτΛ࣮͢Δ DRbMessage#recv_message | Adapter#read |
BLE::UART#read_nonblock 46 / 64
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 47 / 64
%3C#-&"EBQUFS ! όΠτྻʹର͢Δૢ࡞छྨ ! read ! write DRb::BLE::Adapter#close࣮͠·͕͢ࠓճׂѪ 48 /
64
%3C#-&"EBQUFS ! DRbMessage ! BLE::UART #recv_message(n) #read_nonblock(n) ! ϒϩοΩϯάඞཁ !
ϒϩοΩϯά͠ͳ͍ ! ஸOόΠτ΄͍͠ ! ʙOόΠτΛฦ͢ ͜ͷࠩΛ DRb::BLE::Adapter#read Ͱٵऩ͢Δ 49 / 64
%3C#-&"EBQUFS def read(n) ड৴όοϑΝʹ until @uart.available >= n OόΠτ #
... ཷ·Δ·Ͱͭ ϒϩοΩϯά sleep_ms 10 end end 50 / 64
%3C#-&"EBQUFS def read(n) until @uart.available >= n # ... @uart.poll_once
ड৴ύέοτΛ sleep_ms 10 όοϑΝʹੵΉ end end 51 / 64
%3C#-&"EBQUFS def read(n) until @uart.available >= n # ... @uart.poll_once
sleep_ms 10 end OόΠτཷ·ͬͨΒ @uart.read_nonblock(n) औΓग़ͯ͠ฦ͢ end 52 / 64
%3C#-&"EBQUFS ! DRbMessage ! BLE::UART #send_request(data) #write(data) ࣗͷλΠϛϯάͰόΠτΛૹΕΑ͍ 53 /
64
%3C#-&"EBQUFS ͦͷ··సૹ͢Δ def write(data) @uart.write(data) end 54 / 64
%3C#-& ! ιέοτ͕Ͱ͖ͨ! ! αʔόͷ࣮ ! Πϯελϯε࡞ͬͨΓ ! ϝοηʔδΛड͚औͬͯϝιουίʔϧͯ͠ฦ͠ ͨΓ͢Δ͚ͩ
55 / 64
ΞϓϦଆίʔυ ! 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 / 64
ΞϓϦଆίʔυ ! BGUFS # ड৴ଆ(PicoRuby.WASM) # ηοτΞοϓ @obj = DRb::DRbObject.new_with_uri(uri)
# @obj.readΛҰఆ࣌ؒຖʹίʔϧ͢Δ @obj.read.each { |sample| send_data(sample) } 3VCZͬΆ͍ʂ 57 / 64
σϞ 58 / 64
σϞ ! ಈ͍ͯͳ͍ʜʜʁ ! ඵؒαϯϓϧ͕Γ͍ͯͳ͍ 59 / 64
༨ஊ ! ϙʔϦϯάϨʔτԼ ! CFGPSF ! αϯϓϧඵ ! BGUFS !
αϯϓϧඵ ! 60 / 64
༨ஊ ! ϙʔϦϯάϨʔτԼ ʮήʔϜίϯτϩʔϥΈ͍ͨͳͷʹ ɹSFRVFTUSFQMZܕͷ௨৴͖·ͤΜʯ ʮ!ʯ 61 / 64
༨ஊ ! E3VCZ ! QVTI ! SFRVFTUSFQMZܕ ! ҰํͷετϦʔϜ !
ຖճ ! ߴසʹૹΕͯԆ ૹ৴ɾػɾड৴ ! ฦࣄෆཁ ! ௨৴ճ͕૿͑Δ ! ฦࣄΛͭ͘ͳΔ ༻్ʹ͋ͬͨํ๏ Λબ΅͏ ήʔϜίϯτϩʔϥQVTIܕ͖ 62 / 64
͓͠Βͤ 63 / 64
1JDP3VCZ,BJHJ "TTFNCMFΓ·͢ ! 1JDP3VCZΛͭ͘Δɺ1JDP3VCZͰͭ͘Δ ! ϓϩϙʔβϧืूࠓ݄։͖·͢ ! !
!ळ༿ݪ ! IUUQTQJDPSVCZLBJHJPSH 64 / 64