/*
*
* Copyright (C) 2012-2014 R T Huitema. All Rights Reserved.
* Web: www.42.co.nz
* Email: robert@42.co.nz
* Author: R T Huitema
*
* This file is part of the signalk-server-java project
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package nz.co.fortytwo.signalk.server;
import static nz.co.fortytwo.signalk.util.SignalKConstants.FORMAT_DELTA;
import static nz.co.fortytwo.signalk.util.SignalKConstants.POLICY_FIXED;
import static nz.co.fortytwo.signalk.util.SignalKConstants.dot;
import static nz.co.fortytwo.signalk.util.SignalKConstants.env;
import static nz.co.fortytwo.signalk.util.SignalKConstants.env_wind;
import static nz.co.fortytwo.signalk.util.SignalKConstants.env_wind_angleApparent;
import static nz.co.fortytwo.signalk.util.SignalKConstants.env_wind_speedApparent;
import static nz.co.fortytwo.signalk.util.SignalKConstants.vessels_dot_self_dot;
import java.io.File;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import mjson.Json;
import nz.co.fortytwo.signalk.client.StompConnection;
import nz.co.fortytwo.signalk.model.SignalKModel;
import nz.co.fortytwo.signalk.model.impl.SignalKModelFactory;
import nz.co.fortytwo.signalk.util.SignalKConstants;
import nz.co.fortytwo.signalk.util.TestHelper;
import org.apache.activemq.transport.stomp.Stomp;
import org.apache.activemq.transport.stomp.Stomp.Headers.Subscribe;
import org.apache.activemq.transport.stomp.StompFrame;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.websocket.WebsocketConstants;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;
import org.fusesource.mqtt.client.BlockingConnection;
import org.fusesource.mqtt.client.MQTT;
import org.fusesource.mqtt.client.Message;
import org.fusesource.mqtt.client.QoS;
import org.fusesource.mqtt.client.Topic;
import org.fusesource.stomp.client.Constants;
import org.junit.Test;
public class MqttTest extends SignalKCamelTestSupport {
static Logger logger = LogManager.getLogger(MqttTest.class);
@Test
public void testSubscribe() throws Exception {
// fill the model with data
SignalKModel model = SignalKModelFactory.getMotuTestInstance();
model.putAll(TestHelper.getBasicModel().getFullData());
// create MQTT connection
MQTT mqtt = new MQTT();
mqtt.setHost("localhost", 1883);
BlockingConnection connection = mqtt.blockingConnection();
logger.debug("Opened MQTT socket, connecting.. ");
connection.connect();
// StompFrame connect = connection.receive();
// if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
// throw new Exception ("Not connected");
// }
logger.debug("connected" + connection.toString());
// create a private receive queue
String uuid = UUID.randomUUID().toString();
Topic[] topics = { new Topic("signalk/" + uuid
+ "/vessels/motu/navigation", QoS.AT_LEAST_ONCE) };
connection.subscribe(topics);
// subscribe
Json subMsg = getSubscribe("vessels." + SignalKConstants.self, "navigation", 1000, 0,
FORMAT_DELTA, POLICY_FIXED);
subMsg.set(Constants.REPLY_TO.toString(), "signalk." + uuid
+ ".vessels.motu.navigation");
subMsg.set(WebsocketConstants.CONNECTION_KEY, uuid);
subMsg.set(nz.co.fortytwo.signalk.util.ConfigConstants.OUTPUT_TYPE,
nz.co.fortytwo.signalk.util.ConfigConstants.OUTPUT_MQTT);
// HashMap<String,String> headers = new HashMap<String,String>();
// queue>signalk.3202a939-1681-4a74-ad4b-3a90212e4f33.vessels.motu.navigation
// set private queue to receive data
// headers.put("reply-to","/queue/signalk."+uuid+".vessels.motu.navigation");
// headers.put(WebsocketConstants.CONNECTION_KEY, uuid);
connection.publish("signalk.put", subMsg.toString().getBytes(),
QoS.AT_LEAST_ONCE, false);
logger.debug("Sent subscribe msg: " + subMsg);
// listen for messages
Message message = connection.receive(5, TimeUnit.SECONDS);
String body = new String(message.getPayload());
logger.debug("Body: " + body);
message.ack();
assertNotNull(body);
Json reply = Json.read(body);
assertNotNull(reply.at(SignalKConstants.CONTEXT));
assertNotNull(reply.at(SignalKConstants.UPDATES));
// unsubscribe
subMsg = getSubscribe("vessels." + SignalKConstants.self, "navigation", 1000, 0,
FORMAT_DELTA, POLICY_FIXED);
// connection.send("/queue/signalk.put", subMsg.toString(),null,
// headers);
// connection.unsubscribe("/queue/signalk."+uuid+".vessels.motu.navigation");
// disconnect
connection.disconnect();
}
@Test
public void testSendingUpdate() throws Exception {
// fill the model with data
SignalKModel model = SignalKModelFactory.getMotuTestInstance();
// create MQTT connection
MQTT mqtt = new MQTT();
mqtt.setHost("localhost", 1883);
BlockingConnection connection = mqtt.blockingConnection();
logger.debug("Opened MQTT socket, connecting.. ");
connection.connect();
logger.debug("connected" + connection.toString());
connection
.publish(
"signalk.put",
FileUtils
.readFileToByteArray(new File(
"src/test/resources/samples/windAngleUpdate.json.txt")),
QoS.AT_LEAST_ONCE, false);
latch.await(2, TimeUnit.SECONDS);
log.debug("model:" + model);
assertEquals(2.0,
model.getValue(vessels_dot_self_dot + env_wind_angleApparent));
assertEquals(6.8986404,
model.getValue(vessels_dot_self_dot + env_wind_speedApparent));
// disconnect
connection.disconnect();
}
@Test
public void testSendingList() throws Exception {
// fill the model with data
SignalKModel model = SignalKModelFactory.getMotuTestInstance();
model.putAll(TestHelper.getBasicModel().getFullData());
// create MQTT connection
MQTT mqtt = new MQTT();
mqtt.setHost("localhost", 1883);
BlockingConnection connection = mqtt.blockingConnection();
logger.debug("Opened MQTT socket, connecting.. ");
connection.connect();
// StompFrame connect = connection.receive();
// if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
// throw new Exception ("Not connected");
// }
logger.debug("connected" + connection.toString());
// create a private receive queue
String uuid = UUID.randomUUID().toString();
Topic[] topics = { new Topic("signalk/" + uuid
+ "/vessels/motu/navigation", QoS.AT_LEAST_ONCE) };
connection.subscribe(topics);
latch.await(2, TimeUnit.SECONDS);
// send get
Json subMsg = getList("vessels." + SignalKConstants.self, "navigation.position.*");
subMsg.set(Constants.REPLY_TO.toString(), "signalk." + uuid
+ ".vessels.motu.navigation");
subMsg.set(WebsocketConstants.CONNECTION_KEY, uuid);
// HashMap<String,String> headers = new HashMap<String,String>();
// queue>signalk.3202a939-1681-4a74-ad4b-3a90212e4f33.vessels.motu.navigation
// set private queue to receive data
// headers.put("reply-to","/queue/signalk."+uuid+".vessels.motu.navigation");
// headers.put(WebsocketConstants.CONNECTION_KEY, uuid);
connection.publish("signalk.put", subMsg.toString().getBytes(),
QoS.AT_LEAST_ONCE, false);
logger.debug("Sent get msg: " + subMsg);
// listen for messages
Message message = connection.receive(5, TimeUnit.SECONDS);
String body = new String(message.getPayload());
logger.debug("Body: " + body);
message.ack();
assertNotNull(body);
Json reply = Json.read(body);
assertNotNull(reply.at(SignalKConstants.CONTEXT));
assertNotNull(reply.at(SignalKConstants.PATHLIST));
// unsubscribe
// disconnect
connection.disconnect();
}
@Test
public void testSendingGetFull() throws Exception {
// fill the model with data
SignalKModel model = SignalKModelFactory.getMotuTestInstance();
model.putAll(TestHelper.getBasicModel().getFullData());
// create MQTT connection
MQTT mqtt = new MQTT();
mqtt.setHost("localhost", 1883);
BlockingConnection connection = mqtt.blockingConnection();
logger.debug("Opened MQTT socket, connecting.. ");
connection.connect();
// StompFrame connect = connection.receive();
// if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
// throw new Exception ("Not connected");
// }
logger.debug("connected" + connection.toString());
// create a private receive queue
String uuid = UUID.randomUUID().toString();
Topic[] topics = { new Topic("signalk/" + uuid
+ "/vessels/motu/navigation", QoS.AT_LEAST_ONCE) };
connection.subscribe(topics);
latch.await(2, TimeUnit.SECONDS);
// send get
Json subMsg = getGet("vessels." + SignalKConstants.self, env_wind + ".*",
SignalKConstants.FORMAT_FULL);
subMsg.set(Constants.REPLY_TO.toString(), "signalk." + uuid
+ ".vessels.motu.navigation");
subMsg.set(WebsocketConstants.CONNECTION_KEY, uuid);
// HashMap<String,String> headers = new HashMap<String,String>();
// queue>signalk.3202a939-1681-4a74-ad4b-3a90212e4f33.vessels.motu.navigation
// set private queue to receive data
// headers.put("reply-to","/queue/signalk."+uuid+".vessels.motu.navigation");
// headers.put(WebsocketConstants.CONNECTION_KEY, uuid);
connection.publish("signalk.put", subMsg.toString().getBytes(),
QoS.AT_LEAST_ONCE, false);
logger.debug("Sent get msg: " + subMsg);
// listen for messages
Message message = connection.receive(5, TimeUnit.SECONDS);
String body = new String(message.getPayload());
logger.debug("Body: " + body);
message.ack();
assertNotNull(body);
Json reply = Json.read(body);
assertNotNull(reply.at(SignalKConstants.vessels));
assertNotNull(reply.at(SignalKConstants.vessels).at(SignalKConstants.self).at(env)
.at("wind"));
// unsubscribe
// connection.unsubscribe("/queue/signalk."+uuid+"."+vessels_dot_self_dot+env_wind);
// disconnect
connection.disconnect();
}
@Test
public void testSendingGetDelta() throws Exception {
// fill the model with data
SignalKModel model = SignalKModelFactory.getMotuTestInstance();
model.putAll(TestHelper.getBasicModel().getFullData());
// create STOMP connection
StompConnection connection = new StompConnection();
connection.open("localhost", 61613);
logger.debug("Opened STOMP socket, connecting.. ");
StompFrame connect = connection.connect("system", "manager");
// StompFrame connect = connection.receive();
if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
throw new Exception("Not connected");
}
logger.debug("connected" + connect.getHeaders());
// create a private receive queue
String uuid = UUID.randomUUID().toString();
connection
.subscribe("/queue/signalk." + uuid + "."
+ vessels_dot_self_dot + env_wind,
Subscribe.AckModeValues.AUTO);
latch.await(2, TimeUnit.SECONDS);
// send list
Json subMsg = getGet("vessels." + SignalKConstants.self, env_wind + ".*",
SignalKConstants.FORMAT_DELTA);
HashMap<String, String> headers = new HashMap<String, String>();
logger.debug("sending" + subMsg);
// queue>signalk.3202a939-1681-4a74-ad4b-3a90212e4f33.vessels.motu.navigation
// set private queue to receive data
headers.put("reply-to", "/queue/signalk." + uuid + dot
+ vessels_dot_self_dot + env_wind);
headers.put(WebsocketConstants.CONNECTION_KEY, uuid);
connection.send("/queue/signalk.put", subMsg.toString(), null, headers);
// listen for messages
StompFrame message = connection.receive();
logger.debug("Body: " + message.getBody());
assertNotNull(message);
Json reply = Json.read(message.getBody());
assertNotNull(reply.at(SignalKConstants.CONTEXT));
assertNotNull(reply.at(SignalKConstants.UPDATES));
// unsubscribe
connection.unsubscribe("/queue/signalk." + uuid + "."
+ vessels_dot_self_dot + env_wind);
// disconnect
connection.disconnect();
}
@Override
public void configureRouteBuilder(RouteBuilder routeBuilder) {
try {
((RouteManager) routeBuilder).configure0();
} catch (Exception e) {
// TODO Auto-generated catch block
logger.error(e);
fail();
}
}
}