From c7946deb2d157e51ae8574ba5c6982b47b506f32 Mon Sep 17 00:00:00 2001 From: JustBru00 Date: Tue, 4 Jan 2022 13:11:59 -0500 Subject: [PATCH] Implemented the read portion of the modbus registers from Manual Section B.4.2. --- README.md | 3 +- .../multizone4j/MultiZoneDevice.java | 133 +++++++++++++++- .../reference/RefrigerantType.java | 146 ++++++++++++++++++ 3 files changed, 279 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/rbrubaker/multizone4j/reference/RefrigerantType.java diff --git a/README.md b/README.md index 65f9492..d8aea31 100644 --- a/README.md +++ b/README.md @@ -47,13 +47,14 @@ Bacharach documentation states that a modbus master device, such as this library You can view the release history and roadmap below: ### Roadmap -- Fully implement the 3000 series, read/write, Function Code 04/06 registers. (Manual Section B.4.2.) +- Implement the 3000 series, write, Function Code 06 registers. (Manual Section B.4.2.) - Fully implement the block mode registers for advanced remote setup and complete detail access. (Manual Section B.5.) ### Release History ``` Release version 0.1.0-SNAPSHOT: + Implemented all of the modbus registers from Manual Section B.4.1. ++ Implemented read only modbus registers from Manual Section B.4.2. Release version 0.1.0-SNAPSHOT: + Added MultiZoneDevice.getCurrentZoneStatus() diff --git a/src/main/java/com/rbrubaker/multizone4j/MultiZoneDevice.java b/src/main/java/com/rbrubaker/multizone4j/MultiZoneDevice.java index f70bf4a..8608420 100644 --- a/src/main/java/com/rbrubaker/multizone4j/MultiZoneDevice.java +++ b/src/main/java/com/rbrubaker/multizone4j/MultiZoneDevice.java @@ -11,6 +11,7 @@ import com.rbrubaker.multizone4j.reference.AlarmStatus; import com.rbrubaker.multizone4j.reference.CurrentState; import com.rbrubaker.multizone4j.reference.OperatingMode; +import com.rbrubaker.multizone4j.reference.RefrigerantType; /** * This class represents a single Bacharach MultiZone device. @@ -37,7 +38,7 @@ public MultiZoneDevice(int _modbusAddress, String _serialDeviceName) { * Manual Section B.4.1. * This method is blocks as it has to contact the modbus device * Gets the current zone ppm and alarm status for the given zone number. - * @param zoneNumber Zone numbers start with 0. So zone 1 is zonenumber=0. + * @param zoneNumber This method uses zone numbers that start with 0. So zone 1 is zonenumber=0. * @return * @throws ModbusException, Exception * @@ -102,7 +103,7 @@ public ArrayList getAllCurrentZoneStatuses() throws ModbusExc * @throws ModbusException * @throws Exception */ - private int readSingleFunction03RegisterAsInt(int registerNumber) throws ModbusException, Exception{ + private int readSingleFunction03RegisterAsInt(int registerNumber) throws ModbusException, Exception { ModbusSerialMaster master; SerialParameters params = new SerialParameters(serialDeviceName, 19200, AbstractSerialConnection.FLOW_CONTROL_DISABLED, AbstractSerialConnection.FLOW_CONTROL_DISABLED, 8, AbstractSerialConnection.ONE_STOP_BIT, AbstractSerialConnection.NO_PARITY, false); @@ -116,6 +117,20 @@ private int readSingleFunction03RegisterAsInt(int registerNumber) throws ModbusE return reg[0].getValue(); } + private int readSingleFunction04RegisterAsInt(int registerNumber) throws ModbusException, Exception { + ModbusSerialMaster master; + SerialParameters params = new SerialParameters(serialDeviceName, 19200, AbstractSerialConnection.FLOW_CONTROL_DISABLED, + AbstractSerialConnection.FLOW_CONTROL_DISABLED, 8, AbstractSerialConnection.ONE_STOP_BIT, AbstractSerialConnection.NO_PARITY, false); + master = new ModbusSerialMaster(params); + master.connect(); + + InputRegister[] reg = master.readInputRegisters(modbusAddress, registerNumber, 1); + + master.disconnect(); + + return reg[0].getValue(); + } + /** * Manual Section B.4.1. * This method blocks as it has to contact the modbus device. @@ -369,4 +384,118 @@ public double getAveAu() throws ModbusException, Exception { public int getBenchPpm() throws ModbusException, Exception { return readSingleFunction03RegisterAsInt(2054); } + + /** + * Manual Section B.4.2. + * This method blocks as it has to contact the modbus device. + * @param zoneNumber This method uses zone numbers that start with 0. So zone 1 is zonenumber=0. + * @return An integer representing the refrigerant type. Use {@link RefrigerantType} to decode the refrigerant type. + * @throws ModbusException + * @throws Exception + */ + public int getRefrigerantType(int zoneNumber) throws ModbusException, Exception, IllegalArgumentException { + if (zoneNumber < 0 || zoneNumber > 15) { + throw new IllegalArgumentException("The zone number must be between 0-15. The zone number is base 0. Ex. Zone 1 = zoneNumber=0"); + } + + return readSingleFunction04RegisterAsInt(3000 + zoneNumber); + } + + /** + * Manual Section B.4.2. + * This method blocks as it has to contact the modbus device. + * @param zoneNumber This method uses zone numbers that start with 0. So zone 1 is zonenumber=0. + * @return The current leak level setpoint for the given zone. + * @throws ModbusException + * @throws Exception + * @throws IllegalArgumentException + */ + public int getLeakLevelSetpoint(int zoneNumber) throws ModbusException, Exception, IllegalArgumentException { + if (zoneNumber < 0 || zoneNumber > 15) { + throw new IllegalArgumentException("The zone number must be between 0-15. The zone number is base 0. Ex. Zone 1 = zoneNumber=0"); + } + + return readSingleFunction04RegisterAsInt(3016 + zoneNumber); + } + + /** + * Manual Section B.4.2. + * This method blocks as it has to contact the modbus device. + * @param zoneNumber This method uses zone numbers that start with 0. So zone 1 is zonenumber=0. + * @return The current spill level setpoint for the given zone. + * @throws ModbusException + * @throws Exception + * @throws IllegalArgumentException + */ + public int getSpillLevelSetpoint(int zoneNumber) throws ModbusException, Exception, IllegalArgumentException { + if (zoneNumber < 0 || zoneNumber > 15) { + throw new IllegalArgumentException("The zone number must be between 0-15. The zone number is base 0. Ex. Zone 1 = zoneNumber=0"); + } + + return readSingleFunction04RegisterAsInt(3032 + zoneNumber); + } + + /** + * Manual Section B.4.2. + * This method blocks as it has to contact the modbus device. + * @param zoneNumber This method uses zone numbers that start with 0. So zone 1 is zonenumber=0. + * @return The current evacuation level setpoint for the given zone. + * @throws ModbusException + * @throws Exception + * @throws IllegalArgumentException + */ + public int getEvacuationLevelSetpoint(int zoneNumber) throws ModbusException, Exception, IllegalArgumentException { + if (zoneNumber < 0 || zoneNumber > 15) { + throw new IllegalArgumentException("The zone number must be between 0-15. The zone number is base 0. Ex. Zone 1 = zoneNumber=0"); + } + + return readSingleFunction04RegisterAsInt(3048 + zoneNumber); + } + + /** + * Manual Section B.4.2. + * This method blocks as it has to contact the modbus device. + * @param zoneNumber This method uses zone numbers that start with 0. So zone 1 is zonenumber=0. + * @return The sample tube distance setpoint. + * @throws ModbusException + * @throws Exception + * @throws IllegalArgumentException + */ + public int getSampleDistanceSetpoint(int zoneNumber) throws ModbusException, Exception, IllegalArgumentException { + if (zoneNumber < 0 || zoneNumber > 15) { + throw new IllegalArgumentException("The zone number must be between 0-15. The zone number is base 0. Ex. Zone 1 = zoneNumber=0"); + } + + return readSingleFunction04RegisterAsInt(3064 + zoneNumber); + } + + /** + * Manual Section B.4.2. + * This method blocks as it has to contact the modbus device. + * @param zoneNumber This method uses zone numbers that start with 0. So zone 1 is zonenumber=0. + * @return The alarm acknowledge state for the given zone. 1=Acknowledged, 0=Unacknowledged + * @throws ModbusException + * @throws Exception + * @throws IllegalArgumentException + */ + public int getAlarmAcknowledgeState(int zoneNumber) throws ModbusException, Exception, IllegalArgumentException { + if (zoneNumber < 0 || zoneNumber > 15) { + throw new IllegalArgumentException("The zone number must be between 0-15. The zone number is base 0. Ex. Zone 1 = zoneNumber=0"); + } + + return readSingleFunction04RegisterAsInt(3080 + zoneNumber); + } + + /** + * Manual Section B.4.2. + * This method blocks as it has to contact the modbus device. + * @return The alarm acknowledge state for all zones. + * @throws ModbusException + * @throws Exception + */ + public int getAllAlarmAcknowledgeState() throws ModbusException, Exception { + return readSingleFunction04RegisterAsInt(3096); + } + + } diff --git a/src/main/java/com/rbrubaker/multizone4j/reference/RefrigerantType.java b/src/main/java/com/rbrubaker/multizone4j/reference/RefrigerantType.java new file mode 100644 index 0000000..292d319 --- /dev/null +++ b/src/main/java/com/rbrubaker/multizone4j/reference/RefrigerantType.java @@ -0,0 +1,146 @@ +package com.rbrubaker.multizone4j.reference; + +public class RefrigerantType { + + public static final int CO2_R744 = 0; + public static final int NH3_R717 = 0; + public static final int R11 = 0; + public static final int R12 = 1; + public static final int R22 = 2; + public static final int R23 = 3; + public static final int R113 = 4; + public static final int R114 = 5; + public static final int R123 = 6; + public static final int R124 = 7; + public static final int R134A = 8; + public static final int R401A = 9; + public static final int R402A = 10; + public static final int R402B = 11; + public static final int R404A = 12; + public static final int R407A = 13; + public static final int R407C = 14; + public static final int R409A = 15; + public static final int R410A = 16; + public static final int R500 = 17; + public static final int R502 = 18; + public static final int R503 = 19; + public static final int R507 = 20; + public static final int R508B = 21; + public static final int H1301 = 22; + public static final int R408A = 23; + public static final int FA188 = 24; + public static final int R236FA = 25; + public static final int N1230 = 26; + public static final int R227 = 27; + public static final int HFP = 28; + public static final int FC72 = 29; + public static final int R21 = 30; + public static final int R125 = 31; + public static final int H1211 = 32; + public static final int H2402 = 33; + public static final int R245FA = 34; + public static final int R422A = 35; + public static final int R422D = 36; + public static final int R427A = 37; + public static final int H1234YF = 38; + public static final int R424A = 39; + public static final int R426A = 40; + public static final int R438A = 41; + public static final int R32 = 42; + public static final int H1234ZE = 43; + public static final int R407F = 44; + public static final int N7100 = 45; + public static final int N7200 = 46; + public static final int N7300 = 47; + public static final int N7600 = 48; + public static final int H1233ZDE = 49; + public static final int N4710 = 50; + public static final int R448A = 51; + public static final int R449A = 52; + public static final int R513A = 53; + public static final int R452A = 54; + public static final int R452B = 55; + public static final int R514A = 56; + public static final int H1336E = 57; + public static final int H1336Z = 58; + public static final int N5110 = 59; + public static final int R454A = 60; + public static final int R454B = 61; + public static final int R454C = 62; + public static final int R455A = 63; + public static final int H1224ydZ = 64; + public static final int FC3284 = 65; + + public String getValueOf(int refrigerantType) { + switch (refrigerantType) { + case 0: return "CO2/R-744, NH3/R-717, R-11"; + case 1: return "R-12"; + case 2: return "R-22"; + case 3: return "R-23"; + case 4: return "R-113"; + case 5: return "R-114"; + case 6: return "R-123"; + case 7: return "R-124"; + case 8: return "R-134A"; + case 9: return "R-401A"; + case 10: return "R-402A"; + case 11: return "R-402B"; + case 12: return "R-404A"; + case 13: return "R-407A"; + case 14: return "R-407C"; + case 15: return "R-409A"; + case 16: return "R-410A"; + case 17: return "R-500"; + case 18: return "R-502"; + case 19: return "R-503"; + case 20: return "R-507"; + case 21: return "R-508B"; + case 22: return "H1301"; + case 23: return "R-408A"; + case 24: return "FA188"; + case 25: return "R-236FA"; + case 26: return "N1230"; + case 27: return "R-227"; + case 28: return "HFP"; + case 29: return "FC72"; + case 30: return "R-21"; + case 31: return "R-125"; + case 32: return "H1211"; + case 33: return "H2402"; + case 34: return "R-245FA"; + case 35: return "R-422A"; + case 36: return "R-422D"; + case 37: return "R-427A"; + case 38: return "H1234YF"; + case 39: return "R-424A"; + case 40: return "R-426A"; + case 41: return "R-438A"; + case 42: return "R-32"; + case 43: return "H1234ZE"; + case 44: return "R-407F"; + case 45: return "N7100"; + case 46: return "N7200"; + case 47: return "N7300"; + case 48: return "N7600"; + case 49: return "H1233ZDE"; + case 50: return "N4710"; + case 51: return "R-448A"; + case 52: return "R-449A"; + case 53: return "R-513A"; + case 54: return "R-452A"; + case 55: return "R-452B"; + case 56: return "R-514A"; + case 57: return "H1336E"; + case 58: return "H1336Z"; + case 59: return "N5110"; + case 60: return "R-454A"; + case 61: return "R-454B"; + case 62: return "R-454C"; + case 63: return "R-455A"; + case 64: return "H1224ydZ"; + case 65: return "FC3284"; + default: return "Unknown refrigerant type"; + } + } + +}