-
Notifications
You must be signed in to change notification settings - Fork 0
How To Implement A Binding
NOTE: This page is still under construction!!!
Bindings are the most interesting bit for people to get into coding for openHAB and therefore, many questions arise around this topic regularly.
This page tries to give you a starting point, if you intent to implement (and hopefully contribute) your own binding.
For information about how to setup a development environment, please see the according wiki page.
The openHAB runtime distribution comes without any binding. All bindings are considered to be "add-ons", which the user can optionally install by putting it in the "addons" folder of the runtime. As a consequence of this, a binding should usually be a single file and as a file corresponds to an OSGi bundle, a binding should be a single bundle.
The purpose of a binding is to translate between events on the openHAB event bus and an external system. This translation should happen "stateless", i.e. the binding must not access the !ItemRegistry in order to get hold of the current state of an item. Likewise, it should not itself keep states of items in memory.
As explained above, a binding should correspond to one bundle. The naming convention for the binding bundle is "org.openhab.binding.<name>
". To create a working binding skeleton one should use the Maven archetype which facilitates the creation process. The following steps have to be performed:
-
run a full build (meaning run
mvn clean install
in the topmost directory) -
cd ./bundles/archetype/./org.openhab.archetype.binding
-
mvn clean install
-
cd ../../binding
-
use maven archetype
mvn archetype:generate -B -DarchetypeGroupId=org.openhab.archetype -DarchetypeArtifactId=org.openhab.archetype.binding -DarchetypeVersion=1.4.0-SNAPSHOT -Dauthor=<author> -Dversion=1.4.0 -DartifactId=org.openhab.binding.<binding-name-in-small-caps> -Dpackage=org.openhab.binding.<binding-name-in-small-caps> -Dbinding-name=<binding-name-in-camel-case>
-
import newly created project by selecting 'Import->Existing Java project'
-
active the new plugin in !RunConfiguration 'Run Configurations->openHAB Runtime->Plugins->activate your plugin->Auto-start true'
Another possibility is to copy an existing binding and do a search&replace for the name.
A binding may require general configuration settings, such as a host and port of the external system to connect to. This can be done through the OSGi Configuration Admin service, i.e. by registering an OSGi service, which implements the interface ManagedService
.
openHAB then allows to add configuration information in openhab.cfg, which is automatically dispatched to your !ManagedService. All you have to make sure is to specify the property "service.pid
" in your component declaration as "org.openhab.<name>
", where name is the prefix to be used in openhab.cfg.
Please refer to the KNX binding for an example on how to implement a ManagedService and how to register it through OSGi Declarative Services.
more t.b.d.
t.b.d.
There are to directions for the communication of a binding - either sending out commands and status updates from the openHAB even bus to some external system or to receive information from an external system and post this on the openHAB event bus for certain items.
A binding can implement the one or the other direction or both. We usually talk about "Out-", "In-" or "InOut-Bindings" respectively.
A good example for such an "Out-Binding" is the Exec-binding. When receiving a command for an item, a configured command is executed on the command line of the host system.
Such bindings can be implemented pretty easily: All you have to do is to extend the class AbstractBinding
and override the methods
public void internalReceiveCommand(String itemName, Command command)
and / or protected void internalReceiveUpdate(String itemName, State newState) As the method signatures suggest, you are passed the name of the item and the command or state that was sent on the openHAB event bus. In these methods, you can then perform whatever code is appropriate for your use case. See the ExecBinding class as an example.
All there is left to do is to register your class with the OSGi event admin service. To do so, your component has to provide the EventHandler
service and define the property event.topics
. In your OSGI-INF/binding.xml
file, this should look like this:
If you are only interested in commands, you can also choose openhab/command/*
as a topic.
See the component descriptor of the ExecBinding as an example.
If you receive information from an external system somewhere in your code and you want to post commands or status updates on the openHAB event bus, you can as well simply extend AbstractBinding
for your implementation. Your binding class should then reference the EventPublisher
service in the OSGI-INF/binding.xml
file. This should look like this:
In your code, you can then simply refer to the instance variable eventPublisher
in order to very easily send events:
eventPublisher.postUpdate(itemName, state);
eventPublisher.postCommand(itemName, command);
eventPublisher.sendCommand(itemName, command);
Please note the difference between sendCommand
and postCommand
: Sending means a synchronous call, i.e. the method does not return until all event bus subscribers have processed the event. So if you just want to do a fire&forget, use the asynchronous postCommand method instead.
In order to receive information from an external system, you usually either need some background thread continuously listening to the external system (e.g. on a socket or serial interface) or you need to regularly actively poll the external system. In both cases, choosing to extend the class AbstractActiveBinding
will help you.
AbstractActiveBinding
extends AbstractBinding
so everything said above will still be the same. You will simply get an additional feature: The active binding provides a thread creation and handling and all you have to do is to specify a pause interval between calls of the execute()
method.
See the NtpBinding class for a simple example of such a binding.
A few notes on the lifecyle: Bindings are dynamic OSGi services and thus behave according to the OSGi specs. The dynamics make it easy to change openHAB during runtime (add new bindings later on, reconfigure items, etc.), but it also brings some complexity in the coding. In consequence the methods of the interfaces that the bindings implement (such as addBindingProvider(), allBindingsChanged(), updated(), processBindingConfiguration() etc.) can be called at any time and in any order. So you need to make sure that you write your code in a way that you can always react in a decent way when a method is called and reach a valid state of your binding.
This specifically means:
- activate() is called as soon as all required dependencies (e.g. the first !BindingProvider) are resolved and set in your service instance
- optional dependencies might be set any time (e.g. a second !BindingProvider is set through addBindingProvider())
- updated() is called any time, but after activate(). So you should even consider the case that you receive invalid configuration at a later time and thus stop your services again (-> setProperlyConfigured(false)).
- processBindingConfigurations can be called anytime, but always after activate()
After IDE setup and creating/testing your binding, you may want others to use it. For this, you can use the Eclipse export function as follows:
- Right-click on your binding project
- Select Export
- Choose Plug-in Development->Deployable plug-ins and features
- Fill "Directory" with the Path where you want your jar-file to appear
- Check "Use class files compiled in the workspace" on the "Options" tab
- Click Finish and check yor Directory
###Linux / OS X
###Windows
- Cosm Persistence
- db4o Persistence
- Exec Persistence
- InfluxDB Persistence
- JDBC Persistence
- JPA Persistence
- Logging Persistence
- mapdb Persistence
- MongoDB Persistence
- MQTT Persistence
- my.openHAB Persistence
- MySQL Persistence
- rrd4j Persistence
- Sen.Se Persistence
- SiteWhere Persistence
- AlarmDecoder Binding
- Anel Binding
- Arduino SmartHome Souliss Binding
- Asterisk Binding
- Astro Binding
- Autelis Pool Control Binding
- BenQ Projector Binding
- Bluetooth Binding
- Bticino Binding
- CalDAV Binding
- Comfo Air Binding
- Config Admin Binding
- CUL Binding
- CUL Intertechno Binding
- CUPS Binding
- DAIKIN Binding
- Davis Binding
- Denon Binding
- digitalSTROM Binding
- DMX512 Binding
- DSC Alarm Binding
- DSMR Binding
- eBUS Binding
- Ecobee Binding
- EDS OWSever Binding
- eKey Binding
- Energenie Binding
- EnOcean Binding
- Enphase Energy Binding
- Epson Projector Binding
- Exec Binding
- Freebox Binding
- Freeswitch Binding
- Frontier Silicon Radio Binding
- Fritz AHA Binding
- Fritz!Box Binding
- FS20 Binding
- Global Cache IR Binding
- GPIO Binding
- HAI/Leviton OmniLink Binding
- HDAnywhere Binding
- Heatmiser Binding
- Homematic / Homegear Binding
- HTTP Binding
- IEC 62056-21 Binding
- IHC / ELKO Binding
- ImperiHome Binding
- Insteon Hub Binding
- Insteon PLM Binding
- IPX800 Binding
- IRtrans Binding
- jointSPACE-Binding
- KNX Binding
- Koubachi Binding
- LCN Binding
- LightwaveRF Binding
- Leviton/HAI Omnilink Binding
- Lg TV Binding
- Logitech Harmony Hub
- MailControl Binding
- MAX!Cube-Binding
- MAX! CUL Binding
- MiLight Binding
- MiOS Binding
- Modbus TCP Binding
- MPD Binding
- MQTT Binding
- MQTTitude binding
- Neohub Binding
- Nest Binding
- Netatmo Binding
- Network Health Binding
- Network UPS Tools Binding
- Nibe Heatpump Binding
- Nikobus Binding
- Novelan/Luxtronic Heatpump Binding
- NTP Binding
- One-Wire Binding
- Onkyo AV Receiver Binding
- Open Energy Monitor Binding
- OpenPaths presence detection binding
- OpenSprinkler Binding
- OSGi Configuration Admin Binding
- Panasonic TV Bindung
- panStamp Binding
- Philips Hue Binding
- Piface Binding
- pilight Binding
- Pioneer-AVR-Binding
- Plex Binding
- Plugwise Binding
- PLCBus Binding
- Primare Binding
- Pulseaudio Binding
- RFXCOM Binding
- RWE Smarthome Binding
- Sager WeatherCaster Binding
- Samsung AC Binding
- Samsung TV Binding
- Serial Binding
- Sallegra Binding
- Satel Alarm Binding
- Sinthesi Sapp Binding
- Snmp Binding
- Somfy URTSI II Binding
- Sonos Binding
- Squeezebox Binding
- Swegon ventilation Binding
- System Info Binding
- TA CMI Binding
- TCP/UDP Binding
- Tellstick Binding
- TinkerForge Binding
- Tivo Binding
- VDR Binding
- Velleman-K8055-Binding
- Wago Binding
- Wake-on-LAN Binding
- Waterkotte EcoTouch Heatpump Binding
- Weather Binding
- Wemo Binding
- Withings Binding
- XBMC Binding
- xPL Binding
- Yamahareceiver Binding
- Zibase Binding
- Z-Wave Binding
- Asterisk
- Google Calendar
- Linux Media Players
- ROS Robot Operating System
- Telldus Tellstick
- Zoneminder
- Wink Hub (rooted)
- Wink Monitoring
- Transformations
- XSLT
- JSON
- REST-API
- Security
- Service Discovery
- Voice Control
- BritishGasHive-Using-Ruby
- Dropbox Bundle
A good source of inspiration and tips from users gathered over the years. Be aware that things may have changed since they were written and some examples might not work correctly.
Please update the wiki if you do come across any out of date information.
- Comfo Air Binding
- Ecobee Examples
- Nest Examples
- Rollershutter Bindings
- Squeezebox
- WAC Binding
- WebSolarLog
- Alarm Clock
- Convert Farenheit to Celcius
- The mother of all lighting rules
- Reusable Rules via Functions
- Combining different Items
- Items, Rules and more Examples of a SmartHome
- Google Map
- Controlling openHAB with Android
- Usecase examples
- B-Control Manager
- Spell checking for foreign languages
- Flic via Tasker
- Chromecast via castnow