Add to current counter value

Hello, After some experimenal Home Assistant time I am finaly back to openhab.
Now I am trying to make a binding for my old Siemens PTM modules. One of these modules is a counter with a seven bits value, witch I want to add to an existing value.
I created a Number item and I am able to send the new value to this Item.
The question is can I read the current value of this item, add the new value and send the updated value.
Any help is welcome.

Jos

Are you writing the binding in Java? If so you could simply keep a cumulative value within the binding, and perhaps have two channels, one for the cumulative value and one for the latest count.

Alternatively, you can keep this cumulative value on openhab, and perhaps also take advantage of persistence so the value won’t get lost after a restart. In this case, you could write a simple rule that triggers when the counter from the binding is updated (it can be updated to the same value, so change trigger may not work here), and you can add it up to the cumulative value.

@JimT
Thanks for your answer. The goal is to use the persistance of opehab to keep the value. Preferable without making any new rule. But if it is not possible to read the current value, this could be an option.

Provided that you add up the cumulative total in your binding, you could use openhab’s persistence.

Now I’m not sure about the following (never looked into it)

  • When the item is restored by openhab’s persistence, I believe it will UPDATE the item’s state.
  • I think the binding gets notified when the item state is updated (not commanded)
  • Using this in your thinghandlercallback, you can initialise the internal cumulative counter, so the next update will add on to the restored state coming from the persistence.
1 Like

Looking further into this, I don’t think this is supported. The (binding) handler doesn’t get notified when the item’s state is updated within openhab (e.g. by a rule).

Your other option is to just send and persist the discrete values, and when you want the cumulative value, use something like PersistenceExtensions sumSince but that’s probably worse, albeit more flexible, than having a separate item on openhab to hold the cumulative amount and using a rule to increase it when receiving the discrete value from your binding.

Thanks again JimT, I will give it a try

After some more digging I found the folowing “solution” for now

oldValStr = sendHttpGetRequest("http://localhost:8080/rest/items/pbus2c_Address_03_Port1/state");
oldValDbl = oldValStr.equals("NULL") || oldValStr.isEmpty() ? 0 : Double.parseDouble(oldValStr);

You can simply get the item’s state using openhab’s API, and not through REST.
get into itemRegistry, get the item and get its state.

I tried but failed. Any example of how i shoud do that?

If your class is a component, add a @Reference to ItemRegistry in its constructor. Look up the code in openhab-core for examples.

There’s tons of its use. Example: https://github.com/openhab/openhab-core/blob/d3d0fe3995b2b950e253d782efbda33b31eebeec/bundles/org.openhab.core/src/main/java/org/openhab/core/internal/items/ItemUpdater.java#L49

Then

itemRegistry.getItem("pbus2c_Address_03_Port1").getState()

Thanks again.
Excuse me if I have it wrong, but a.f.a.i.k. I have normal classes.
How to use the api in that case?

Within a binding, there’s usually a component, somewhere. Get a reference from that, and pass it along to your class.

I am a bit confused about your last reply.

Managed to change the only component I found in my binding

@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.pbus")
public class PbusHandlerFactory extends BaseThingHandlerFactory {

    private final SerialPortManager serialPortManager;
    public ItemRegistry itemRegistry;

    @Activate
    public PbusHandlerFactory(final @Reference SerialPortManager serialPortManager, final @Reference ItemRegistry itemRegistry) {
        this.serialPortManager = serialPortManager;
        this.itemRegistry = itemRegistry;
    }

And in my sensor handler

                try {
                    State state = PbusHandlerFactory.itemRegistry.getItem("pbus2c_Address_03_Port1").getState();
                } catch (ItemNotFoundException e) {
                    throw new RuntimeException(e);
                }

But now I got the error

Non-static field 'itemRegistry' cannot be referenced from a static context

Please help me out.

That error message explained it.

Show me the whole thing so I can make a suggestion.

Here is the full code of the sensorhandler

/**
 * Copyright (c) 2010-2024 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.openhab.binding.pbus.internal.handler;

import static org.openhab.binding.pbus.internal.PbusBindingConstants.*;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.pbus.internal.packets.PbusPacket;
import org.openhab.core.items.*;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.thing.*;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;

/**
 * The {@link PbusSensorHandler} is responsible for handling commands, which are
 * sent to one of the channels.
 *
 * @author Jos Wanders - Initial contribution
 */

@NonNullByDefault
public class PbusSensorHandler extends PbusThingHandler {
    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
            Arrays.asList(THING_2D20, THING_4D20, THING_2D42, THING_2D20S, THING_2D250, THING_4D20R));

    private static ItemRegistry itemRegistry;

    public String thingType = thing.getUID().toString().split(":")[1];

    public boolean fourPorts = (thingType.indexOf("4") == 0);

    public PbusSensorHandler(Thing thing) {
        super(thing);
    }

    @Override
    public void handleCommand(ChannelUID channelUID, Command command) {
        PbusBridgeHandler pbusBridgeHandler = getPbusBridgeHandler();
        if (pbusBridgeHandler == null) {
            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
            return;
        }
    }

    @Override
    public void onPacketReceived(byte[] packet) {
        logger.trace("onPacketReceived(sensor) was called");

        if (packet[0] == PbusPacket.STX && packet.length >= 5) {
            byte command = packet[3];

            final ChannelUID p1ChannelUID = new ChannelUID(thing.getUID(), "port1");

            if (command == COMMAND_PORT_STATUS && packet.length >= 6) {

                try {
                    State state = itemRegistry.getItem("pbus2c_Address_03_Port1").getState();
                } catch (ItemNotFoundException e) {
                    throw new RuntimeException(e);
                }

                byte channelPressed = packet[4];
                if (channelPressed != 0) {

                    updateState(p1ChannelUID, OpenClosedType.CLOSED);
                    logger.debug("Update Channel : {} to {}", p1ChannelUID, OpenClosedType.CLOSED);
                }

                byte channelReleased = packet[5];
                if (channelReleased != 0) {
                    updateState(p1ChannelUID, OpenClosedType.OPEN);
                    logger.debug("Update Channel : {} to {}", p1ChannelUID, OpenClosedType.OPEN);
                }
            }
        }
    }
}

And the code of the component

/**
 * Copyright (c) 2010-2024 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.openhab.binding.pbus.internal;

import static org.openhab.binding.pbus.internal.PbusBindingConstants.*;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.pbus.internal.handler.Pbus2cHandler;
import org.openhab.binding.pbus.internal.handler.PbusBridgeHandler;
import org.openhab.binding.pbus.internal.handler.PbusNetworkBridgeHandler;
import org.openhab.binding.pbus.internal.handler.PbusSensorHandler;
import org.openhab.binding.pbus.internal.handler.PbusSerialBridgeHandler;
import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
 * The {@link PbusHandlerFactory} is responsible for creating things and thing
 * handlers.
 *
 * @author Jos Wanders - Initial contribution
 */
@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.pbus")
public class PbusHandlerFactory extends BaseThingHandlerFactory {

    private final SerialPortManager serialPortManager;
    public ItemRegistry itemReg;

    @Activate
    public PbusHandlerFactory(final @Reference SerialPortManager serialPortManager,
            final @Reference ItemRegistry itemRegistry) {
        this.serialPortManager = serialPortManager;
        this.itemReg = itemRegistry;
    }

    @Override
    public boolean supportsThingType(ThingTypeUID thingTypeUID) {
        return SUPPORTED_BRIDGE_UIDS.contains(thingTypeUID) || SUPPORTED_THING_UIDS.contains(thingTypeUID);
    }

    @Override
    protected @Nullable ThingHandler createHandler(Thing thing) {
        ThingTypeUID thingTypeUID = thing.getThingTypeUID();
        ThingHandler thingHandler = null;

        if (SUPPORTED_BRIDGE_UIDS.contains(thingTypeUID)) {
            PbusBridgeHandler pbusBridgeHandler;
            if (thingTypeUID.equals(BRIDGE_NETWORK)) {
                pbusBridgeHandler = new PbusNetworkBridgeHandler((Bridge) thing);
            } else {
                pbusBridgeHandler = new PbusSerialBridgeHandler((Bridge) thing, serialPortManager);
            }
            thingHandler = pbusBridgeHandler;

        } else if (Pbus2cHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
            thingHandler = new Pbus2cHandler(thing);
        } else if (PbusSensorHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
            thingHandler = new PbusSensorHandler(thing);
        }

        return thingHandler;
    }
}

/**
 * Copyright (c) 2010-2024 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.openhab.binding.pbus.internal;

import static org.openhab.binding.pbus.internal.PbusBindingConstants.*;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.pbus.internal.handler.Pbus2cHandler;
import org.openhab.binding.pbus.internal.handler.PbusBridgeHandler;
import org.openhab.binding.pbus.internal.handler.PbusNetworkBridgeHandler;
import org.openhab.binding.pbus.internal.handler.PbusSensorHandler;
import org.openhab.binding.pbus.internal.handler.PbusSerialBridgeHandler;
import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
 * The {@link PbusHandlerFactory} is responsible for creating things and thing
 * handlers.
 *
 * @author Jos Wanders - Initial contribution
 */
@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.pbus")
public class PbusHandlerFactory extends BaseThingHandlerFactory {

    private final SerialPortManager serialPortManager;
    private final ItemRegistry itemRegistry;

    @Activate
    public PbusHandlerFactory(final @Reference SerialPortManager serialPortManager,
            final @Reference ItemRegistry itemRegistry) {
        this.serialPortManager = serialPortManager;
        this.itemRegistry = itemRegistry;
    }

    @Override
    public boolean supportsThingType(ThingTypeUID thingTypeUID) {
        return SUPPORTED_BRIDGE_UIDS.contains(thingTypeUID) || SUPPORTED_THING_UIDS.contains(thingTypeUID);
    }

    @Override
    protected @Nullable ThingHandler createHandler(Thing thing) {
        ThingTypeUID thingTypeUID = thing.getThingTypeUID();
        ThingHandler thingHandler = null;

        if (SUPPORTED_BRIDGE_UIDS.contains(thingTypeUID)) {
            PbusBridgeHandler pbusBridgeHandler;
            if (thingTypeUID.equals(BRIDGE_NETWORK)) {
                pbusBridgeHandler = new PbusNetworkBridgeHandler((Bridge) thing);
            } else {
                pbusBridgeHandler = new PbusSerialBridgeHandler((Bridge) thing, serialPortManager);
            }
            thingHandler = pbusBridgeHandler;

        } else if (Pbus2cHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
            thingHandler = new Pbus2cHandler(thing);
        } else if (PbusSensorHandler.SUPPORTED_THING_TYPES.contains(thingTypeUID)) {
            thingHandler = new PbusSensorHandler(thing, itemRegistry);
        }

        return thingHandler;
    }
}
/**
 * Copyright (c) 2010-2024 Contributors to the openHAB project
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package org.openhab.binding.pbus.internal.handler;

import static org.openhab.binding.pbus.internal.PbusBindingConstants.*;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.pbus.internal.packets.PbusPacket;
import org.openhab.core.items.*;
import org.openhab.core.library.types.OpenClosedType;
import org.openhab.core.thing.*;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;

/**
 * The {@link PbusSensorHandler} is responsible for handling commands, which are
 * sent to one of the channels.
 *
 * @author Jos Wanders - Initial contribution
 */

@NonNullByDefault
public class PbusSensorHandler extends PbusThingHandler {
    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
            Arrays.asList(THING_2D20, THING_4D20, THING_2D42, THING_2D20S, THING_2D250, THING_4D20R));

    private final ItemRegistry itemRegistry;

    public String thingType = thing.getUID().toString().split(":")[1];

    public boolean fourPorts = (thingType.indexOf("4") == 0);

    public PbusSensorHandler(Thing thing, ItemRegistry itemRegistry) {
        super(thing);
        this.itemRegistry = itemRegistry;
    }

    @Override
    public void handleCommand(ChannelUID channelUID, Command command) {
        PbusBridgeHandler pbusBridgeHandler = getPbusBridgeHandler();
        if (pbusBridgeHandler == null) {
            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
            return;
        }
    }

    @Override
    public void onPacketReceived(byte[] packet) {
        logger.trace("onPacketReceived(sensor) was called");

        if (packet[0] == PbusPacket.STX && packet.length >= 5) {
            byte command = packet[3];

            final ChannelUID p1ChannelUID = new ChannelUID(thing.getUID(), "port1");

            if (command == COMMAND_PORT_STATUS && packet.length >= 6) {

                try {
                    State state = itemRegistry.getItem("pbus2c_Address_03_Port1").getState();
                } catch (ItemNotFoundException e) {
                    throw new RuntimeException(e);
                }

                byte channelPressed = packet[4];
                if (channelPressed != 0) {

                    updateState(p1ChannelUID, OpenClosedType.CLOSED);
                    logger.debug("Update Channel : {} to {}", p1ChannelUID, OpenClosedType.CLOSED);
                }

                byte channelReleased = packet[5];
                if (channelReleased != 0) {
                    updateState(p1ChannelUID, OpenClosedType.OPEN);
                    logger.debug("Update Channel : {} to {}", p1ChannelUID, OpenClosedType.OPEN);
                }
            }
        }
    }
}

Thanks, that did the trick,