@prefix schema: <https://schema.org/> .
@prefix skos: <http://www.w3.org/2004/02/skos/core#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ks: <https://comcomponent.com/vocab/> .

<https://comcomponent.com/blog/2026/03/19/001-serial-communication-app-pitfalls/#article>
    schema:about <https://comcomponent.com/knowledge/serial-communication/>, <https://comcomponent.com/knowledge/frame-parser/>, <https://comcomponent.com/knowledge/single-writer/> ;
    schema:mentions <https://comcomponent.com/knowledge/byte-stream/>, <https://comcomponent.com/knowledge/frame-boundary/>, <https://comcomponent.com/knowledge/datareceived-event/>, <https://comcomponent.com/knowledge/timeout-taxonomy/>, <https://comcomponent.com/knowledge/inter-byte-timeout/>, <https://comcomponent.com/knowledge/response-timeout/>, <https://comcomponent.com/knowledge/reconnect-backoff/>, <https://comcomponent.com/knowledge/session-regeneration/>, <https://comcomponent.com/knowledge/request-id/>, <https://comcomponent.com/knowledge/flow-control-lines/>, <https://comcomponent.com/knowledge/hex-dump-logging/>, <https://comcomponent.com/knowledge/crc-check/>, <https://comcomponent.com/knowledge/response-mismatch-risk/> .

<https://comcomponent.com/knowledge/serial-communication/> a skos:Concept ;
    skos:prefLabel "シリアル通信"@ja ;
    skos:definition "1本の通信路で順序付きのbyte列をやり取りする通信方式。メッセージの境界は自分でプロトコルとして定義する必要がある。"@ja ;
    skos:altLabel "Serial Communication" ;
    ks:uses <https://comcomponent.com/knowledge/byte-stream/> .

<https://comcomponent.com/knowledge/frame-parser/> a skos:Concept ;
    skos:prefLabel "フレームパーサー(蓄積してから切り出す設計)"@ja ;
    skos:definition "受信したbyte列をいったんバッファへ蓄積し、フレーム境界の定義に沿ってメッセージを切り出す受信側の設計。"@ja ;
    skos:altLabel "Frame Parser" ;
    ks:implements <https://comcomponent.com/knowledge/frame-boundary/> ;
    ks:recommendedFor <https://comcomponent.com/knowledge/byte-stream/> .

<https://comcomponent.com/knowledge/single-writer/> a skos:Concept ;
    skos:prefLabel "single writer(単一書き込み口)"@ja ;
    skos:definition "呼び出し側が何スレッドあっても、書き込み先(ログファイルやシリアルポートなど)への実際の書き込みは1か所(1スレッド)だけに絞る設計。"@ja ;
    skos:altLabel "書き込み口の一本化"@ja ;
    ks:recommendedFor <https://comcomponent.com/knowledge/serial-communication/> .

<https://comcomponent.com/knowledge/byte-stream/> a skos:Concept ;
    skos:prefLabel "byte stream(順序付きbyte列)"@ja ;
    skos:definition "送受信の順序だけが保証され、メッセージの境界を持たないbyteの列。1回の書き込みが受信側では分割されたり連結されたりして届く。"@ja ;
    ks:requires <https://comcomponent.com/knowledge/frame-boundary/> .

<https://comcomponent.com/knowledge/frame-boundary/> a skos:Concept ;
    skos:prefLabel "フレーム境界"@ja ;
    skos:definition "byte列のどこからどこまでを1メッセージ(フレーム)と見なすかを決める、プロトコル側の取り決め。固定長・区切り文字・長さ+payload+checksumなどの形がある。"@ja ;
    skos:altLabel "メッセージ境界"@ja .

<https://comcomponent.com/knowledge/datareceived-event/> a skos:Concept ;
    skos:prefLabel "SerialPort.DataReceivedイベント"@ja ;
    skos:definition ".NETのSerialPortが提供する受信通知イベント。受信byteごとに発火するとは限らず、UIスレッドでもない。"@ja ;
    skos:altLabel "DataReceived" ;
    ks:notRecommendedFor <https://comcomponent.com/knowledge/frame-boundary/> .

<https://comcomponent.com/knowledge/crc-check/> a skos:Concept ;
    skos:prefLabel "CRCによるフレーム検証"@ja ;
    skos:definition "フレームの末尾に付与したCRC値を使い、受信したフレームが壊れていないかを検証する仕組み。"@ja ;
    skos:altLabel "CRC-16/MODBUS" .

<https://comcomponent.com/knowledge/inter-byte-timeout/> a skos:Concept ;
    skos:prefLabel "inter-byte timeout"@ja ;
    skos:definition "フレーム組み立て中に次のbyteが届かない状態を打ち切り、再同期に移るまでの時間。"@ja .

<https://comcomponent.com/knowledge/timeout-taxonomy/> a skos:Concept ;
    skos:prefLabel "タイムアウトの種別分割"@ja ;
    skos:definition "open・inter-byte・response・reconnect backoffなど、意味ごとに分けて設計するタイムアウトの考え方。1個の数字で全部を表現しようとすると原因の切り分けが難しくなる。"@ja ;
    ks:uses <https://comcomponent.com/knowledge/inter-byte-timeout/> ;
    ks:uses <https://comcomponent.com/knowledge/response-timeout/> ;
    ks:uses <https://comcomponent.com/knowledge/reconnect-backoff/> .

<https://comcomponent.com/knowledge/response-timeout/> a skos:Concept ;
    skos:prefLabel "response timeout"@ja ;
    skos:definition "コマンド発行から応答完了までを打ち切るまでの時間。"@ja .

<https://comcomponent.com/knowledge/reconnect-backoff/> a skos:Concept ;
    skos:prefLabel "backoff付き再接続"@ja ;
    skos:definition "初回はすぐretryし、だめなら段階的に間隔を伸ばし、上限を設け、手動の再接続ボタンも用意する再接続方式。"@ja .

<https://comcomponent.com/knowledge/response-mismatch-risk/> a skos:Concept ;
    skos:prefLabel "応答の取り違えリスク"@ja ;
    skos:definition "リクエストIDを持たないプロトコルで、遅れて届いた前の応答が次のコマンドの応答として扱われてしまうリスク。"@ja .

<https://comcomponent.com/knowledge/request-id/> a skos:Concept ;
    skos:prefLabel "リクエストID"@ja ;
    skos:definition "コマンドとその応答を一意に対応づけるための識別子。フレームに持たせないと、遅延応答を次のコマンドの応答と誤認するおそれがある。"@ja ;
    skos:altLabel "Request ID" ;
    ks:prevents <https://comcomponent.com/knowledge/response-mismatch-risk/> .

<https://comcomponent.com/knowledge/session-regeneration/> a skos:Concept ;
    skos:prefLabel "session再生成(再接続設計)"@ja ;
    skos:definition "受信バッファ・parser状態・pending request・初期化シーケンスまで含めて作り直す再接続の設計。単なるOpen()のやり直しでは足りない。"@ja ;
    skos:altLabel "セッション再生成"@ja ;
    ks:recommendedFor <https://comcomponent.com/knowledge/response-mismatch-risk/> ;
    ks:uses <https://comcomponent.com/knowledge/reconnect-backoff/> .

<https://comcomponent.com/knowledge/flow-control-lines/> a skos:Concept ;
    skos:prefLabel "フロー制御・DTR/RTS"@ja ;
    skos:definition "RTS/CTSなどの制御線やXON/XOFFによる、送りすぎを防ぐ仕組み。実機ではDTR/RTSの変化を起動やモード切替の合図として使うこともある。"@ja ;
    skos:altLabel "Handshake" ;
    skos:altLabel "RTS/CTS" .

<https://comcomponent.com/knowledge/hex-dump-logging/> a skos:Concept ;
    skos:prefLabel "hex dumpを含む送受信ログ"@ja ;
    skos:definition "送受信時刻・ポート設定・送受信フレームのhex dump・parserエラー・応答の対応関係・再接続理由を残すログ設計。"@ja ;
    ks:recommendedFor <https://comcomponent.com/knowledge/serial-communication/> .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/serial-communication/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/byte-stream/> ;
    schema:description "シリアル通信は順序付きのbyte streamであり、メッセージ境界は勝手には付かない"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/byte-stream/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/frame-boundary/> ;
    schema:description "byte streamからメッセージを取り出すには、フレーム境界をプロトコルとして自分で定義する必要がある"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.read> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/frame-parser/> ;
    rdf:predicate ks:implements ;
    rdf:object <https://comcomponent.com/knowledge/frame-boundary/> ;
    schema:description "フレームパーサーは、蓄積したbyte列からフレーム境界の定義に沿ってメッセージを切り出す実装を担う"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.basestream> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/datareceived-event/> ;
    rdf:predicate ks:notRecommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/frame-boundary/> ;
    schema:description "DataReceivedは受信byteごとに発火するとは限らないため、これを1メッセージ(フレーム)到着の通知として扱うことは推奨されない"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.datareceived> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/frame-parser/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/byte-stream/> ;
    schema:description "受信をいったん蓄積してからフレームを切り出す設計が、byte streamからメッセージを取り出す方法として本記事の推奨"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.read> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/single-writer/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/serial-communication/> ;
    schema:description "送信を1本のワーカーに集約するsingle writer設計が、シリアル通信での送信順序の崩れやコマンドの割り込みを防ぐための本記事の推奨"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.basestream> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/frame-parser/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/crc-check/> ;
    schema:description "CRCを持つプロトコル(この記事が想定するヘッダ・長さ・payload・CRCのフレーム例)では、フレームパーサーは切り出したフレームの末尾のCRC値を検証し、壊れたフレームを捨てる"@ja ;
    ks:evidence <https://pyserial.readthedocs.io/en/latest/pyserial_api.html> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/frame-parser/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/inter-byte-timeout/> ;
    schema:description "堅牢さを狙う設計では、フレームパーサーは組み立て中の候補が一定時間を超えたら諦めて再同期するinter-byte timeoutを持つ"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.readtimeout> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/timeout-taxonomy/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/inter-byte-timeout/> ;
    schema:description "タイムアウトの種別分割は、フレーム組み立て中に次のbyteが来ない時間を扱うinter-byte timeoutを含む"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/timeout-taxonomy/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/response-timeout/> ;
    schema:description "タイムアウトの種別分割は、コマンド発行から応答完了までを扱うresponse timeoutを含む"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/timeout-taxonomy/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/reconnect-backoff/> ;
    schema:description "タイムアウトの種別分割は、再接続の待機間隔を扱うreconnect backoffを含む"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/response-timeout/> ;
    rdf:predicate ks:mayCause ;
    rdf:object <https://comcomponent.com/knowledge/response-mismatch-risk/> ;
    schema:description "応答がタイムアウトしたあとそのまま次のコマンドを送ると、遅れて届いた前の応答が次のコマンドの応答として渡ってしまうことがある"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.basestream> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/request-id/> ;
    rdf:predicate ks:prevents ;
    rdf:object <https://comcomponent.com/knowledge/response-mismatch-risk/> ;
    schema:description "フレームにリクエストIDを持たせて応答と突き合わせれば、遅れて届いた応答は知らないIDとして捨てられ、取り違えを防げる"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.basestream> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/session-regeneration/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/response-mismatch-risk/> ;
    schema:description "リクエストIDが無いプロトコルでは、応答がタイムアウトしたあとそのまま次を送らず、この接続を作り直すセッション再生成に落とすことが本記事の推奨"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.basestream> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/session-regeneration/> ;
    rdf:predicate ks:uses ;
    rdf:object <https://comcomponent.com/knowledge/reconnect-backoff/> ;
    schema:description "セッション再生成は、pending requestを失敗させたあとreconnect backoffの期間を置いてから再度ポートを開く"@ja ;
    ks:evidence <https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-commtimeouts> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/serial-communication/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/flow-control-lines/> ;
    schema:description "実機との通信では、RTS/CTSやXON/XOFFなどのフロー制御、DTR/RTSの設定を明示しておく必要がある。ソフトウェアのみのループバックやエミュレーションなど実機を介さない通信ではこの前提は当てはまらない"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.handshake> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/hex-dump-logging/> ;
    rdf:predicate ks:recommendedFor ;
    rdf:object <https://comcomponent.com/knowledge/serial-communication/> ;
    schema:description "送受信時刻・ポート設定・送受信フレームのhex dump・parserエラー・応答の対応関係・再接続理由を残すログ設計が、通信障害の切り分けのために本記事が推奨する運用"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.basestream> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "established" .

[] a rdf:Statement ;
    rdf:subject <https://comcomponent.com/knowledge/single-writer/> ;
    rdf:predicate ks:requires ;
    rdf:object <https://comcomponent.com/knowledge/response-timeout/> ;
    schema:description "request-response型のプロトコルでsingle writerを使う場合、そのワーカーは1件を送ったら応答が来るかresponse timeoutに達するまで次のコマンドを送らずに待つ。ログ書き込みのようなfire-and-forget用途のsingle writerにはこの前提は当てはまらない"@ja ;
    ks:evidence <https://learn.microsoft.com/ja-jp/dotnet/api/system.io.ports.serialport.readtimeout> ;
    ks:verifiedAt "2026-08-01" ;
    ks:certainty "context-dependent" .
