Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
スキャン音は鳴るのにカートに入らない — レジと物理デバイスの事件簿
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Kenta Enomoto
August 26, 2026
Technology
35
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
スキャン音は鳴るのにカートに入らない — レジと物理デバイスの事件簿
Mobile Mob #2 の登壇資料です
https://bitkey.connpass.com/event/400743/
Kenta Enomoto
August 26, 2026
More Decks by Kenta Enomoto
See All by Kenta Enomoto
Renovate のバグを直した話
enomotok
0
13
[DroidKaigi 2025] 共有と分離 - Compose Multiplatform "本番導入" の設計指針
enomotok
0
72
Kotlin Multiplatform / Compose Multiplatform を活用したモバイルアプリ開発の最前線
enomotok
0
170
Compose MultiplatformにおけるiOSネイティブ実装のベストプラクティス
enomotok
1
540
STORES ブランドアプリのスケールするアプリづくり
enomotok
0
110
What's new in Xcode 16 ダイジェスト
enomotok
0
890
Introducing Pkl
enomotok
0
3.2k
iOS リポジトリへの Renovate の導入
enomotok
2
460
iOS開発とGitLab CI
enomotok
7
4.1k
Other Decks in Technology
See All in Technology
安心して変更できるWebフロントエンドの作り方
pirosikick
4
2.2k
GoにおけるFFIのこれまでとこれから
goccy
5
2.9k
Snowflakeで実現する全社横断の顧客の声(VOC)分析・活用基盤@Snowflake World Tour Tokyo 2026
yuto16
0
210
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
5
25k
HRC_Frontend_Conference_Fukuoka_2026.pdf
ts020
0
680
AI時代、データエンジニアが一番おもろい
genshun9
0
550
コスト最適化の「めんどくさい」を AWS FinOps Agent でチョット楽にする
classmethod_kaz
0
340
2026/09/10 Spring Bootから Jakarta EE/MicroProfileへの移行
megascus
0
360
2026-09-11 【Snowflake World Tour Tokyo 2026】Snowflakeを起点に、AI Agentが自律稼働し続ける未来へ / Driving AI Agents with Snowflake
civitaspo
0
390
omasushiというライブラリを作った
polidog
PRO
0
220
「守り」で活用するオンデバイスLLM 〜写ってはいけないを総力戦で防ぐ〜 / iOSDC Japan 2026
nakamuuu
0
150
Sigmaで作る業務アプリ
kazushiro_honma
0
140
Featured
See All Featured
A Modern Web Designer's Workflow
chriscoyier
699
190k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
490
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.7k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
250
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.6k
Heart Work Chapter 1 - Part 1
lfama
PRO
9
36k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
A designer walks into a library…
pauljervisheath
211
25k
Leo the Paperboy
mayatellez
9
2.3k
Transcript
スキャン音は鳴るのにカートに入らない — レジと物理デバイスの事件簿 2026.08.26 Mobile Mob #2 STORES 株式会社 榎本健太
自己紹介 榎本 健太 STORES 株式会社 x.com/enomot_ github.com/enomoto 最近の趣味はジョギングです 2
STORES レジ 3
STORES レジと物理デバイスたち レシートプリンター キャッシュドロア バーコードスキャナー 決済端末 今日は、この現場で実際に起きた「事件」の話をします 4
事件: 10点スキャンしたのに、8点しか計上されていない 10点スキャンしたのに、 8点しか計上されていない…。 スキャンが早くなると、よく起きるんです 😥 お店の人 • レジ利用店舗からの報告。会計のズレに直結しかねない、最も避けたい類の不具合 •
環境: iPad 第9世代 / プリンター: スター精密 mcPrint3 / スキャナー: BSH-20U • スキャナーはプリンターに有線接続 — スキャンデータはプリンター経由で iPad に届く 5
この不具合の何が嫌か • 構成が特殊 — スキャナーがプリンター経由。再現には、まずこの物理構成を組むところ から • タイミング依存 — ゆっくりスキャンすると再現しない
• 失敗が静か — スキャン音は鳴る。エラー表示は次のスキャンで即消える Q. みなさんなら、どこから調べますか? 6
手がかり①: 経路の「差分」を読む スキャナー入力の経路は2系統 スキャナー iPad(レジ) ① 直挿し(HID): 改行までバッファ → フレーミングあり
スキャナー プリンター 有線 iPad(レジ) Bluetooth classic ② プリンター経由: 前後トリムのみ → フレーミングなし 🤔「複数のバーコードが、1回の didReceive にまとまって届いているのでは?」 (※didReceive はプリンターメーカーの SDK で呼ばれるメソッド) 7
手がかり②: デバイス境界に「生ログ」を仕込む 単発スキャン(正常) didReceive count=14 utf8="2002226945019\n" → 照合ヒット → カート追加成功
高速連続スキャン(不具合) didReceive count=42 utf8="2002226945019\n2002226945019\n2002226945019\n" → 照合失敗 → カート未追加(でもスキャン音は鳴る) • 3回分のスキャンが、改行連結で1回にまとまって届いていた • 前後トリムでは中間の改行が残り、「この世に存在しない商品コード」が誕生 • この1行で「取りこぼし」「デコード失敗」の仮説も同時に棄却できた 8
原因の本質: フレーミングの欠如 ストリーム型の入力には、メッセージの境界がない • 「1回の受信イベント = 1メッセージ」は、受信側が勝手にしていた思い込み • 区切りを解釈して1件ずつに切り出す —
フレーミングは受信側の責務 • HID の経路には考慮が入っていたが・・・ “Notify that the data is received” didReceive の公式リファレンスの説明 — これで全文。区切りも集約も、何も書かれていない BLE の notify / TCP / シリアル — ストリームを受けるコードには必ず潜む問題 9
修正と検証 • 修正: 受信ペイロードを改行で分割し、1件ずつ処理する。それだけ • 工夫: 分割ロジックを static 関数に切り出し →
実機なしでユニットテスト (単一 / 複数連結 / CR・CRLF 混在 / 空セグメント) • 検証: 実機の高速連続スキャンで before / after を動画に記録して確認 「観測された事実の範囲で直す」— 線引きを PR に明記 10
Take Away: 物理デバイスとの付き合い方 • ストリーム受信を見たら、フレーミングを疑う 「1回の受信 = 1メッセージ」はどのプロトコルでも思い込み • タイミング依存の不具合には、デバイス境界の「生ログ」
加工前のバイト数と生文字列。1行で複数の仮説を棄却できる • 経路の「差分」を探す 動く経路に在って、壊れる経路に無いものが、答えの近くにいる • 再現環境をケチらない 報告と同じ物理構成を組んで再現できた 11