質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.12%

byte[]→string→string[]→doubleについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 601

P5_USER

score 56

前提・実現したいこと

前提条件①:C#にて4つのdouble型変数をスペース区切りでstring型変数にしている
前提条件②:そのstringをUTF8でエンコードしてbyte[]としている。
前提条件③:UDPでbyte[]を送信している(ここまではC#の出来事)
前提条件④:以下URLを参考にprocessingでbyte[]を受け取っている(はず)。
URL:http://memorandums.hatenablog.com/entry/2016/11/08/203610

目標①:受け取ったバイト配列をスペース区切りで4つに分割してprocessing側で新規に作成したdouble型変数(ここではA_nowとか)に格納する。
目標②:updateTime()での値更新。

今回C#にさせる役割はデータの仲介です。
通信の全体図

発生している問題・エラーメッセージ

変数の値(A_now,B_now,C_now,D_now,A_before,B_before,C_before,D_before)
が変わっていない

ずっと0.0のまま
Bashoで確認
Bashoについて:https://www.youtube.com/watch?v=8Z23xNN7IGU

該当のソースコード

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace test4_P5.ver
{
    [StructLayout(LayoutKind.Sequential)]
    struct STRUCTURE
    {
        public double AA;
        public double BB;
        public double CC;
        public double D1;
        public double D2;
    };

    class Program
    {
        static void Main(string[] args)
        {
            System.String name;
            DateTime dt = System.DateTime.Now;
            name = @"C:\Users\hogehoge\Desktop\フォルダ\" + dt.ToString("tthh時mm分ss秒") + ".csv";
            System.IO.StreamWriter w = new System.IO.StreamWriter(name, false);
            System.Threading.Thread.Sleep(5000);
            w.Write("time,AA,AA,BB,BB,CC,CC,D1,D2,DD\n");

            //バインドするローカルIPとポート番号
            string localIpString = "〇.〇.〇.〇";
            //string localIpString = "127.0.0.1";

            System.Net.IPAddress localAddress =
                System.Net.IPAddress.Parse(localIpString);
            int localPort = 12000;

            //UdpClientを作成し、ローカルエンドポイントにバインドする
            System.Net.IPEndPoint localEP =
                new System.Net.IPEndPoint(localAddress, localPort);
            System.Net.Sockets.UdpClient udp =
                new System.Net.Sockets.UdpClient(localEP);

            //データを送信するリモートホストとポート番号
            string remoteHost = "172.0.0.1";
            int remotePort = 60000;

            //UdpCliantオブジェクトを作成する。
            System.Net.Sockets.UdpClient client =
                new System.Net.Sockets.UdpClient();

            DateTime startdt = System.DateTime.Now;

            //Processingにデータを渡すための前処理
            double AA, BB, CC, DD;

            for (; ; )
            {
                //データを受信する
                System.Net.IPEndPoint remoteEP = null;
                byte[] rcvBytes = udp.Receive(ref remoteEP);
                //データを文字列に変換する
                FSSM rcvMsg = new STRUCTURE();
                //Marshal.PtrToStructure(rcvBytes, typeof(STRUCTURE));

                //string rcvMsg = System.Text.Encoding.UTF8.GetString(rcvBytes);

                //↓[追加]バイト配列を構造体にコピーする。
                IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(rcvMsg));

                Marshal.Copy(rcvBytes, 0, ptr, Marshal.SizeOf(rcvMsg));
                rcvMsg = (STRUCTURE)Marshal.PtrToStructure(ptr, typeof(STRUCTURE));
                Console.WriteLine(Marshal.SizeOf(rcvMsg));
                Marshal.FreeHGlobal(ptr);

                //送信するデータを作成する
                AA = rcvMsg.AA;
                BB = rcvMsg.BB;
                CC = rcvMsg.CC;
                DD = ((rcvMsg.D1 + rcvMsg.D2) / 2);

                string sendMsg = AA + " " + BB + " " + CC + " " + DD;
                byte[] sendBytes = System.Text.Encoding.UTF8.GetBytes(sendMsg);

                //リモートホストを指定してデータを転送する
                client.Send(sendBytes, sendBytes.Length, remoteHost, remotePort);

                //"exit"を受信したら終了
                if (rcvMsg.Equals("exit"))
                {
                    w.Close();
                    break;
                }
            }

            //UdpClientを閉じる
            udp.Close();
            Console.WriteLine("終了しました。");
            Console.ReadLine();
            w.Close();

            client.Close();
        }
    }
}
import hypermedia.net.*; //<>//
UDP udp;
//Basho basho;
//Double_Absolute D_ABS;

int dW, dH, dW30, dW15, dW10, dH30, dH15, dH10 ;

//現在値
double A_now = 0.0;
double B_now = 0.0;
double C_now = 0.0;
double D_now = 0.0;

//1フレーム前の値
double A_before;
double B_before;
double C_before;
double D_before;


void setup() {
  fullScreen();
  frameRate(60);//フレームレートを設定
  dW=displayWidth;
  dH=displayHeight;

  udp = new UDP (this, 60000);
  udp.listen(true);
  //basho  = new Basho(this);
}

void receive (byte[] data, String ip, int port) {
  String message = new String(data);
  String[] rcvMSG = splitTokens(message, " ");

  A_now = Double.parseDouble(rcvMSG[0]);
  B_now = Double.parseDouble(rcvMSG[1]);
  C_now = Double.parseDouble(rcvMSG[2]);
  D_now = Double.parseDouble(rcvMSG[3]);
  //println( "receive: \""+message+"\" from "+ip+" on port "+port );
}


void draw() {
  background(0, 0, 0);//黒色背景
  smooth();//滑らかな描写
  stroke(0, 255, 0);//線の色:緑
  fill(0, 255, 0);//充填の色:緑
  scale(1, -1);//x軸右側正&y軸上側正
  translate(dW/2, -dH/2);//画面中央に原点移動
  updateTime();
}

void updateTime() {//一個前の値を差分処理用に格納
  A_before = A_now;
  B_before = B_now;
  C_before = C_now;
  D_before = D_now;
}

class Double_Absolute {//abs()がdoubleをサポートしていないのでdouble用に作成
  double ABS (double b)
  {
    if (b<0)
    {
      b = -b;
    }
    return b;
  }
}

試したこと

デバッグモードでの変数確認や先程記載したBashoでのリアルタイム変数遷移の確認。
↑でもやっぱり値が変わらず...

もしかして,送信と受信のヘルツがあってないとダメ?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2017/11/28 13:40

    そもそもAPサーバーに到達しているかどうか

    キャンセル

  • P5_USER

    2017/11/28 13:48

    初めてAPサーバーなる言葉を目にしたのですが,1つ目のURLに記載されていたUDP通信を模倣&改良したので,全く考えておりませんでした。実際に到達しているか否かというのは,println等で確認をしたりするのでしょうか。

    キャンセル

  • coco_bauer

    2017/11/28 16:52

    コードのどこかにUDPからデータを読み出す "udp.receive"が必要だと思うのですが、見当たりません。 質問のコードにあるreceiveメソッドの第一引数のバイト列 dataの値は、どこから得ているのですか。

    キャンセル

  • P5_USER

    2017/11/28 16:57 編集

    前提条件④でのURLを参考にしており,実際に通信に成功したのですが,udp.receiveが必要なのですね。
    私も調べてみます。

    キャンセル

回答 1

checkベストアンサー

+1

asahina1979さんのコメントがあたりのような・・・

多分、講師の方が公開しておられる下のページですよね・・・
http://memorandums.hatenablog.com/entry/2016/11/08/203610

このプログラムの場合、Processing側でUDPポート(6000)から通信が入ってくるのを常に待っていて、受信したらreceiveメソッドが呼び出されるという仕組みのようです。上記ページのコードと見比べたところ特に違いは見つからなかったのでおそらくC#側からProcessingへ通信が届いてないような気がします。

確認方法として以下をやってみてはいかがでしょうか?

...
int receiveCount = 0; // 受信回数を記録する変数をメソッドの外側に定義
...

void receive (byte[] data, String ip, int port) {
  // ここで受信回数をインクリメント
  receiveCount++;
  // 以下は元のコードのとおり
  String message = new String(data);
  ...
}

BashoのgithubのReadme.mdには非常にあっさりと「大域変数の監視とか」という程度のことしか書いてないのでよくわかりませんが、もし上記receiveCountの値がBashoで観察できるなら通信が届いているかどうかすぐわかると思います。

もし0のまま変わらないならC#側の問題と思いますのでそちらに着目して調べてみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/28 15:32 編集

    たしかにそうですね!
    もし172.0.0.1が割り当てられてないIPだとUDPなので送信できないまま何もエラーを検知できないということになるんでしょうか。そこは自分も知りたい気がします。==>そこは本件には関係ないですね。失礼しました。

    キャンセル

  • 2017/11/28 15:44

    確か,UDPの場合だとホスト側は受信の確認をクライアントから求めないので(というより,求めないようにして通信速度を速めている),エラーが出ない筈です。
    今回は,その仕様に見事にハマってしまいました^^;

    キャンセル

  • 2017/11/28 15:54

    愚問でした。パケット出す前にエラーがわかるケースがあるのかなとふと感じたのですが自分で調べるべきでした!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる