Newbie at plugin development: Accessing values stored in services/mybinding.cfg from code

I can’t seem to find an example anywhere, but how do I access config parameters in a services config file from java code in a new plugin. I want to put my client id and secret for an oauth app into services/mybinding.cfg but I don’t really know how to find it at runtime when I get there.

As an example, see my sensebox binding:

First, you create a Configuration class that matches your desired properties:

https://github.com/openhab/openhab2-addons/blob/master/addons/binding/org.openhab.binding.sensebox/src/main/java/org/openhab/binding/sensebox/config/SenseBoxConfiguration.java

Then you let the ESH core load your file:

I think this is read from the things/mything.cfg though, correct? I was thinking that properties for authentication to a service is more of a services/myservice.cfg. In the Think config it gets messy to add things like clientid/secret/etc to a thing config and would be much nicer in the whole key value pair per line config like you see in services/myservice.cfg. Maybe you’re saying the same thing with this code and I’m missing it.

Aaah, I believe you are right, this is for the things config file. I have the same services/myservice.cfg in one of my openhab1 bindings, I don’t know off the hand though whether there is any difference for OH1 bindings:

see the “updated()” method in PushBulletActionService.java

Looking at some of the openhab 1 bindings, I see that for instance the nest binding makes use of the Preferences.userRoot().node(‘some_identifier’). Which seems to have data that is in the nest.cfg file. I’m not completely sure what has to happen to get that information loaded into the Preferences persistence, but I’m wondering if this is still considered to be the correct way for openhab 2 bindings.

[Edit]
Sorry that was wrong, give me a minute to post the correct way.

The correct way:

In OH 2 bindings what is used as a config parameter is set in the XML files ( found in the directory ESH-INF).
The actual usage is like:

Configuration config = getThing().getConfiguration();
setLocationID((String) config.get(TankerkoenigBindingConstants.CONFIG_LOCATION_ID));
setApiKey((String) config.get(TankerkoenigBindingConstants.CONFIG_API_KEY));

1 Like

OK, I figured this out with a little bit of digging around.

When you create a cfg file with key/value pairs in the services folder, it loads the key value pairs into a service.pid of org.openhab.<cfg_file_name> which can be seen when you go into the karaf console and type config:list.

This was easy, but it took me a little while to figure out how to read them out with code. What I did was create an osgi service that read in the key/value pairs and then loaded them into the service I needed them in. To do this, I had to implement the org.osgi.service.cm.ManagedService Interface on my service in the .internal package and then create a matching .xml file in OSGI-INF.

<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" 
    immediate="true" 
    activate="activate" 
    deactivate="deactivate"
    name="org.openhab.wink.AuthenticationConfigurationService">
<implementation class="org.openhab.binding.wink.internal.AuthenticationConfigurationService"/>
<service>
  <provide interface="org.osgi.service.cm.ManagedService"/>
</service>
<property name="service.pid" value="org.openhab.wink" />
</scr:component>

Important parts of this are the service.pid property which defines the cfg file that you loaded from the services folder and the activate attribute on the scr:component which defines the name of the method on the implementation class that is called with the ComponentContext object that will give you access to those key/value pairs through the getProperties() method:

    public void activate(ComponentContext context) throws Exception {
       Dictionary<String, Object> properties = context.getProperties();
       configure(properties);
    }

The ManagedService interface also defines an updated(Dictionary) method that handles changes to the configuration of the service as well.

you could add a @Component and @Activate - then the required xml will be generated automatically

this results in reading services/rachio.cfg

@Component(service = DiscoveryService.class, immediate = true, configurationPid = "rachio")  
public class RachioDiscoveryService extends AbstractDiscoveryService {
    private final Logger logger = LoggerFactory.getLogger(RachioDiscoveryService.class);

and then process the cfg key/value pairs

@Override
@Activate
protected void activate(Map<String, Object> configProperties) {
        bindingConfig.updateConfig(configProperties);
}