/**
* Copyright (c) 2010-2017 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.modbus.internal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.runners.Parameterized.Parameters;
import org.openhab.binding.modbus.ModbusBindingProvider;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
public class WriteRegistersTestParameters extends TestCaseSupport {
private static Command[] ZERO_COMMANDS = new Command[] { OnOffType.OFF, OpenClosedType.CLOSED };
private static Command[] ONE_COMMANDS = new Command[] { OnOffType.ON, OpenClosedType.OPEN };
@Parameters
public static List<Object[]> parameters() {
List<Object[]> parameters = new ArrayList<>();
generateWriteInt16SameValueAsBefore(parameters);
generateNumberItemInt16(parameters);
generateSwitchItemInt16(parameters);
// Currently not testing 32bit valuetypes due to bit buggy (subject to argue) implementation (32bit float is
// written as rounded 16bit integer, same goes for 32bit int)
// generateNumberItemFloat32(parameters);
// generateNumberItemInt32(parameters);
// // See
// https://community.openhab.org/t/writing-values-in-modbus-binding-not-considering-valuetype-and-binding-state/5247
//
//
// Also not tested:
// - Switch to slave with valuetype=bit (correct functionality tbd)
// (requires hardware) Serial RTU/ASCII/whatever
// (more exotic cases, perhaps not of interest)
// Switch item to *int32 (correct functionality tbd)
// Switch item to *int8 (correct functionality tbd)
// Switch item to float (0x3F800000 or 0x0 expected)
// INCREASE/DECREASE/UP/DOWN tests?
return parameters;
}
private static void generateSwitchItemInt16(List<Object[]> parameters) {
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xAAA, 0xAAA, 0xAAA, 0xAAA, 0xAAA }, new DecimalType(.0), new short[] { 0x0001 }, false, // if
// true
// expecting
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT16, ModbusBindingProvider.VALUE_TYPE_INT16, },
ONE_COMMANDS));
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xAAA, 0xAAA, 0xAAA, 0xAAA, 0xAAA }, new DecimalType(.0), new short[] { 0x0 }, false, // if
// true
// expecting
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT16, ModbusBindingProvider.VALUE_TYPE_INT16, },
ZERO_COMMANDS));
}
/*-
* Tests
* - writing 12345
* - writing -12345
* - writing 12345.5
* - writing -12345.5
*
* All tests are run with these combinations
* - holding register or input register
* - int16 or uint16
* - any other combination introduced by generateParameters
*
* @param parameters
*/
private static void generateNumberItemInt16(List<Object[]> parameters) {
/* int16 */
Command[] decimal_12345 = new Command[] { new DecimalType(12345) };
Command[] decimal_minus_12345 = new Command[] { new DecimalType(-12345) };
// -12345 int16 = 53191 uint16
Command[] decimal_53191 = new Command[] { new DecimalType(53191) };
short[] reg_int16_12345 = new short[] { 0x3039 }; // 0x3039;
short[] reg_uint16_12345 = reg_int16_12345;
short[] reg_int16_minus_12345 = new short[] { (short) 0xCFC7 }; // 0xCFC7;
short[] reg_uint16_minus_12345 = reg_int16_minus_12345; // 0xCFC7
Command[] decimal_12345_pt_5 = new Command[] { new DecimalType(12345.5) };
Command[] decimal_minus_12345_pt_5 = new Command[] { new DecimalType(-12345.5) };
// positive
for (Command command : Arrays.asList(decimal_12345[0], decimal_12345_pt_5[0])) {
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF }, new DecimalType(.0), reg_int16_12345, false, // if
// true
// expecting
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_INT16, }, new Command[] { command }));
}
// negative
for (Command command : Arrays.asList(decimal_minus_12345[0], decimal_minus_12345_pt_5[0])) {
parameters.addAll(
WriteRegistersTestParameters.generateParameters(new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
new DecimalType(.0), reg_int16_minus_12345, false, // if true expecting failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_INT16, }, new Command[] { command }));
}
// overflow
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF }, new DecimalType(.0), reg_int16_minus_12345, false, // if
// true
// expecting
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_INT16, }, decimal_53191));
/* uint16 */
// positive
for (Command command : Arrays.asList(decimal_12345[0], decimal_12345_pt_5[0])) {
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF }, new DecimalType(.0), reg_uint16_12345, false, // if
// true
// expecting
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT16, }, new Command[] { command }));
}
// negative
for (Command command : Arrays.asList(decimal_minus_12345[0], decimal_minus_12345_pt_5[0])) {
parameters.addAll(
WriteRegistersTestParameters.generateParameters(new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
new DecimalType(.0), reg_uint16_minus_12345, false, // if true expecting failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT16, }, new Command[] { command }));
}
// overflow
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF }, new DecimalType(.0), reg_uint16_minus_12345, false, // if
// true
// expecting
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT16, }, decimal_53191));
}
/*-
* - writing 12345678
* - writing -12345678
* - writing 12345678.5
* - writing -12345678.5
*
* All tests are run with these combinations
* - holding register or input register
* - int32 or uint32
* - any other combination introduced by generateParameters
*
* @param parameters
*/
private static void generateNumberItemInt32(List<Object[]> parameters) {
/* int32 */
Command[] decimal_12345678 = new Command[] { new DecimalType(12345678) };
Command[] decimal_minus_12345678 = new Command[] { new DecimalType(-12345678) };
// -12345678 int32 = 4282621618 uint32
Command[] decimal_4282621618 = new Command[] { new DecimalType(4282621618L) };
short[] reg_int32_12345678 = new short[] { 0x00BC, 0x614E }; // 0x00BC614E;
short[] reg_uint32_12345678 = reg_int32_12345678;
short[] reg_int32_minus_12345678 = new short[] { 0x00BC, 0x614E }; // 0xFF439EB2;
short[] reg_uint32_minus_12345678 = reg_int32_minus_12345678; // 0xFF439EB2
Command[] decimal_12345678_pt_5 = new Command[] { new DecimalType(12345678.5) };
Command[] decimal_minus_12345678_pt_5 = new Command[] { new DecimalType(-12345678.5) };
for (Command command : Arrays.asList(decimal_12345678[0], decimal_12345678_pt_5[0])) {
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF }, new DecimalType(.0), reg_int32_12345678, false, // true
// ->
// exptected
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_INT32, }, new Command[] { command }));
}
for (Command command : Arrays.asList(decimal_minus_12345678[0], decimal_minus_12345678_pt_5[0])) {
parameters.addAll(
WriteRegistersTestParameters.generateParameters(new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
new DecimalType(.0), reg_int32_minus_12345678, false, // true -> exptected failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_INT32, }, new Command[] { command }));
}
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF }, new DecimalType(.0), reg_int32_minus_12345678, false, // true
// ->
// exptected
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_INT32, }, decimal_4282621618));
/* uint32 */
for (Command command : Arrays.asList(decimal_12345678[0], decimal_12345678_pt_5[0])) {
parameters.addAll(WriteRegistersTestParameters.generateParameters(
new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF }, new DecimalType(.0), reg_uint32_12345678, false, // true
// ->
// exptected
// failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT32, }, new Command[] { command }));
}
for (Command command : Arrays.asList(decimal_minus_12345678[0], decimal_minus_12345678_pt_5[0])) {
parameters.addAll(
WriteRegistersTestParameters.generateParameters(new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
new DecimalType(.0), reg_uint32_minus_12345678, false, // true -> exptected failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT32, }, new Command[] { command }));
}
parameters.addAll(
WriteRegistersTestParameters.generateParameters(new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
new DecimalType(.0), reg_uint32_minus_12345678, false, // true -> exptected failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_UINT32, }, decimal_4282621618));
}
/*-
* - writing 12345678.5
* - writing -12345678.5
*
* All tests are run with these combinations
* - holding register or input
* - any other combination introduced by generateParameters
*
* @param parameters
*/
private static void generateNumberItemFloat32(List<Object[]> parameters) {
/* float32 */
Command[] decimal_12345678_pt_5 = new Command[] { new DecimalType(12345678.5) };
Command[] decimal_minus_12345678_pt_5 = new Command[] { new DecimalType(-12345678.5) };
short[] reg_float32_12345678_pt_5 = new short[] { 0x4B3C, 0x614E }; // 0x4B3C614E;
short[] reg_float32_minus_12345678_pt_5 = new short[] { (short) 0xCB3C, 0x614F }; // 0xCB3C614F;
parameters.addAll(
WriteRegistersTestParameters.generateParameters(new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
new DecimalType(.0), reg_float32_12345678_pt_5, false, // true -> exptected failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_FLOAT32, }, decimal_12345678_pt_5));
parameters.addAll(
WriteRegistersTestParameters.generateParameters(new short[] { 0xFFF, 0xFFF, 0xFFF, 0xFFF, 0xFFF },
new DecimalType(.0), reg_float32_minus_12345678_pt_5, false, // true -> exptected failure
new String[] { ModbusBindingProvider.TYPE_INPUT, ModbusBindingProvider.TYPE_HOLDING },
new String[] { ModbusBindingProvider.VALUE_TYPE_FLOAT32, }, decimal_minus_12345678_pt_5));
}
private static void generateWriteInt16SameValueAsBefore(List<Object[]> parameters) {
// Verify that we will write the data even though value remains the
// same!
// (only tested for 16bit values for simplicity)
parameters.addAll(WriteRegistersTestParameters.generateParameters(new short[] { 5, 5, 5, 5, 5 },
new DecimalType(5.0), new short[] { 5 }, false, // true -> expected failure
new String[] { ModbusBindingProvider.TYPE_HOLDING, ModbusBindingProvider.TYPE_INPUT },
new String[] {
// ModbusBindingProvider.VALUE_TYPE_FLOAT32,
// ModbusBindingProvider.VALUE_TYPE_INT32,
// ModbusBindingProvider.VALUE_TYPE_UINT32,
ModbusBindingProvider.VALUE_TYPE_INT16, ModbusBindingProvider.VALUE_TYPE_UINT16,
// ModbusBindingProvider.VALUE_TYPE_INT8,
// ModbusBindingProvider.VALUE_TYPE_UINT8,
// ModbusBindingProvider.VALUE_TYPE_BIT,
}, new Command[] { new DecimalType(5.0) }));
}
/**
* Create cross product of test parameters
*
* @param initialRegisters
* Registers are initialized to these values (starting from
* smallest index to largest)
* @param itemInitialState
* Items are initialized this value
* @param expectedValue
* Expected register values that are written. Register positions
* are automatically determined
* @param expectingAssertionError
* whether assertion error is expected (i.e. known failure)
* @param types
* for generating multiple tests: all types (e.g. "holding") that
* are tested
* @param valueTypes
* for generating multiple tests: all valuetypes (e.g. "int16")
* that are tested
* @param commands
* for generating multiple tests: all commands that are tested
* @return
*/
public static List<Object[]> generateParameters(short[] initialRegisters, State itemInitialState,
short[] expectedValue, boolean expectingAssertionError, String[] types, String[] valueTypes,
Command... commands) {
List<Object[]> parameters = new ArrayList<>();
for (ServerType serverType : TestCaseSupport.TEST_SERVERS) {
for (boolean nonZeroOffset : new Boolean[] { true, false }) {
for (Command command : commands) {
for (int itemIndex : new Integer[] { 0, 1 }) {
for (String type : types) {
for (String valueType : valueTypes) {
parameters.add(new Object[] { serverType, initialRegisters, itemInitialState,
nonZeroOffset, type, valueType, itemIndex, command, expectedValue,
expectingAssertionError });
}
}
}
}
}
}
return parameters;
}
}