Closed AnaKatarina closed 9 years ago
What you want is KNX process communication. There is an example in the introduction repository here. This allows you to read and write datapoints. You can create the different datapoints of your weather station using either several StateDPs, or supply directly the DPTXlator instances of the DPTs you use for translating the KNX data. To listen to incoming changes, add a ProcessListener to the process communicator.
Whether you use routing or tunneling, it does not really make a difference. You only have to select your choice in the IP network link constructor via the service mode parameter. Some differences are that KNX routers often support only one active tunnel connection, in routing mode packets are not acknowledged (in tunneling mode they are). You can easily try both and use what better fits your setup.
Thank you for the explanation.
Today I tried this code and it's working but only for rain because only that parameter is boolean true/false statement. Do you know how should I write the rest of the code for temperature (data type 9.001 °C), wind speed (data type 9.005 meter per second), brightness (data type 9.004 lux), morning/evening (data type 1.001 switch)? Where could I found that? This library supports these data type right?
package projFiles;
import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.InetSocketAddress;
import tuwien.auto.calimero.DetachEvent; import tuwien.auto.calimero.GroupAddress; import tuwien.auto.calimero.KNXAddress; import tuwien.auto.calimero.Priority; import tuwien.auto.calimero.cemi.CEMILData; import tuwien.auto.calimero.datapoint.Datapoint; import tuwien.auto.calimero.dptxlator.DPT; import tuwien.auto.calimero.exception.KNXException; import tuwien.auto.calimero.exception.KNXTimeoutException; import tuwien.auto.calimero.link.KNXLinkClosedException; import tuwien.auto.calimero.link.KNXNetworkLink; import tuwien.auto.calimero.link.KNXNetworkLinkIP; import tuwien.auto.calimero.link.KNXNetworkMonitorIP; import tuwien.auto.calimero.link.NetworkLinkListener; import tuwien.auto.calimero.link.medium.KNXMediumSettings; import tuwien.auto.calimero.link.medium.TPSettings; import tuwien.auto.calimero.process.ProcessCommunicator; import tuwien.auto.calimero.process.ProcessCommunicatorImpl; import tuwien.auto.calimero.process.ProcessEvent; import tuwien.auto.calimero.process.ProcessListener;
public class MainClass {
/**
* Address of your KNXnet/IP server. Replace the IP address as necessary.
*/
private static final String remoteHost = "192.168.1.220";
/**
* We will read a boolean from this KNX datapoint group address, replace the address string with
* one of yours. Make sure this datapoint exists, otherwise you will get a read timeout!
*/
private static final String group = "4/1/2";
public static void main(String[] args) {
// TODO Auto-generated method stub
KNXNetworkLink knxLink = null;
ProcessCommunicator pc = null;
try {
// Create our network link. See other constructors if this one assumes too many
// default settings.
knxLink = new KNXNetworkLinkIP(remoteHost, TPSettings.TP1);
// create a process communicator using that network link
pc = new ProcessCommunicatorImpl(knxLink);
System.out.println("read the group value from datapoint " + group);
// this is a blocking method to read a boolean from a KNX datapoint
final boolean value = pc.readBool(new GroupAddress(group));
System.out.println("value read from datapoint " + group + ": " + value);
pc.addProcessListener(new ProcessListener() {
@Override
public void groupWrite(ProcessEvent arg0) {
// TODO Auto-generated method stub
//The groupWrite() method of your handler will then be called on every received A_GroupWrite indication, with the received message as a parameter (wrapped in a ProcessEvent). Look at ProcessListenerEx for an example how to decode the payload.
System.out.println("groupWrite");
}
@Override
public void detached(DetachEvent arg0) {
// TODO Auto-generated method stub
System.out.println("detached");
}
});
Thread.sleep(10000);
}
catch (final KNXException e) {
System.out.println("Error reading KNX datapoint: " + e.getMessage());
}
catch (final InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
finally {
// we don't need the process communicator anymore, detach it from the link
if (pc != null)
pc.detach();
// close the KNX link
if (knxLink != null)
knxLink.close();
}
}
}
The first image shows false because the sensor was dry and then I poured sensor with water and then it was written true.
DPT 9.x is the KNX 2-byte float. Use pc.readFloat(new GroupAddress(temperature), false)
and pc.readFloat(new GroupAddress(windspeed), false)
, where temperature
and windspeed
are the corresponding datapoints. This returns you the value as Java type float
.
Alternatively, if you want to have a datapoint value formatted as string with the unit of measurement appended, use something like
final Datapoint dp = new StateDP(new GroupAddress(temperature),
"Weather station temperature", 0, "9.001");
String s = pc.read(dp);
Thank you, I did it, can you explain how to catch telegrams from weather station through ProcessListener? I don't understand that part very well
For example, the program is running and then happens some changes and weather station sends telegrams automaticaly
You already added the process listener. I would suggest to replace ProcessListener
with ProcessListenerEx. This provides you with methods like asFloat
, so you can easily convert to, e.g., a Java floating point type.
As a start copy this in all your process listener methods (or create a method for it):
try {
System.out.println(LocalTime.now() +" " + svc + " " + e.getSourceAddr() + "->"
+ e.getDestination() + ": " + DataUnitBuilder.toHex(e.getASDU(), ""));
}
catch (final KNXFormatException | RuntimeException ex) {}
This prints you for every notification the KNX source/destination, and data of your weather station in hexadecimal format. It works for any datapoint (you basically created a very simple KNX group monitor).
In your case, a straightforward implementation for data formatting, because you know your DPTs, is the following (shown for the temperature datapoint; copy the following code into the try
block from above):
if (e.getDestination().equals(new GroupAddress(temperature))) {
final double v = asFloat(e, false);
System.out.println("Temperature changed to " + v);
}
Similar for your other datapoints.
HTH, Boris
An example of a simple group monitor I put here.
Thanks for explanation! It works! One more question, which protocol is used for sending telegrams in this library? UDP or TCP/IP?
KNXnet/IP uses UDP.
Hi, I'm Ana Katarina from Croatia and my task is to make a desktop application that will be able to connect with the KNX / IP router and receive telegram from weather station and save that parameters to database. I'm using Schneider knx router and ETS 3 software. My weather station sends rain as a bit- rain/no rain, temperature, brightness value-lux, is it morning or evening also as bit and wind speed in meters per second.
In my university it's unicast, does that make some difference in code? Because when I was looking for the right code for my project it's mulitcast everywhere.
If I only want to connect to router and receive telegrams from weather station I only need class for connection and class for routing?