package com.intelligt.modbus.jlibmodbus.data; import com.intelligt.modbus.jlibmodbus.Modbus; import com.intelligt.modbus.jlibmodbus.exception.IllegalDataAddressException; import com.intelligt.modbus.jlibmodbus.exception.IllegalDataValueException; import com.intelligt.modbus.jlibmodbus.utils.DataUtils; import java.util.Arrays; /* * Copyright (C) 2016 "Invertor" Factory", JSC * [http://www.sbp-invertor.ru] * * This file is part of JLibModbus. * * 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. * * Authors: Vladislav Y. Kochedykov, software engineer. * email: vladislav.kochedykov@gmail.com */ /** * since 1.2.8.4 it extends Observable to notify observers if register values was changed. * * @see java.util.Observable * @see java.util.Observer */ public class ModbusHoldingRegisters extends ModbusValues { private int[] registers = new int[0]; public ModbusHoldingRegisters(int size) { registers = new int[(Modbus.checkEndAddress(size) ? size : Modbus.MAX_START_ADDRESS)]; } public ModbusHoldingRegisters() { } void setSize(int size) { synchronized (this) { if (registers.length != size) { registers = Arrays.copyOf(registers, size); } } } protected void checkOffsetAndValue(int offset, int value) throws IllegalDataValueException, IllegalDataAddressException { checkAddress(offset); checkValue(value); } @Override public void setImpl(int offset, Integer value) throws IllegalDataAddressException, IllegalDataValueException { checkAddress(offset); checkValue(value); synchronized (this) { registers[offset] = value; } } public void setRange(int offset, int[] range) throws IllegalDataAddressException, IllegalDataValueException { checkRange(offset, range.length); if (!Modbus.checkWriteRegisterCount(range.length)) throw new IllegalDataAddressException(offset); synchronized (this) { for (int i = 0; i < range.length; i++) { set(offset + i, range[i]); } } } public void setInt8At(int offset, int i8) throws IllegalDataAddressException, IllegalDataValueException { checkOffsetAndValue(offset, i8); set(offset, (int) DataUtils.byteLow(i8)); } public void setInt16At(int offset, int i16) throws IllegalDataAddressException, IllegalDataValueException { checkOffsetAndValue(offset, i16); set(offset, i16); } public void setInt32At(int offset, int i32) throws IllegalDataAddressException, IllegalDataValueException { setInt16At(offset, DataUtils.wordLow(i32)); setInt16At(offset + 1, DataUtils.wordHigh(i32)); } public void setInt64At(int offset, long i64) throws IllegalDataAddressException, IllegalDataValueException { setInt32At(offset, (int) (i64 & 0xffffffff)); setInt32At(offset + 2, (int) ((i64 >> 32) & 0xffffffff)); } public void setFloat32At(int offset, float f32) throws IllegalDataAddressException, IllegalDataValueException { setInt32At(offset, Float.floatToRawIntBits(f32)); } public void setFloat64At(int offset, double f64) throws IllegalDataAddressException, IllegalDataValueException { setInt64At(offset, Double.doubleToRawLongBits(f64)); } public int getInt8At(int offset) throws IllegalDataAddressException { checkAddress(offset); return DataUtils.byteLow(get(offset)); } public int getInt16At(int offset) throws IllegalDataAddressException { return get(offset); } public int getInt32At(int offset) throws IllegalDataAddressException { return (getInt16At(offset)&0xffff) | ((getInt16At(offset + 1)&0xffff) << 16); } public long getInt64At(int offset) throws IllegalDataAddressException { return (getInt32At(offset)&0xffffffffL) | ((getInt32At(offset + 2)&0xffffffffL) << 32); } public float getFloat32At(int offset) throws IllegalDataAddressException { return Float.intBitsToFloat(getInt32At(offset)); } public double getFloat64At(int offset) throws IllegalDataAddressException { return Double.longBitsToDouble(getInt64At(offset)); } public int[] getRegisters() { return Arrays.copyOf(registers, getQuantity()); } public void setRegisters(int[] registers) { this.registers = Arrays.copyOf(registers, registers.length); } @Override synchronized public int getByteCount() { return getQuantity() * 2; } @Override public byte[] getBytes() { return DataUtils.toByteArray(registers); } @Override public void setBytesBe(byte[] bytes) { registers = DataUtils.BeToIntArray(bytes); } public void setBytesLe(byte[] bytes) { this.registers = DataUtils.LeToIntArray(bytes); } @Override synchronized public int getQuantity() { return registers.length; } @Override public Integer get(int offset) throws IllegalDataAddressException { checkAddress(offset); synchronized (this) { return registers[offset]; } } public int[] getRange(int offset, int quantity) throws IllegalDataAddressException { checkRange(offset, quantity); if (!Modbus.checkReadRegisterCount(quantity)) throw new IllegalDataAddressException(offset); synchronized (this) { return Arrays.copyOfRange(registers, offset, offset + quantity); } } private void checkRange(int offset, int quantity) throws IllegalDataAddressException { if (offset + quantity > getQuantity()) throw new IllegalDataAddressException(offset); } private void checkAddress(int offset) throws IllegalDataAddressException { if (DataUtils.wordLow(offset) > (getQuantity() - 1)) throw new IllegalDataAddressException(offset); } private void checkValue(int value) throws IllegalDataValueException { if (!Modbus.checkRegisterValue(value)) throw new IllegalDataValueException(); } }