bmwcarit / barefoot

Java map matching library for integrating the map into software and services with state-of-the-art online and offline map matching that can be used stand-alone and in the cloud.
Apache License 2.0
665 stars 186 forks source link

Sending json to Tracker Monitor failing #87

Closed Trevirirus closed 6 years ago

Trevirirus commented 6 years ago

Hi Sebastian,

I really appreciate your great work on this nice project!!

But i ran into some problems using the tracker server.

ISSUE: With jQuery send JSON Data is not accepted at the Server I build a little webpage displaying my GNSS live positions on a nice little OpenLayers Map. So i wan't to use the tracker server to match my live tracked data to the osm data. I'm trying to send the computed positions via a jQuery ajax POST request to the tracker server running on my separate Ubuntu machine. But the response by the tracker server is always ERROR. The tracker server outputs into the console:

2018-01-26 08:16:49,802 ERROR [pool-2-thread-2] TrackerServer: A JSONObject text must begin with '{' at character 1 org.json.JSONException: A JSONObject text must begin with '{' at character 1 at org.json.JSONTokener.syntaxError(JSONTokener.java:410) at org.json.JSONObject.(JSONObject.java:179) at org.json.JSONObject.(JSONObject.java:402) at com.bmwcarit.barefoot.tracker.TrackerServer$MatcherResponseFactory$2.response(TrackerServer.java:155) at com.bmwcarit.barefoot.util.AbstractServer$ResponseHandler.call(AbstractServer.java:143) at com.bmwcarit.barefoot.util.AbstractServer$ResponseHandler.call(AbstractServer.java:119) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)

How i'm building my JSON Data:

var obj = {
    "point": "POINT(13.76156 50.995984)",
    "time": "2015-06-29 04:45:33+0200",
    "id": "id"
  };

  $.ajax({
    url: url,
    type: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    data: JSON.stringify(obj),
    dataType: "json",
    success: function (data) {
      alert(data);
    }
  });

What I tried else: Sending an JSON object instead of a JSON string is not working either. Using the provided python script from the project is working fine with the test data also with other data. But here i'm not getting an SUCCESS output into the console as mentioned in the docs.

smattheis commented 6 years ago

Thanks for the feedback. I'm not familiar with ajax, but it looks like you're sending a HTTP request. This is not supported, the tracker provides only a REST-like API on TCP, no REST API on HTTP. If you try it with netcat as shown below, it should work:

echo "{\"point\":\"POINT(13.76156 50.995984)\",\"time\":\"2015-06-29 04:45:33+0200\",\"id\":\"id\"}" | netcat localhost 1234

AFAIK, a connection from a browser to TCP socket is not straight-forward. The best way is a NodeJS server that accepts your HTTP requests from the the browser and forwards the TCP messages to the tracker via, e.g., net.Socket as shown here: https://nodejs.org/api/net.html#net_class_net_socket

Trevirirus commented 6 years ago

Thanks for your reply. Just didn't know the server is just using TCP sockets. So i switched from javascript to python. And got another problem:

There is always a request handler timeout:

2018-01-26 15:54:01,723 ERROR [Thread-91] AbstractServer: 192.168.1.14:50692 request handler timeout

Python socket Code:

sample = {"time": "{}".format(time), "id":"{}".format(randint(0,1000)), "point":"POINT({} {})".format(lon, lat)}
        nachricht = json.dumps(sample)
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect((ip, port))
            s.send(nachricht.encode())
            s.send(nachricht.encode())
            answer = s.recv(1024)
            print(answer.decode())
            s.close()
            return lat, lon
        except Exception as e:
            return lat, lon
            print(e)

What i tried: Upscaling the timeout in the tracker server config is not helping. Setting a socket timeout in python is also not helping. The coordinates are surely within my OSM extract. netcat is sadly no option.

smattheis commented 6 years ago

Thanks for providing the nice code snippet: I think you only miss a newline. For me, this works for the example provided in the repo:

import socket,json

def main():
    with open("src/test/resources/com/bmwcarit/barefoot/matcher/x0001-001.json") as file:
        samples = json.load(file)
    for sample in samples:
        message = json.dumps(sample) + "\n"
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.connect(("localhost", 1234))
            sock.send(message.encode())
            response = sock.recv(1024)
            print(response.decode())
            sock.close()
        except Exception as e:
            print(e)

if __name__== "__main__":
    main()
Trevirirus commented 6 years ago

Thanks for your answer that solved my Problems with sending the Data.

Am i right that the results of the map matching are published on the port specified inside the tracker.config under: tracker.port=1235?

Do you have any hint to decode the byte response to a python object?

smattheis commented 6 years ago

Yes, that's the right port. However, there you have to connect via ZeroMQ (there is a ZeroMQ binding for almost any language available) because it follows a publish/subscribe communication pattern. Further, the real-time tracker tool-chain is more or less a demo/example and, hence, uses an output format that is tailored for visualization with the provided monitor (NodeJS + OpenLayers), see https://github.com/bmwcarit/barefoot/blob/master/src/main/java/com/bmwcarit/barefoot/tracker/TrackerServer.java#L267. That means, if you need a different output format for your application you may need to customize the publish and delete methods.

Trevirirus commented 6 years ago

Nice ZeroMQ was the right hint! :thumbsup: As i'm also using OpenLayers with the tracker servers response all is working fine !