Подключение к потоку данных UDP с Mathematica - PullRequest
8 голосов
/ 30 апреля 2011

У меня на iPhone есть приложение под названием iSeismometer , которое считывает акселерометры iPhone и действует как сервер, который передает эти данные по UDP (я могу установить IP-адрес и номер порта).Вопрос в том, как прочитать этот поток данных с Mathematica?Очевидно, Dreeves изучал это 12 лет назад , так что я предполагаю, что что-то должно было случиться за это время.

Обновление
Я получил два отличных ответа;один от WReach и один от Марка МакКлюра.Оба используют JLink, чтобы получить данные.Это похоже на хороший подход.Тем не менее, мне напомнили о работе над балансом WII.Используя несколько бесплатных программ (GlovePIE и PPJoy), я получил это периферийное устройство Bluetooth, чтобы оно отображалось как джойстик для Windows и, следовательно, также для Mathematica (через ControllerState).Конечно, bluetooth и UDP довольно разные, но можно ли что-то сделать в том же духе, чтобы они тоже работали?

Ответы [ 2 ]

4 голосов
/ 30 апреля 2011

JLink - определенно путь.Я предпочитаю разделять код Java и код Mathematica, компилируя программу Java, которую я затем вызываю из Mathematica.Я установил программу Java для ноутбука и сопутствующей программы, которую можно скачать здесь: http://facstaff.unca.edu/mcmcclur/UDPFiles.tar.gz

Вот необходимый код Mathematica:

Needs["JLink`"];
InstallJava[];
AddToClassPath[NotebookDirectory[]];
udpReader = JavaNew["myClient"];
i = 0;
While[True && i++ < 100,
  Print[udpReader@udpReadOne[10552]]]

Класс updReader определяется следующим кодом Java.

// A simple UDP client to read from iseismometer:
// http://www.iseismometer.com/
// You can run this from the command line via "java myClient"
// to check that your iseismometer setup is correct or you can
// call the the udpReadOne method from another program.

import java.io.*;
import java.net.*;
import java.util.*;

public class myClient {
    public static void main() throws IOException {
        DatagramSocket socket = new DatagramSocket(10552);
        byte[] buffer = new byte[500];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        while(true) {
            socket.receive(packet);
            String received = new String(packet.getData(), 0, packet.getLength());
            System.out.println(received);
        }
    }

    public static String udpReadOne(int port) throws IOException {
        DatagramSocket socket = new DatagramSocket(port);
        byte[] buffer = new byte[100];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
        socket.receive(packet);
        String received = new String(packet.getData(), 0, packet.getLength());
        socket.close();
        return received;
    }
}

Обратите внимание, что вы можете использовать метод main класса myClient, чтобы проверить, что ваша установка работает без Mathematica, по существу устраняя одну потенциальную проблему из цикла.

4 голосов
/ 30 апреля 2011

Если предположить настройку, описанную в записи в блоге на веб-сайте iSeismometer, на ум приходит несколько вариантов.

Импорт

Первый вариант - использовать внешнюю программу для захвата пакетов, а затем использовать Import для получения результатов, например,

Import["!someexternalprog", "Lines"]

Увы, программа Python, упомянутая в сообщении в блоге, будетне работает хорошо здесь, так как он работает в бесконечном цикле, который должен быть вручную завершен.Подход Import будет работать только в том случае, если эта программа будет изменена для остановки после фиксированного количества пакетов или ограничения по времени или чего-то еще.

JLink

Альтернативный подходможет быть реализован без выхода из удобной среды Mathematica с помощью JLink.Ну, может быть, не стоит говорить о том, что мы остаемся в Mathematica, так как из кода Mathematica смешано довольно много забавного Java-кода.Тем не менее, он иллюстрирует полезность встроенного Java-дистрибутива, который поставляется с каждой копией Mathematica:

Needs["JLink`"]
LoadJavaClass["java.util.Arrays"];

ClearAll@ListenToISeismometer
ListenToISeismometer[port_] :=
  JavaBlock@Module[{socket, packet, listen, record = Null, listening = True}
  , packet = JavaNew["java.net.DatagramPacket", JavaNew["[B", 1024], 1024]
  ; listen[] :=
      If[$Failed =!= Quiet[socket@receive[packet], Java::excptn]
      , record =
          JavaNew[
            "java.lang.String"
          , java`util`Arrays`copyOfRange @@ packet /@ {getData[], getOffset[], getLength[]}
          ]@toString[] // Sow
      ]
  ; Row[{Button["Stop", listening = False], Dynamic[record]}, "  "] // PrintTemporary
  ; AbortProtect[
      socket = JavaNew["java.net.DatagramSocket", port]
    ; socket@setSoTimeout[1000]
    ; Reap[While[listening, listen[]]; socket@close[]][[2, 1]]
    ]
  ]

Некоторые ярлыки были сделаны в отношении обработки исключений, декодирования пакетов и тому подобного, чтобыдержите этот пример на управляемой длине.

ListenToISeismometer должен быть предоставлен номер порта UDP для прослушивания.Давайте использовать тот же порт, что и в сообщении в блоге, 10552:

In[33]:= data = ListenToISeismometer[10552];

stop button

Функция будет прослушивать все UDP-события на этом порту до тех пор, пока ей не будет приказано остановиться.Для этого представлена ​​кнопка, где каждый пакет мигает вдоль полученной стороны.Когда кнопка нажата, функция возвращает список полученных пакетов:

In[34]:= data // Column
Out[34]= 1,83575.099,0.029,0.044,0.094
         1,83575.781,0.056,0.033,0.099
         1,83575.924,0.047,0.054,0.094
         1,83575.613,0.096,0.092,0.057
         1,83575.748,0.073,0.049,0.061
         1,83575.577,0.008,0.089,0.020
         ...

JLink делает это возможным , но нельзя избежать того факта, что использование JLink требуетрабочее знание Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...