package com.intelligt.modbus.jlibmodbus.msg.base.mei;
|
|
import com.intelligt.modbus.jlibmodbus.Modbus;
|
import com.intelligt.modbus.jlibmodbus.data.DataHolder;
|
import com.intelligt.modbus.jlibmodbus.data.mei.ReadDeviceIdentificationInterface;
|
import com.intelligt.modbus.jlibmodbus.data.mei.ReadDeviceIdentificationInterface.DataObject;
|
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
|
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusInputStream;
|
import com.intelligt.modbus.jlibmodbus.net.stream.base.ModbusOutputStream;
|
import com.intelligt.modbus.jlibmodbus.utils.MEITypeCode;
|
|
import java.io.IOException;
|
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
|
*/
|
public class MEIReadDeviceIdentification implements ModbusEncapsulatedInterface {
|
|
public static final int SIZE_OF_HEADER = 8;
|
private int objectId = 0;
|
private ReadDeviceIdentificationCode readDeviceIdCode = ReadDeviceIdentificationCode.BASIC_STREAM_ACCESS;
|
private ConformityLevel conformityLevel = ConformityLevel.BASIC_STREAM_ONLY;
|
private boolean moreFollows = false;
|
private int nextObjectId = 0;
|
private int numberOfObjects = 0;
|
private DataObject[] objects = new DataObject[0];
|
private int responseSize = 0;
|
|
private int firstObjectIndex = 0;
|
|
@Override
|
public MEITypeCode getTypeCode() {
|
return MEITypeCode.READ_DEVICE_IDENTIFICATION;
|
}
|
|
@Override
|
public void writeRequest(ModbusOutputStream fifo) throws IOException {
|
fifo.write(getReadDeviceIdCode().toInt());
|
fifo.write(getObjectId());
|
}
|
|
@Override
|
public void readRequest(ModbusInputStream fifo) throws IOException {
|
setReadDeviceId(ReadDeviceIdentificationCode.get(fifo.read()));
|
setObjectId(fifo.read());
|
}
|
|
@Override
|
public int getRequestSize() {
|
return 2;
|
}
|
|
@Override
|
public void writeResponse(ModbusOutputStream fifo) throws IOException {
|
fifo.write(getReadDeviceIdCode().toInt());
|
fifo.write(getConformityLevel().toInt());
|
fifo.write(isMoreFollows() ? 0xFF : 0x00);
|
fifo.write(getNextObjectId());
|
fifo.write(getNumberOfObjects());
|
for (int i = getFirstObjectIndex(); i < getFirstObjectIndex() + getNumberOfObjects(); i++) {
|
DataObject o = objects[i];
|
fifo.write(o.getId());
|
fifo.write(o.getValue().length);
|
fifo.write(o.getValue());
|
}
|
}
|
|
@Override
|
public void readResponse(ModbusInputStream fifo) throws IOException, ModbusNumberException {
|
setReadDeviceId(ReadDeviceIdentificationCode.get(fifo.read()));
|
setConformityLevel(ConformityLevel.get(fifo.read()));
|
setMoreFollows(fifo.read() == 0xff);
|
setNextObjectId(fifo.read());
|
setNumberOfObjects(fifo.read());
|
if (getNumberOfObjects() > 0x7F) {
|
throw new ModbusNumberException("Illegal number of data objects", getNumberOfObjects());
|
}
|
setObjects(new DataObject[getNumberOfObjects()]);
|
int size = SIZE_OF_HEADER;
|
for (int i = 0; i < getNumberOfObjects(); i++) {
|
int id = fifo.read();
|
int length = fifo.read();
|
size += 2 + length;
|
if (size > Modbus.MAX_PDU_LENGTH)
|
throw new ModbusNumberException("Exceeded max pdu length", size);
|
byte[] value = new byte[length];
|
int read;
|
if ((read = fifo.read(value)) != length)
|
Modbus.log().warning(length + " bytes expected, but " + read + " received.");
|
objects[i] = new DataObject(id, value);
|
}
|
setResponseSize(size);
|
}
|
|
@Override
|
public int getResponseSize() {
|
return responseSize;
|
}
|
|
public void setResponseSize(int responseSize) {
|
this.responseSize = responseSize;
|
}
|
|
@Override
|
public void process(DataHolder dataHolder) {
|
ReadDeviceIdentificationInterface deviceId = dataHolder.getReadDeviceIdentificationInterface();
|
if (deviceId.getExtended().length != 0) {
|
setConformityLevel(ConformityLevel.EXTENDED_STREAM_AND_INDIVIDUAL);
|
} else if (deviceId.getRegular().length != 0) {
|
setConformityLevel(ConformityLevel.REGULAR_STREAM_AND_INDIVIDUAL);
|
} else {
|
setConformityLevel(ConformityLevel.BASIC_STREAM_AND_INDIVIDUAL);
|
}
|
switch (getReadDeviceIdCode()) {
|
case BASIC_STREAM_ACCESS:
|
setObjects(deviceId.getBasic());
|
break;
|
case REGULAR_STREAM_ACCESS:
|
setObjects(deviceId.getRegular());
|
break;
|
case EXTENDED_STREAM_ACCESS:
|
setObjects(deviceId.getExtended());
|
break;
|
case ONE_SPECIFIC_INDIVIDUAL_ACCESS:
|
default:
|
setObjects(new DataObject[]{deviceId.getValue(getObjectId())});
|
}
|
int size = SIZE_OF_HEADER;
|
int number_of_objects = 0;
|
|
if (getObjectId() != 0) {
|
for (int i = 0; i < objects.length && getFirstObjectIndex() == 0; i++) {
|
if (objects[i].getId() == getObjectId()) {
|
setFirstObjectIndex(i);
|
}
|
}
|
}
|
|
for (int i = getFirstObjectIndex(); i < objects.length; i++) {
|
size += objects[i].getValue().length + 2;//object id + object length = 2
|
if (size >= Modbus.MAX_PDU_LENGTH) {
|
break;
|
}
|
number_of_objects++;
|
}
|
setResponseSize(size);
|
if ((objects.length - getFirstObjectIndex()) > number_of_objects) {
|
setNextObjectId(number_of_objects + 1);
|
} else {
|
setMoreFollows(false);
|
}
|
setNumberOfObjects(number_of_objects);
|
}
|
|
public int getNumberOfObjects() {
|
return numberOfObjects;
|
}
|
|
public void setNumberOfObjects(int numberOfObjects) {
|
this.numberOfObjects = numberOfObjects;
|
}
|
|
public int getObjectId() {
|
return objectId;
|
}
|
|
public void setObjectId(int objectId) {
|
this.objectId = objectId;
|
}
|
|
public ReadDeviceIdentificationCode getReadDeviceIdCode() {
|
return readDeviceIdCode;
|
}
|
|
public void setReadDeviceId(ReadDeviceIdentificationCode readDeviceIdCode) {
|
this.readDeviceIdCode = readDeviceIdCode;
|
}
|
|
public ConformityLevel getConformityLevel() {
|
return conformityLevel;
|
}
|
|
public void setConformityLevel(ConformityLevel conformityLevel) {
|
this.conformityLevel = conformityLevel;
|
}
|
|
public boolean isMoreFollows() {
|
return moreFollows;
|
}
|
|
public void setMoreFollows(boolean moreFollows) {
|
this.moreFollows = moreFollows;
|
}
|
|
public int getNextObjectId() {
|
return nextObjectId;
|
}
|
|
public void setNextObjectId(int nextObjectId) {
|
this.nextObjectId = nextObjectId;
|
}
|
|
public DataObject[] getObjects() {
|
return Arrays.copyOf(objects, objects.length);
|
}
|
|
public void setObjects(DataObject[] objects) {
|
this.objects = Arrays.copyOf(objects, objects.length);
|
}
|
|
public int getFirstObjectIndex() {
|
return firstObjectIndex;
|
}
|
|
public void setFirstObjectIndex(int firstObjectIndex) {
|
this.firstObjectIndex = firstObjectIndex;
|
}
|
}
|