C#でCTI機能の実現を目指しております。
プログラムは以下サイトからDLして改造しています。
http://tmp.junkbox.info/e14.html
しかし、エラーが頻発し原因不明です。
構成、仕様としては、
アロハPC1という機械から電話番号データを受信しPCに受け渡し。
・データを受け取る(ここは問題なし)
データ形式は
STX(02H)、着信日時(月日曜時分9桁)、電話番号(20桁)、ETX(03H)
として送られてきます。
例) 1214112050457771111
・正常データの場合はACK(06H)を返信(これをしない場合1秒後に同データが再送される)
・データ整形
・データ表示
というような形にしたいのです。
上記サイトのプログラムをアロハPC1に合わせて通信できるようにした状態ですと、例のような生データが問題なく表示されます。
これを以下のようにしてみましたが、エラーが出てしまいます。
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
// 受信文字列の取得
string receivedData = "";
string moji = "";
string moji2 = "";
try
{
receivedData = this.serialPort1.ReadExisting();
receivedData = receivedData.Replace(this.serialPort1.NewLine, "\r\n");
string[] week = { "(日)", "(月)", "(火)", "(水)", "(木)", "(金)", "(土)" };
string stx = receivedData.Substring(0, 1);
string etx = receivedData.Substring(30, 1);
// ACKを返す。
byte[] ack_data = new byte[1];
ack_data[0] = 06;
serialPort1.Write(ack_data,0,1);
string data_m = receivedData.Substring(1, 2);
string data_d = receivedData.Substring(3, 2);
string w = receivedData.Substring(5, 1);
int w2 = int.Parse(w);
string data_w = week[w2];
string data_h = receivedData.Substring(6, 2);
string data_i = receivedData.Substring(8, 2);
moji2 = receivedData.Substring(10, 20);
// スペースを痴漢
moji2 = moji2.Replace(" ", "");
moji = data_m + "月" + data_d + "日" + data_w + data_h + "時" + data_i + "分 ";
if (moji2 == "P")
{
moji = moji + "着信番号非通知\n";
}
else if (moji2 == "O")
{
moji = moji + "着信番号提供地域外\n";
}
else if (moji2 == "C")
{
moji = moji + "公衆電話\n";
}
else
{
moji = moji + moji2 + "\n";
}
}
catch (Exception ex)
{
moji = ex.Message;
}
// richTextBox側のスレッドに AddRecievedDataメソッドのポインタを渡して、
// 受信文字列を追加させる
AddRecievedDataDelegate add = new AddRecievedDataDelegate(AddRecievedData);
this.richTextBox1.Invoke(add, moji);
}
結果:
1221112260457771111
12月21日(月)12時26分 0457771111
1221112
startIndex に文字列の長さより大きい値を指定することはできません。
パラメータ名: startIndex260457771111
startIndex に文字列の長さより大きい値を指定することはできません。
パラメータ名: startIndex
Substringを削除すると「startIndex に文字列の長さより大きい値を指定することはできません。」というようなエラーは出てきません。
receivedData = this.serialPort1.ReadExisting();
を文字列を直接代入した場合はエラーは発生しません。
これをどのようにすれば正常に動くのでしょうか。
また、ACKが正常に送信できてないみたいなのも解れば助かります。
よろしくお願いします。
No.2ベストアンサー
- 回答日時:
>・データを受け取る(ここは問題なし)
確認も無しに断言してはいけません。
このプログラムの問題点は、受信したデータ(receivedDat)が必ずしも31文字にならないことです。
SerialPortのDataReceived()イベントは、1文字受信するたびに発生します。
従って受信したデータには、ReadExisting()した時点でSerialPortに受信されている分しか入りません。
解決方法を2種類示しますが、動作確認はしていません。
◎解決方法1
ReadExisting()する前にBytesToReadをチェックして31文字未満ならReadしない。
◎解決方法2
一度に1文字ずつReadして文字をつないでいく。
このとき、
STXを受信する前は、Readしたデータは捨てる。(受信データは空にする)
STXを受信した後は、Readしたデータを受信データに継ぎ足していく。
ETXを受信したら(継ぎ足したデータがETXなら)、受信データ長を確認してACK送信にすすむ。
仰るとおりでした。
常にデータがすべて来る訳ではないのですね。
こういうプログラムははじめてなのでわからないことだらけです。
解決方法の通り、BytesToReadでチェックしたらうまくいきました。
ありがとうございました。
No.1
- 回答日時:
string etx = receivedData.Substring(30, 1);
この行がいけないのでは??
エラーの原因はSubstringだと思います、Substringの第一パラメータの名称はstartIndexですから。
ACKが送られていないということなので、ACKの送信前のコードに限定できます、そして怪しいのがこの1行となるわけです。
送信データが
1214112050457771111
であれば、30字に満たないので、発生しそうですね。
回答ありがとうございます。
しかしならが、申し訳ありませんが、送信データは投稿の最、半角スペースデータが削除されてしまったようですが、元の受信データはたしかに
STX(02H)、着信日時(月日曜時分9桁)、電話番号(20桁)、ETX(03H)
という31文字分受信されています。(電話番号が20文字に足りない場合半角スペース(20H)で埋められる)
また、テストしましたが、
string stx = receivedData.Substring(0, 1);
のみ残して、他を消した状態でも「startIndex に~」というエラーが発生します。
なぜこのような挙動になるのか不思議です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
餃子を食べるとき、何をつけますか?
みんな大好き餃子。 ふと素朴な疑問ですが、餃子には何をつけて食べますか? 王道は醤油とお酢でしょうか。
-
これ何て呼びますか
あなたのお住いの地域で、これ、何て呼びますか?
-
初めて自分の家と他人の家が違う、と意識した時
子供の頃、友達の家に行くと「なんか自分の家と匂いが違うな?」って思いませんでしたか?
-
ちょっと先の未来クイズ第4問
11月ごろに発表される、2024年の「新語・流行語大賞」にノミネートされる言葉を書けるだけ書いてください。
-
あなたの習慣について教えてください!!
あなたが習慣だと思って実践しているものを共有してくださいませんか? 筋肉トレーニングでも朝シャワーでも、あなたが習慣だなと思えば何でも構いません
-
C# シリアル通信でデータ受信時の欠損について
C言語・C++・C#
-
RS232cを用いた送信プログラム
C言語・C++・C#
-
圧縮ソフト 7-Zipについて あまり圧縮されないのですか?
フリーソフト
-
-
4
デバッグとビルドは何が違うのですか?
Visual Basic(VBA)
-
5
.txtではなく.logの方が良いのでしょうか?
その他(プログラミング・Web制作)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
アセンブリ言語について。
-
フロントエンドエンジニアをし...
-
Google ColaboでGUI作成
-
AIのプログラムについて教えて...
-
プログラミングについて プログ...
-
プログラミングの進学について
-
vba クリップボードクリアにつ...
-
プログラミングのやり方ざっく...
-
fortran write文について マチ...
-
コトリン言語について。
-
このURLで広告を出しているのは...
-
python エラー
-
Pythonでgif画像が上手く作れない
-
pythonで複数画像からgifを作る...
-
Gitについて質問。 クローンし...
-
HTMLソースが表示のページのも...
-
batファイル、コマンドプロンプ...
-
Google Colabでimport soxが出...
-
プログラミングを学ぼうと思い...
-
paiza python03 ランクC獲得
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Outlookの「受信日時」「件名」...
-
TCP/IP のパケットの分断と結合...
-
UDP受信時の通信異常検知について
-
シリアル通信時のデータ受信方法
-
「TCPは全二重可能」の意味
-
DHCPOFFERの受信について
-
Outlookの「受信日時」「送信者...
-
C#にてCTI。RS232Cの受信と送信...
-
TCPでパケットロス?
-
recv関数の戻り値について
-
RS232cを用いた送信プログラム
-
CRC-CCITTに関しての仕様とサン...
-
winsockを使ったTCP及びUDP通信...
-
バイナリをテキストファイルに...
-
javamail
-
VC++メッセージの送受信につい...
-
ネットワークでの受信バイト数
-
赤外線センサーについて
-
ソケットプログラミング(配列に...
-
LINE APIからasp.net の web サ...
おすすめ情報