net.kuhlmeyer.vjlib.ViessmannCommunicator Maven / Gradle / Ivy
package net.kuhlmeyer.vjlib;
import gnu.io.*;
import org.apache.log4j.Logger;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Date;
public class ViessmannCommunicator {
private static Logger LOG = Logger.getLogger(ViessmannCommunicator.class);
private final Communicator communicator;
private InputStream is;
private OutputStream os;
public ViessmannCommunicator(Communicator communicator) {
super();
this.communicator = communicator;
}
public Double getNormaleRaumtemperatur() throws IOException {
return convertByteToDouble(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x06}), 1.0d);
}
public void setNormaleRaumtemperatur(short temperature) throws IOException {
if (temperature >= 3 && temperature <= 37) {
LOG.info("Setting normal room temperature to " + temperature);
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x06, temperature});
}
}
public Double getReduzierteRaumtemperatur() throws IOException {
return convertByteToDouble(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x07}), 1.0d);
}
public void setReduzierteRaumtemperatur(short temperature) throws IOException {
if (temperature >= 3 && temperature <= 37) {
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x07, temperature});
}
}
public Double getTemperaturPartybetrieb() throws IOException {
return convertByteToDouble(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x08}), 1.0d);
}
public void setTemperaturPartybetrieb(short temperature) throws IOException {
if (temperature >= 3 && temperature <= 37) {
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x08, temperature});
}
}
public Double getNeigung() throws IOException {
return convertByteToDouble(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x05}), 10.0d);
}
public void setNeigung(double temperature) throws IOException {
// TODO Zwischen 0.2 und 3.5
}
public Double getNiveau() throws IOException {
return convertByteToDouble(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x04}), 1.0d);
}
public void setNiveau(short temperature) throws IOException {
// TODO Zwischen -30 und 40
}
public Double getVerbrauch() throws IOException {
// TODO Mal B4 Probieren...Gefördertes Material Pellet 08B0 (oder 08B4)
return convertIntBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x04, new short[]{0x08, 0xb4}), 1000.0d);
}
public Double getAussenTemperatur() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x55, 0x25}), 10.0d);
}
public String getBetriebsArt() throws IOException {
// short[] response = sendAndReceive((short) 0x01, new short[] { 0x25,
// 0x00 });
short[] response = communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x23});
if (response != null && response.length > 0) {
switch (response[0]) {
case 0x00:
return "WW";
case 0x01:
return "RED";
case 0x02:
return "NORM";
case 0x03:
case 0x04:
return "H+WW";
case 0x05:
return "ABSCHALT";
}
}
LOG.info(String.format("BETRIEBSART IST: %s", response == null ? "null" : Arrays.toString(response)));
return "UNBEKANNT";
}
public boolean setBetriebsArt(OperatingMode betriebsArt) throws IOException {
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x23, betriebsArt.getSendByte()});
return true;
}
public Integer getBrennerStarts() throws IOException {
return convertIntBytesToInt(communicator.sendAndReceive(is, os, (short) 0x04, new short[]{0x08, 0x8a}));
}
public Double getBrennerStunden() throws IOException {
return convertIntBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x04, new short[]{0x08, 0xa7}), 3600.0d);
}
public Double getKesseltemperaturIst() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0xa2, 0x02}), 100.0d);
}
public Double getKesseltemperaturSoll() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0xa2, 0x66}), 100.0d);
}
public Double getKollektortemperatur() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x65, 0x64}), 10.0d);
}
public Double getLeistung() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0xA3, 0x05}), 10.0d);
}
public Double getMischer() throws IOException {
return convertByteToDouble(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x25, 0xc4}), 2.0d);
}
public Boolean getPartyBetrieb() throws IOException {
return convertByteToBoolean(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x03}), 1.0d);
}
public boolean setPartyBetrieb(boolean partyBetrieb) throws IOException {
if (partyBetrieb) {
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x03, 0x01});
} else {
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x03, 0x00});
}
return true;
}
public Double getRuecklaufIstM2() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x08, 0x0a}), 10.0d);
}
public Integer getSolarLeistung() throws IOException {
return convertIntBytesToInt(communicator.sendAndReceive(is, os, (short) 0x04, new short[]{0x65, 0x60}));
}
public Integer getSolarStunden() throws IOException {
return convertShortBytesToInt(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x65, 0x68}));
}
public Boolean getSparbetrieb() throws IOException {
return convertByteToBoolean(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x23, 0x02}), 1.0d);
}
public boolean setSparBetrieb(boolean partyBetrieb) throws IOException {
if (partyBetrieb) {
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x02, 0x01});
} else {
communicator.sendAndReceive(is, os, SendMode.Write, (short) 0x01, new short[]{0x23, 0x02, 0x00});
}
return true;
}
public Boolean getStatusHeizkreisPumpe() throws IOException {
return convertByteToBoolean(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x29, 0x06}), 1.0d);
}
public Boolean getStatusSolarpumpe() throws IOException {
return convertByteToBoolean(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x65, 0x52}), 1.0d);
}
public Boolean getStatusSpeicherladePumpe() throws IOException {
return convertByteToBoolean(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x08, 0x45}), 1.0d);
}
public Boolean getStatusWarmwasserSolar() throws IOException {
return convertByteToBoolean(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x65, 0x51}), 1.0d);
}
public Boolean getStatusZirkulationspumpe() throws IOException {
return convertByteToBoolean(communicator.sendAndReceive(is, os, (short) 0x01, new short[]{0x08, 0x46}), 1.0d);
}
public Double getTemperaturSpeicherUnten() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x65, 0x66}), 10.0d);
}
public Double getVorlaufIst() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x29, 0x00}), 10.0d);
}
public Double getVorlaufIstM2() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x08, 0x0c}), 10.0d);
}
public Double getVorlaufSollM1() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x25, 0x44}), 10.0d);
}
public Double getWarmwasserIst() throws IOException {
return convertShortBytesTodouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x08, 0x04}), 10.0d);
}
public Double getWarmwasserSoll() throws IOException {
return convertByteToDouble(communicator.sendAndReceive(is, os, (short) 0x02, new short[]{0x63, 0x00}), 1.0d);
}
private Double convertByteToDouble(short[] input, double div) {
if (input == null || input.length < 1) {
return null;
}
return input[0] / div;
}
private Double convertShortBytesTodouble(short[] input, double div) {
if (input == null || input.length < 2) {
return null;
}
return ((input[1] << 8) + input[0]) / div;
}
private Integer convertShortBytesToInt(short[] input) {
if (input == null || input.length < 2) {
return null;
}
return ((input[1] << 8) + input[0]);
}
private Integer convertIntBytesToInt(short[] input) {
if (input == null || input.length < 4) {
return null;
}
return ((input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0]);
}
private Double convertIntBytesTodouble(short[] input, double div) {
if (input == null || input.length < 4) {
return null;
}
return ((input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0]) / div;
}
private Boolean convertByteToBoolean(short[] input, double div) throws IOException {
Double doubleValue = convertByteToDouble(input, div);
if (doubleValue == null) {
return null;
}
return doubleValue == 0x01;
}
public void endTransmission() throws IOException {
os.write((byte) 0x04);
os.flush();
}
public boolean initializeTransmission() throws IOException {
os.flush();
os.write((byte) 0x04);
os.flush();
for (int i = 0; i < 50; i++) {
LOG.trace("Waiting for 0x05");
if (is.available() <= 0) {
sleep(200);
}
byte[] bytes = new byte[is.available()];
is.read(bytes);
if (LOG.isTraceEnabled()) {
StringBuilder logBuffer = new StringBuilder();
for (byte b : bytes) {
logBuffer.append(String.format("%02X", b));
}
LOG.trace(logBuffer.toString());
}
if (bytes != null && bytes.length > 0 && bytes[bytes.length - 1] == 0x05) {
os.write(new byte[]{0x16, 0x00, 0x00});
os.flush();
LOG.trace("sending 0x16 0x00 0x00");
byte resp = (byte) is.read();
LOG.trace("Received " + String.format("%02X", resp));
if (resp == 0x06) {
return true;
}
}
}
return false;
}
private void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException ex) {
LOG.error(ex);
}
}
public SerialPort openPort(final String viessmannDevice) throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, IOException {
LOG.debug("Opening port " + viessmannDevice);
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(viessmannDevice);
LOG.debug("Got port identifier");
if (portIdentifier.isCurrentlyOwned()) {
LOG.info("Port " + viessmannDevice + " is currently in use");
} else {
LOG.debug("Not owned. Now opening port " + viessmannDevice);
CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
if (commPort instanceof SerialPort) {
SerialPort serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(4800, SerialPort.DATABITS_8, SerialPort.STOPBITS_2, SerialPort.PARITY_EVEN);
serialPort.setDTR(false);
serialPort.setRTS(false);
is = serialPort.getInputStream();
os = serialPort.getOutputStream();
return serialPort;
}
LOG.error(String.format("Port '%s' is not an instance of a Serial Port. Class is %s", viessmannDevice, commPort.getClass().getName()));
}
return null;
}
public void closePort(SerialPort serialPort) throws IOException {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
if (serialPort != null) {
serialPort.close();
}
}
public ViessmannData collectHeatingData(final String viessmannDevice) throws IOException, PortInUseException, UnsupportedCommOperationException, NoSuchPortException {
SerialPort serialPort = null;
try {
LOG.debug("Opening port.. ");
serialPort = openPort(viessmannDevice);
LOG.debug("Initializing device connection ");
boolean initOK = initializeTransmission();
if(!initOK) {
LOG.warn("Initialization not successful. Cancelling transmission!");
}
if(initOK) {
LOG.debug("Collecting heating data from device ");
ViessmannData heatingData = new ViessmannData();
heatingData.setTimestamp(new Date());
heatingData.setTempAussen(getAussenTemperatur());
heatingData.setBetriebsArtM1(getBetriebsArt());
heatingData.setBrennerStarts(getBrennerStarts());
heatingData.setBrennerStunden1(getBrennerStunden());
heatingData.setTempKesselIst(getKesseltemperaturIst());
heatingData.setTempKesselSoll(getKesseltemperaturSoll());
heatingData.setTempKollektor(getKollektortemperatur());
heatingData.setLeistung(getLeistung());
heatingData.setMischerM1(getMischer());
heatingData.setNeigungM1(getNeigung());
heatingData.setNiveauM1(getNiveau());
heatingData.setTempRaumNormalSollM1(getNormaleRaumtemperatur());
heatingData.setStatusPartyBetriebM1(getPartyBetrieb());
heatingData.setTempRaumReduziertSollM1(getReduzierteRaumtemperatur());
heatingData.setTempRuecklaufIstM2(getRuecklaufIstM2());
heatingData.setSolarLeistung(getSolarLeistung());
heatingData.setSolarStunden(getSolarStunden());
heatingData.setStatusSparbetriebM1(getSparbetrieb());
heatingData.setStatusPumpeM1(getStatusHeizkreisPumpe());
heatingData.setStatusPumpeSolar(getStatusSolarpumpe());
heatingData.setStatusSpeicherladepumpe(getStatusSpeicherladePumpe());
heatingData.setStatusSolarNachladeunterdrueckung(getStatusWarmwasserSolar());
heatingData.setStatusPumpeZirkulation(getStatusZirkulationspumpe());
heatingData.setTempPartyM1(getTemperaturPartybetrieb());
heatingData.setTempSpeicherUnten(getTemperaturSpeicherUnten());
heatingData.setVerbrauch(getVerbrauch());
heatingData.setTempVorlaufIstM1(getVorlaufIst());
heatingData.setTempVorlaufIstM2(getVorlaufIstM2());
heatingData.setTempVorlaufSollM1(getVorlaufSollM1());
heatingData.setTempWWIst(getWarmwasserIst());
heatingData.setTempWWSoll(getWarmwasserSoll());
LOG.debug("Finished collecting heating data.");
return heatingData;
}
} catch (Throwable e) {
LOG.error("Error collecting data from device: '" + viessmannDevice + "'", e);
} finally {
endTransmission();
try {
closePort(serialPort);
} catch (IOException e) {
LOG.error("Error closing port: '" + viessmannDevice + "'", e);
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy