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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
makicamel
June 08, 2026
Programming
420
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
900
First step to PicoRuby
makicamel
2
620
PicoRuby on Rails
makicamel
4
300
Take a small step beyond the api
makicamel
2
220
Road to RubyKaigi: Making Tinny Chiptunes with Ruby
makicamel
4
1.9k
Road to RubyKaigi
makicamel
4
720
Rails アプリ地図考 Flush Cut
makicamel
1
240
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
Terraform標準の組織で AWS CDKをどう使うか
mu7889yoon
1
490
言葉の格闘技のススメ~紙とペンと言葉から始める、キャリアの描き方~
progresscicada
2
140
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
1
250
JAWS-UG横浜 #102 AWSサ終供養LT会 成仏できない AWS サービスたち 〜本日、三体供養します〜
maroon1st
0
330
Android CLI
fornewid
0
210
改善しないと、タスクが回らない。 “てんこ盛りポジション” を引き継いだ情シスの、入社3ヶ月の業務改善録
krm963
0
260
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
450
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
200
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
180
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
310
全PRの83%がAIレビューだけでマージできるようになった開発組織はその後どうなったか
athug
1
1.5k
【やさしく解説 設計編・中級 #6】良いアーキテクチャとは ~ 一本の登り道の、行き先 ~
panda728
PRO
0
210
Featured
See All Featured
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
790
Java REST API Framework Comparison - PWX 2021
mraible
34
9.6k
Skip the Path - Find Your Career Trail
mkilby
1
180
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.2k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
200
The Mindset for Success: Future Career Progression
greggifford
PRO
0
440
Everyday Curiosity
cassininazir
0
270
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
56
3.4k
Being A Developer After 40
akosma
91
590k
Jess Joyce - The Pitfalls of Following Frameworks
techseoconnect
PRO
1
330
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
350
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
170
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