Search in sources :

Example 16 with ModbusReadRequestBlueprint

use of org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint in project openhab-addons by openhab.

the class ModbusDataThingHandler method validateWriteIndex.

private void validateWriteIndex() throws ModbusConfigurationException {
    @Nullable ModbusReadRequestBlueprint readRequest = this.readRequest;
    if (!writeStart.isPresent() || !writeSubIndex.isPresent()) {
        // 
        return;
    } else if (readRequest == null) {
        // should not happen, already validated
        throw new ModbusConfigurationException("Must poll data with writeStart=X.Y");
    }
    if (writeSubIndex.isPresent() && (writeSubIndex.get() + 1) > 16) {
        // the sub index Y (in X.Y) is above the register limits
        String errmsg = String.format("readStart=X.Y, the value Y is too large");
        throw new ModbusConfigurationException(errmsg);
    }
    // Determine bit positions polled, both start and end inclusive
    int pollStartBitIndex = readRequest.getReference() * 16;
    int pollEndBitIndex = pollStartBitIndex + readRequest.getDataLength() * 16 - 1;
    // Determine bit positions read, both start and end inclusive
    int writeStartBitIndex = writeStart.get() * 16 + readSubIndex.orElse(0);
    int writeEndBitIndex = writeStartBitIndex - 1;
    if (writeStartBitIndex < pollStartBitIndex || writeEndBitIndex > pollEndBitIndex) {
        String errmsg = String.format("Out-of-bounds: Poller is reading from index %d to %d (inclusive) but this thing configured to write  starting from element %d. Must write within polled limits", pollStartBitIndex / 16, pollEndBitIndex / 16, writeStart.get());
        throw new ModbusConfigurationException(errmsg);
    }
}
Also used : ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) ModbusConfigurationException(org.openhab.binding.modbus.internal.ModbusConfigurationException) Nullable(org.eclipse.jdt.annotation.Nullable) ModbusWriteCoilRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint) ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) ModbusWriteRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusWriteRequestBlueprint) ModbusWriteRegisterRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint)

Example 17 with ModbusReadRequestBlueprint

use of org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint in project openhab-addons by openhab.

the class ModbusDataThingHandler method initialize.

@Override
public synchronized void initialize() {
    // Long running initialization should be done asynchronously in background.
    try {
        logger.trace("initialize() of thing {} '{}' starting", thing.getUID(), thing.getLabel());
        ModbusDataConfiguration localConfig = config = getConfigAs(ModbusDataConfiguration.class);
        updateUnchangedValuesEveryMillis = localConfig.getUpdateUnchangedValuesEveryMillis();
        Bridge bridge = getBridge();
        if (bridge == null || !bridge.getStatus().equals(ThingStatus.ONLINE)) {
            logger.debug("Thing {} '{}' has no bridge or it is not online", getThing().getUID(), getThing().getLabel());
            updateStatusIfChanged(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "No online bridge");
            return;
        }
        BridgeHandler bridgeHandler = bridge.getHandler();
        if (bridgeHandler == null) {
            logger.warn("Bridge {} '{}' has no handler.", bridge.getUID(), bridge.getLabel());
            String errmsg = String.format("Bridge %s '%s' configuration incomplete or with errors", bridge.getUID(), bridge.getLabel());
            throw new ModbusConfigurationException(errmsg);
        }
        if (bridgeHandler instanceof ModbusEndpointThingHandler) {
            // Write-only thing, parent is endpoint
            ModbusEndpointThingHandler endpointHandler = (ModbusEndpointThingHandler) bridgeHandler;
            slaveId = endpointHandler.getSlaveId();
            comms = endpointHandler.getCommunicationInterface();
            childOfEndpoint = true;
            functionCode = null;
            readRequest = null;
        } else {
            ModbusPollerThingHandler localPollerHandler = (ModbusPollerThingHandler) bridgeHandler;
            pollerHandler = localPollerHandler;
            ModbusReadRequestBlueprint localReadRequest = localPollerHandler.getRequest();
            if (localReadRequest == null) {
                logger.debug("Poller {} '{}' has no read request -- configuration is changing or bridge having invalid configuration?", bridge.getUID(), bridge.getLabel());
                updateStatusIfChanged(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, String.format("Poller %s '%s' has no poll task", bridge.getUID(), bridge.getLabel()));
                return;
            }
            readRequest = localReadRequest;
            slaveId = localReadRequest.getUnitID();
            functionCode = localReadRequest.getFunctionCode();
            comms = localPollerHandler.getCommunicationInterface();
            pollStart = localReadRequest.getReference();
            childOfEndpoint = false;
        }
        validateAndParseReadParameters(localConfig);
        validateAndParseWriteParameters(localConfig);
        validateMustReadOrWrite();
        updateStatusIfChanged(ThingStatus.ONLINE);
    } catch (ModbusConfigurationException | EndpointNotInitializedException e) {
        logger.debug("Thing {} '{}' initialization error: {}", getThing().getUID(), getThing().getLabel(), e.getMessage());
        updateStatusIfChanged(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getMessage());
    } finally {
        logger.trace("initialize() of thing {} '{}' finished", thing.getUID(), thing.getLabel());
    }
}
Also used : ModbusDataConfiguration(org.openhab.binding.modbus.internal.config.ModbusDataConfiguration) ModbusEndpointThingHandler(org.openhab.binding.modbus.handler.ModbusEndpointThingHandler) BridgeHandler(org.openhab.core.thing.binding.BridgeHandler) ModbusConfigurationException(org.openhab.binding.modbus.internal.ModbusConfigurationException) ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) ModbusPollerThingHandler(org.openhab.binding.modbus.handler.ModbusPollerThingHandler) EndpointNotInitializedException(org.openhab.binding.modbus.handler.EndpointNotInitializedException) Bridge(org.openhab.core.thing.Bridge)

Example 18 with ModbusReadRequestBlueprint

use of org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint in project openhab-addons by openhab.

the class ModbusPollerThingHandler method registerPollTask.

/**
 * Register poll task
 *
 * @throws EndpointNotInitializedException in case the bridge initialization is not complete. This should only
 *             happen in transient conditions, for example, when bridge is initializing.
 */
@SuppressWarnings("null")
private synchronized void registerPollTask() throws EndpointNotInitializedException {
    logger.trace("registerPollTask()");
    if (pollTask != null) {
        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
        logger.debug("pollTask should be unregistered before registering a new one!");
        return;
    }
    ModbusEndpointThingHandler slaveEndpointThingHandler = getEndpointThingHandler();
    if (slaveEndpointThingHandler == null) {
        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, String.format("Bridge '%s' is offline", Optional.ofNullable(getBridge()).map(b -> b.getLabel()).orElse("<null>")));
        logger.debug("No bridge handler available -- aborting init for {}", this);
        return;
    }
    ModbusCommunicationInterface localComms = slaveEndpointThingHandler.getCommunicationInterface();
    if (localComms == null) {
        updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, String.format("Bridge '%s' not completely initialized", Optional.ofNullable(getBridge()).map(b -> b.getLabel())));
        logger.debug("Bridge not initialized fully (no communication interface) -- aborting init for {}", this);
        return;
    }
    this.comms = localComms;
    ModbusReadFunctionCode localFunctionCode = functionCode;
    if (localFunctionCode == null) {
        return;
    }
    ModbusReadRequestBlueprint localRequest = new ModbusReadRequestBlueprint(slaveEndpointThingHandler.getSlaveId(), localFunctionCode, config.getStart(), config.getLength(), config.getMaxTries());
    this.request = localRequest;
    if (config.getRefresh() <= 0L) {
        logger.debug("Not registering polling with ModbusManager since refresh disabled");
        updateStatus(ThingStatus.ONLINE, ThingStatusDetail.NONE, "Not polling");
    } else {
        logger.debug("Registering polling with ModbusManager");
        pollTask = localComms.registerRegularPoll(localRequest, config.getRefresh(), 0, callbackDelegator, callbackDelegator);
        assert pollTask != null;
        updateStatus(ThingStatus.ONLINE);
    }
}
Also used : ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) AsyncModbusFailure(org.openhab.core.io.transport.modbus.AsyncModbusFailure) ModbusRegisterArray(org.openhab.core.io.transport.modbus.ModbusRegisterArray) ModbusBindingConstantsInternal(org.openhab.binding.modbus.internal.ModbusBindingConstantsInternal) LoggerFactory(org.slf4j.LoggerFactory) AtomicReference(java.util.concurrent.atomic.AtomicReference) ModbusConstants(org.openhab.core.io.transport.modbus.ModbusConstants) Thing(org.openhab.core.thing.Thing) ModbusPollerConfiguration(org.openhab.binding.modbus.internal.config.ModbusPollerConfiguration) Nullable(org.eclipse.jdt.annotation.Nullable) ModbusCommunicationInterface(org.openhab.core.io.transport.modbus.ModbusCommunicationInterface) ModbusFailureCallback(org.openhab.core.io.transport.modbus.ModbusFailureCallback) ChannelUID(org.openhab.core.thing.ChannelUID) ThingStatusInfo(org.openhab.core.thing.ThingStatusInfo) AtomicStampedValue(org.openhab.binding.modbus.internal.AtomicStampedValue) NonNullByDefault(org.eclipse.jdt.annotation.NonNullByDefault) ModbusReadCallback(org.openhab.core.io.transport.modbus.ModbusReadCallback) ThingStatus(org.openhab.core.thing.ThingStatus) Command(org.openhab.core.types.Command) Logger(org.slf4j.Logger) ModbusDataThingHandler(org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler) ThingHandler(org.openhab.core.thing.binding.ThingHandler) PollTask(org.openhab.core.io.transport.modbus.PollTask) ModbusReadFunctionCode(org.openhab.core.io.transport.modbus.ModbusReadFunctionCode) ThingStatusDetail(org.openhab.core.thing.ThingStatusDetail) Collectors(java.util.stream.Collectors) List(java.util.List) AsyncModbusReadResult(org.openhab.core.io.transport.modbus.AsyncModbusReadResult) Optional(java.util.Optional) BaseBridgeHandler(org.openhab.core.thing.binding.BaseBridgeHandler) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Bridge(org.openhab.core.thing.Bridge) ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) ModbusCommunicationInterface(org.openhab.core.io.transport.modbus.ModbusCommunicationInterface) ModbusReadFunctionCode(org.openhab.core.io.transport.modbus.ModbusReadFunctionCode)

Example 19 with ModbusReadRequestBlueprint

use of org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint in project openhab-core by openhab.

the class SmokeTest method testRegularReadEvery150msWithCoil.

/**
 * Testing regular polling of coils
 *
 * Amount of requests is timed, and average poll period is checked
 *
 * @throws Exception
 */
@Test
public void testRegularReadEvery150msWithCoil() throws Exception {
    generateData();
    ModbusSlaveEndpoint endpoint = getEndpoint();
    AtomicInteger unexpectedCount = new AtomicInteger();
    CountDownLatch callbackCalled = new CountDownLatch(5);
    AtomicInteger dataReceived = new AtomicInteger();
    long start = System.currentTimeMillis();
    try (ModbusCommunicationInterface comms = modbusManager.newModbusCommunicationInterface(endpoint, null)) {
        comms.registerRegularPoll(new ModbusReadRequestBlueprint(SLAVE_UNIT_ID, ModbusReadFunctionCode.READ_COILS, 1, 15, 1), 150, 0, result -> {
            Optional<BitArray> bitsOptional = result.getBits();
            if (bitsOptional.isPresent()) {
                BitArray bits = bitsOptional.get();
                dataReceived.incrementAndGet();
                try {
                    assertThat(bits.size(), is(equalTo(15)));
                    testCoilValues(bits, 1);
                } catch (AssertionError e) {
                    unexpectedCount.incrementAndGet();
                }
            } else {
                unexpectedCount.incrementAndGet();
            }
            callbackCalled.countDown();
        }, failure -> {
            unexpectedCount.incrementAndGet();
            callbackCalled.countDown();
        });
        assertTrue(callbackCalled.await(60, TimeUnit.SECONDS));
        long end = System.currentTimeMillis();
        assertPollDetails(unexpectedCount, dataReceived, start, end, 145, 500);
    }
}
Also used : ModbusSlaveEndpoint(org.openhab.core.io.transport.modbus.endpoint.ModbusSlaveEndpoint) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) ModbusCommunicationInterface(org.openhab.core.io.transport.modbus.ModbusCommunicationInterface) BitArray(org.openhab.core.io.transport.modbus.BitArray) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.jupiter.api.Test)

Example 20 with ModbusReadRequestBlueprint

use of org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint in project openhab-core by openhab.

the class SmokeTest method testConnectionCloseAfterLastCommunicationInterfaceClosed.

@Test
public void testConnectionCloseAfterLastCommunicationInterfaceClosed() throws Exception {
    assumeFalse(isRunningInCI(), "Running in CI! Will not test timing-sensitive details");
    ModbusSlaveEndpoint endpoint = getEndpoint();
    assumeTrue(endpoint instanceof ModbusTCPSlaveEndpoint, "Connection closing test supported only with TCP slaves");
    // Generate server data
    generateData();
    EndpointPoolConfiguration config = new EndpointPoolConfiguration();
    config.setReconnectAfterMillis(9_000_000);
    // 1. capture open connections at this point
    long openSocketsBefore = getNumberOfOpenClients(SOCKET_SPY);
    assertThat(openSocketsBefore, is(equalTo(0L)));
    // 2. make poll, binding opens the tcp connection
    try (ModbusCommunicationInterface comms = modbusManager.newModbusCommunicationInterface(endpoint, config)) {
        {
            CountDownLatch latch = new CountDownLatch(1);
            comms.submitOneTimePoll(new ModbusReadRequestBlueprint(1, ModbusReadFunctionCode.READ_COILS, 0, 1, 1), response -> {
                latch.countDown();
            }, failure -> {
                latch.countDown();
            });
            assertTrue(latch.await(60, TimeUnit.SECONDS));
        }
        waitForAssert(() -> {
            // 3. ensure one open connection
            long openSocketsAfter = getNumberOfOpenClients(SOCKET_SPY);
            assertThat(openSocketsAfter, is(equalTo(1L)));
        });
        try (ModbusCommunicationInterface comms2 = modbusManager.newModbusCommunicationInterface(endpoint, config)) {
            {
                CountDownLatch latch = new CountDownLatch(1);
                comms.submitOneTimePoll(new ModbusReadRequestBlueprint(1, ModbusReadFunctionCode.READ_COILS, 0, 1, 1), response -> {
                    latch.countDown();
                }, failure -> {
                    latch.countDown();
                });
                assertTrue(latch.await(60, TimeUnit.SECONDS));
            }
            assertThat(getNumberOfOpenClients(SOCKET_SPY), is(equalTo(1L)));
            // wait for moment (to check that no connections are closed)
            Thread.sleep(1000);
            // no more than 1 connection, even though requests are going through
            assertThat(getNumberOfOpenClients(SOCKET_SPY), is(equalTo(1L)));
        }
        Thread.sleep(1000);
        // Still one connection open even after closing second connection
        assertThat(getNumberOfOpenClients(SOCKET_SPY), is(equalTo(1L)));
    }
    // 4. close (the last) comms
    // ensure that open connections are closed
    // (despite huge "reconnect after millis")
    waitForAssert(() -> {
        long openSocketsAfterClose = getNumberOfOpenClients(SOCKET_SPY);
        assertThat(openSocketsAfterClose, is(equalTo(0L)));
    });
}
Also used : SocketImpl(java.net.SocketImpl) CoreMatchers(org.hamcrest.CoreMatchers) BeforeEach(org.junit.jupiter.api.BeforeEach) ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) Socket(java.net.Socket) ModbusRegisterArray(org.openhab.core.io.transport.modbus.ModbusRegisterArray) SocketOption(java.net.SocketOption) LoggerFactory(org.slf4j.LoggerFactory) ModbusResponse(org.openhab.core.io.transport.modbus.ModbusResponse) Constructor(java.lang.reflect.Constructor) AtomicReference(java.util.concurrent.atomic.AtomicReference) InetAddress(java.net.InetAddress) BitArray(org.openhab.core.io.transport.modbus.BitArray) BitVector(net.wimpi.modbus.util.BitVector) ModbusTCPSlaveEndpoint(org.openhab.core.io.transport.modbus.endpoint.ModbusTCPSlaveEndpoint) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ModbusWriteCoilRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint) ModbusCommunicationInterface(org.openhab.core.io.transport.modbus.ModbusCommunicationInterface) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Method(java.lang.reflect.Method) ModbusConnectionException(org.openhab.core.io.transport.modbus.exception.ModbusConnectionException) StandardSocketOptions(java.net.StandardSocketOptions) EndpointPoolConfiguration(org.openhab.core.io.transport.modbus.endpoint.EndpointPoolConfiguration) NonNullByDefault(org.eclipse.jdt.annotation.NonNullByDefault) SimpleRegister(net.wimpi.modbus.procimg.SimpleRegister) PollTask(org.openhab.core.io.transport.modbus.PollTask) IOException(java.io.IOException) ModbusReadFunctionCode(org.openhab.core.io.transport.modbus.ModbusReadFunctionCode) SocketImplFactory(java.net.SocketImplFactory) ModbusSlaveErrorResponseException(org.openhab.core.io.transport.modbus.exception.ModbusSlaveErrorResponseException) InvocationTargetException(java.lang.reflect.InvocationTargetException) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) Test(org.junit.jupiter.api.Test) CountDownLatch(java.util.concurrent.CountDownLatch) ModbusSlaveIOException(org.openhab.core.io.transport.modbus.exception.ModbusSlaveIOException) WriteCoilRequest(net.wimpi.modbus.msg.WriteCoilRequest) SimpleDigitalOut(net.wimpi.modbus.procimg.SimpleDigitalOut) Assumptions(org.junit.jupiter.api.Assumptions) WriteMultipleCoilsRequest(net.wimpi.modbus.msg.WriteMultipleCoilsRequest) Assertions(org.junit.jupiter.api.Assertions) ModbusRequest(net.wimpi.modbus.msg.ModbusRequest) Optional(java.util.Optional) ModbusSlaveEndpoint(org.openhab.core.io.transport.modbus.endpoint.ModbusSlaveEndpoint) SimpleDigitalIn(net.wimpi.modbus.procimg.SimpleDigitalIn) BitSet(java.util.BitSet) Queue(java.util.Queue) ConcurrentLinkedQueue(java.util.concurrent.ConcurrentLinkedQueue) ModbusSlaveEndpoint(org.openhab.core.io.transport.modbus.endpoint.ModbusSlaveEndpoint) EndpointPoolConfiguration(org.openhab.core.io.transport.modbus.endpoint.EndpointPoolConfiguration) ModbusReadRequestBlueprint(org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint) ModbusTCPSlaveEndpoint(org.openhab.core.io.transport.modbus.endpoint.ModbusTCPSlaveEndpoint) ModbusCommunicationInterface(org.openhab.core.io.transport.modbus.ModbusCommunicationInterface) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.junit.jupiter.api.Test)

Aggregations

ModbusReadRequestBlueprint (org.openhab.core.io.transport.modbus.ModbusReadRequestBlueprint)47 ModbusSlaveEndpoint (org.openhab.core.io.transport.modbus.endpoint.ModbusSlaveEndpoint)22 Test (org.junit.jupiter.api.Test)21 ModbusRegisterArray (org.openhab.core.io.transport.modbus.ModbusRegisterArray)21 ModbusCommunicationInterface (org.openhab.core.io.transport.modbus.ModbusCommunicationInterface)19 PollTask (org.openhab.core.io.transport.modbus.PollTask)17 ModbusDataThingHandler (org.openhab.binding.modbus.internal.handler.ModbusDataThingHandler)14 Configuration (org.openhab.core.config.core.Configuration)14 CountDownLatch (java.util.concurrent.CountDownLatch)13 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)13 AsyncModbusReadResult (org.openhab.core.io.transport.modbus.AsyncModbusReadResult)12 ModbusTCPSlaveEndpoint (org.openhab.core.io.transport.modbus.endpoint.ModbusTCPSlaveEndpoint)11 AtomicReference (java.util.concurrent.atomic.AtomicReference)10 ModbusWriteCoilRequestBlueprint (org.openhab.core.io.transport.modbus.ModbusWriteCoilRequestBlueprint)10 Bridge (org.openhab.core.thing.Bridge)9 Thing (org.openhab.core.thing.Thing)9 ModbusPollerThingHandler (org.openhab.binding.modbus.handler.ModbusPollerThingHandler)8 ModbusReadCallback (org.openhab.core.io.transport.modbus.ModbusReadCallback)8 ModbusWriteRegisterRequestBlueprint (org.openhab.core.io.transport.modbus.ModbusWriteRegisterRequestBlueprint)8 ModbusWriteRequestBlueprint (org.openhab.core.io.transport.modbus.ModbusWriteRequestBlueprint)7