Gc100ir transform map

First, thank you for getting the gc100ir binding updated and part of the repo. I’m finally having some success making this device work.

What I’m wondering is if there’s a way to use the binding via a .map file for transformation of the IR codes. In the updated Wiki documentation (https://github.com/openhab/openhab/wiki/Global-Cache-IR-Binding) a string item is used and has the specific IR embedded in the item binding. This then requires a number of string for each separate function on an individual device. Is there a way to map these instead?

Thank you.

Interesting idea. Could you rough out what you envision and how this would simplify configuration?

I first saw it supported in the TCP binding.

tcp=">[ON:‘MAP(my.device.map)’)], >[OFF:‘MAP(my.device.map)’]" // for a Switch Item where values are converted using the my.device.map

Without it, unless I’m missing something, I end-up with multiple lines of code, one per operation:

String AQUOS_ON { gc100ir="[#living|1|1|38000,1,1,10,70,10,30,10,30,10,30,10,70,10,30,10,70,10,30,10,70,10,30,10,30,10,70,10,30,10,70,10,30,10,1657,10,70,10,30,10,30,10,30,10,70,10,70,10,30,10,70,10,30,10,70,10,70,10,30,10,70,10,30,10,70,10,1657]" }
String AQUOS_OFF { gc100ir="[#living|1|1|38000,1,1,10,70,10,30,10,30,10,30,10,70,10,70,10,70,10,30,10,70,10,30,10,30,10,70,10,30,10,70,10,30,10,1657,10,70,10,30,10,30,10,30,10,70,10,30,10,30,10,70,10,30,10,70,10,70,10,30,10,70,10,30,10,70,10,1657]" }
String AQUOS_VID4 { gc100ir="[#living|1|1|38000,1,1,11,70,11,30,11,30,11,30,11,30,11,70,11,30,11,70,11,70,11,30,11,30,11,70,11,70,11,70,11,30,11,1587,11,70,11,30,11,30,11,30,11,30,11,30,11,70,11,30,11,30,11,70,11,70,11,30,11,30,11,30,11,70,11,1830]" }
String AQUOS_CH2 { gc100ir="[#living|1|1|38000,1,1,10,70,10,30,10,30,10,30,10,30,10,30,10,70,10,30,10,30,10,30,10,30,10,30,10,30,10,70,10,30,10,1657,10,70,10,30,10,30,10,30,10,30,10,70,10,30,10,70,10,70,10,70,10,70,10,70,10,70,10,30,10,70,10,1657]" }

Followed by a series of individual buttons:

Frame label=“Aquos” {
Switch item=AQUOS_ON label=“Aquos ON” mappings=[1=“ON”]
Switch item=AQUOS_OFF label=“Aquos OFF” mappings=[1=“OFF”]
Switch item=AQUOS_VID4 label=“Aquos HDMI 4” mappings=[1=“HDMI 4”]
Switch item=AQUOS_CH2 label=“Aquos CH 2” mappings=[1=“CH 2”]

With it, I might instead have a single button with multiple mappings…

Switch item=AQUOS_SWITCH label=“Aquos TV” mappings=[ON=“On”,OFF=“Off”,TVCH2=“TV CH2”,HDMI=“HDMI”]

Where each mapping would map to a line in a file like sharpaquos.map that would define the IR codes.

The same number of IR code lines to maintain – though arguably easier in a .map file. But a simpler implementation at the button level if I could define a single string with the map. Something like this maybe:

String AQUOS_SWITCH { gc100ir="[#living|1|1|[MAP(sharpaquos.map):%s]]" }

It does look much cleaner to have a single item like

String MyTV { gc100ir="[#living|1|1|MAP(sharpaquos.map)]" }

and look up the string version of the sent command in a map file like:


The code could be changed to use any named transform in place of the IR codes, take in the sent command, and upon successfully transforming it, send those codes. Great idea.

I opened an issue for this enhancement request.

@watou We had traded posts on this a while ago. I’m just getting back around to this now that I got one of my OH2 installations working pretty well.

Is this the way you would envision this working? Note this is just dummy/test data.

Sample sitemap:

Frame label=“Contact Closure” {
Switch item=CC1 label="Activate Relay on Connector 1"
Switch item=CC2 label="Activate Relay on Connector 2"
Switch item=CC3 label=“Activate Relay on Connector 3”
Frame label=“Momentary Contact Closure Using Rules” {
Switch item=Momentary1 label=“Momentary Relay on Connector 1” mappings=[ON=“Do It”]
Switch item=Momentary2 label=“Momentary Relay on Connector 2” mappings=[ON=“Do It”]
Switch item=Momentary3 label=“Momentary Relay on Connector 3” mappings=[ON=“Do It”]

Frame label=“IR Device 1” {
Switch item=IRDevice1 label=“Device 1 Power on Connector 1” mappings=[POWER=“Power”]
Switch item=IRDevice1 label=“Device 1 Temp Up on Connector 1” mappings=[TEMP_UP=“Temp Up”]
Switch item=IRDevice1 label=“Device 1 Temp Down on Connector 1” mappings=[TEMP_DOWN=“Temp Down”]
Frame label=“IR Device 2” {
Switch item=IR Device2 label=“Device 2 Power on Connector 2 - Power” mappings=[POWER_ON=“On”,POWER_OFF=“Off”]
Switch item=IR Device2 label=“Device 2 Volume on Connector 2- Volume” mappings=[VOLUME_UP=“Volume Up”]
Frame label=“IR Device 3” {
Switch item=IRDevice3 label=“Device 3 Volume on Connector 3 - Volume” mappings=[VOLUME_UP=“Volume Up”,VOLUME_DOWN=“Volume Down”]
Switch item=IRDevice3 label=“Device 3 Input on Connector 3 - Input” mappings=[INPUT_HDMI_1=“HDMI 1”,INPUT_HDMI_2=“HDMI 2”,INPUT_DVD=“DVD”]
Frame label=“IR Device 4” {
Switch item=IRDevice4 label=“Device 4 Volume on Connector 3 - Volume” mappings=[VOLUME_DOWN=“Volume Down”]
Switch item=IRDevice4 label=“Device 4 Input on Connector 3 - Input” mappings=[INPUT_HDMI_1=“HDMI 1”,INPUT_HDMI_2=“HDMI 2”,INPUT_DVD=“DVD”]

Sample items:

Switch CC1    "Relay on Connector 1"  { channel="globalcache:itachCC:52043160527:m1c1" }
Switch CC2    "Relay on Connector 2"  { channel="globalcache:itachCC:52043160527:m1c2" }
Switch CC3    "Relay on Connector 3"  { channel="globalcache:itachCC:52043160527:m1c3" }

Switch Momentary1   "Momentary Rule on Connector 1"
Switch Momentary2   "Momentary Rule on Connector 2"
Switch Momentary3   "Momentary Rule on Connector 3"

String IRDevice1	"Device 1 on IR Connector 1 [MAP(device1.map):%s]"  { channel="globalcache:itachIR:52043061111:m1c1" }
String IRDevice2	"Device 2 on IR Connector 2 [MAP(device2.map):%s]"  { channel="globalcache:itachIR:52043061111:m1c2" }
String IRDevice3	"Device 3 on IR Connector 3 [MAP(device3.map):%s]"  { channel="globalcache:itachIR:52043061111:m1c3" }
String IRDevice4	"Device 4 on IR Connector 3 [MAP(device4.map):%s]"  { channel="globalcache:itachIR:52043061111:m1c3" }

Sample map (device3.map, other map files are similar)

POWER_ON=IR string goes here
POWER_OFF=IR string goes here
VOLUME_UP=IR string goes here
VOLUME_DOWN=IR string goes here
INPUT_HDMI_1=IR string goes here
INPUT_HDMI_2=IR string goes here
INPUT_HDMI_3=IR string goes here
INPUT_DVD=IR string goes here

Sample rule (using contact closure for things like garage door openers):

rule "Garage Door 1"
	Item Momentary1 received command
        sendCommand(CC1, ON)
        sendCommand(CC1, OFF)	   


  • For IR Devices 1 & 2, connector 1 (m1c1) and connector 2 (m1c2) are IR emitters
  • Fro IR Devices 3 & 4, connector 3 (m1c3) is an IR blaster, hence the reason why there are two items (IRDevice3 and IRDevice4) linked to the connector 3 channel

I have a prototype globalcache binding working (not based on gc100ir) with the following functionality:

  • automatic iTach and GC100 device discovery by listening for globalcache device announcement beacons on multicast address and port. GC devices announce themselves every 10-20 seconds on a specific multicast IP and port.
  • auto discovered devices are added to the inbox, which then can be added as things using Paper UI
  • devices supported should include GC-100-6, GC-100-12, IP2IR, WF2IR, IP2CC, WF2CC, IP2SL, WF2SL (not sure about iTach Flex as I haven’t looked at the Flex API document yet)
  • Contact Closure (i.e. relay) devices are working

For IR devices, I’m a bit stumped on how to retrieve the IR string in handleCommand(). What are the APIs that I need to call in handleCommand that allow me to transform the command (e.g. INPUT_HDMI_1) to the IR string contained in the map file?

Once I get that functionality working for IR commands, it should work the same way for serial commands.

I still have quite a bit of work to do on the code. But, I really could use some help understanding how to map the command to the IR string. I don’t see much in the way of documentation to point me in the right direction.

Thanks for the help.

1 Like

The change I suggested for the OH1 GC100IR binding was to allow the binding config string to contain an expression like MAP(DeviceMakeModel.map) instead of the hardcoded string for a single IR command. Such a change would allow the item to receive any command like ON or OFF or “HDMI1”, etc., and then choose the correct IR command from a map file, the result being that a single item could be used for sending all IR commands, instead of the current situation of needing a separate item for each command to the same device.

In OH2/ESH, you would probably instead use Thing configuration as the way to specify how commands are mapped to IR codes for the given thing. So if you have a “TelevisionRemote” Thing, when its handleCommand is called, you would inspect the Thing’s commandMap parameter, and then use the appropriate transformation service to produce the IR command to send.

Thanks for the feedback!

Manually creating a Thing for each controlled AV device (TV, cable box, DVD player, preamp/amp, etc.) was a little more work than I wanted. Ideally, I wanted to have a separate MAP file for each controlled AV device. This would make it easier to manage the IR codes for individual AV devices (i.e. they could be managed outside of OH2), more easily shared, etc.

It appears there’s no way for the ThingHandler to access a MAP file that’s referenced in the item definition, so that would seem to rule out what I was proposing in my post above.

I suppose I could use the MAP transformation service directly from within the ThingHandler. A MAP file could be specified in the GlobalCache thing configuration for each connector on the GlobalCache device. That works fine when using an IR emitter and/or the serial port, as there’s a one-to-one relationship between the connector on the GlobalCache device and the AV device it’s controlling. It also looks like it’s just a few lines of code to implement.

The downside is when there’s an IR blaster connected to connector 3 on the GlobalCache device. In this case, there could/would be multiple AV devices controlled through that one GlobalCache device connector. This would require that the MAP file contain IR codes for multiple devices. This is easily done. By convention, commands would need to named to avoid conflicts (e.g. TV_POWER_ON, DVD_POWER_ON, CABLE_POWER_ON, PREAMP_POWER_ON).

1 Like

I am interested in this binding. Please let us know when you have a jar to test. I have several IP2IR’s set up and working well with a commercial product. I also have an IP2SL.

I also have a couple of comments.

  1. Your assumption that there is only one device on IR ports 1 & 2. They do make 2 way and 3 way IR emitters, so one could connect multiple devices on these ports as well.


  1. For the IP2SL devices, I would think that this binding would allow another binding to pass through it. In other words, it would automatically discover the device and create a thing. But then another binding could take over and pass through. (see Pioneer AVR binding wiki)

Thanks for the feedback. This is still a work in progress. I have discovery, contact closure, and IR working. I have a GC-100 on the way so that I can test serial. I’ve only run it in the IDE so far. :worried: Today I’ll probably build a jar and try it in my OH2 test environment.

For IR and SL, I decided to add a config item to the thing where the MAP file can specified. The MAP file would contain entries for all AV devices, such as with this example I’ve been using for testing:


Then there would be items that looked like this:

String XFINITYFR    "Xfinity One Box in Family Room"        { channel="globalcache:itachIR:52043154597:m1c1" }
String HKAVR245     "Harmon Kardon AVR-245 Receiver"        { channel="globalcache:itachIR:52043154597:m1c2" }
String SAMSUNGHLS   "Samsung HL-S DLP TV"                   { channel="globalcache:itachIR:52043154597:m1c3" }

String TEST_IR      "Item for testing IR errors"            { channel="globalcache:itachIR:52043154597:m1c1" }

And then something like this in the sitemap:

	Frame label="Harmon Kardon Receiver" {
            Switch item=HKAVR245 label="Power" mappings=[HKAVR245_POWER_ON="On",HKAVR245_POWER_OFF="Off"]
            Switch item=HKAVR245 label="Volume" mappings=[HKAVR245_VOLUME_UP="Up",HKAVR245_VOLUME_DOWN="Down"]
            Switch item=HKAVR245 label="Select Input" mappings=[HKAVR245_HDMI1="HDMI 1",HKAVR245_HDMI2="HDMI 2"]
    	Frame label="Samsung TV" {
            Switch item=SAMSUNGHLS label="Power" mappings=[SAMSUNGHLS_POWER_ON="On",SAMSUNGHLS_POWER_OFF="Off"]
    	Frame label="Xfinity One" {
            Switch item=XFINITYFR label="Guide" mappings=[XFINITYXG2_GUIDE="Guide",XFINITYXG2_EXIT="Exit"]
    	Frame label="Test IR" {
            Switch item=TEST_IR label="Test Bad Command" mappings=[TEST_IR_COMMAND="Command"]
            Switch item=TEST_IR label="Test Bad Frequency" mappings=[TEST_IR_FREQ="Freq"]
            Switch item=TEST_IR label="Test Bad Repeat" mappings=[TEST_IR_REPEAT="Repeat"]
            Switch item=TEST_IR label="Test Bad Offset" mappings=[TEST_IR_OFFSET="Offset"]
            Switch item=TEST_IR label="Test Unequal On/Off" mappings=[TEST_IR_ONOFF="On Off"]

Let me know what you think with this approach.

I’ve not used one of those multiway emitters. I see no reason why that wouldn’t work with the above approach, but I’ll need to test it.

I’ll look into what you said about pass through. I did not think about that as a possibility.

1 Like

I think your approach that you outline looks good, although I am new to OH and I am not a programmer.

As far as the serial is concerned, I have another example. I have a shinybow 8x8 audio matrix switcher that is controlled by an RS 232 port. I am using an IP to serial converter (digi portserver in my case, but same concept as GC IP2SL). I am using the tcp/udp binding to send commands and get feedback. So, here is another case where one could use your GC binding to discover the device, then another binding takes over. You could argue that most OH users are pretty advanced and know how to find the IP address of their device and should just go straight to the second binding. But commercial RC devices like iRule and Roomie/Simple Control have figured out device discovery, and it is pretty nice. I previously mentioned that several brands of AV Receivers have rs232 ports that could be used to control them with other bindings.

I can’t think of a case for IR and CC where your binding would need to allow another binding to pass through or hand off to another.

Also, I wonder if there would be a way to rapidly import the IR codesets from outside databases. I noticed on the GC website, that they have a database of IR codes, and regular users are allowed to import 5 devices per day. OpenRemote has a built in IR code database called beehive. Remotecentral has a lot of IR codes in text format.

Sorry for the long delay in responding, @jacksteraz. I got side tracked with tracking down some issues with another binding (squeezebox), and had to figure out the process for how to submit changes.

I have at least a dozen things on my todo list for the globalcache binding. Once I get 50-60% through that list, I might have a jar file that you could take for a test drive, if you’re still interested. I’ve been using the IR functionality pretty extensively with my home AV system. The Contact Closure (CC) functionality also is pretty straightforward. Have not had a chance to test serial (SL) yet, or the GC-100…

I’m hoping to use the hue emulation binding from @digitaldan to enable Amazon Echo control of AV devices connected to a GC device. Theoretically, this would allow any IR, serial, and/or relay-activated device to be controlled using Echo.

I think I understand what you’re saying about the pass through. I think you are saying that the GC binding could act as a proxy to the other binding, such that the other binding could send/receive commands through the GC binding to the A/V device. I’m not sure how to do that at the present time, but I’ll give it some thought after I get the initial functionality working.

I look forward to trying your code.

I recently got an iTach IP2IR working with the old GC100ir binding. I updated the wiki to reflect that iTach’s work too.

@jacksteraz Sorry for the long delay.

If you still want to try it out, you can find the jar file here.

You need to be running a recent OH2 snapshot, or the recently released beta 4. If you drop this into the addons directory, the framework should load it. After that, it will immediately start to discover devices, and add them to the inbox.

You can read through the draft documentation here.

@watou I haven’t done a PR for this yet. I’ve been running it for a while now in a couple locations. Once I get some feedback from jacksteraz, I’ll likely submit the PR. Any feedback you have in advance of the PR would be greatly appreciated.


I’ve been quietly excited about this addon and have downloaded both the beta 4 and the addon. Autodetected my IP2CC just fine - but the itachflex IR’s had issues. This is what I got in the log:

2016-09-16 08:57:54.855 [ERROR] [balcache.discovery.MulticastListener] - Multicast listener unable to find a thing type for device model iTachFlexWiFi
2016-09-16 08:57:55.197 [WARN ] [balcache.discovery.MulticastListener] - Multicast listener beacon length is too short, length is 100

Then those messages repeat every 10 seconds or so…


Not surprised about the Flex. I don’t have a Flex, so I was unable to put in support for it yet. Sorry about not noting that. I really need to get one of those!

You can stop the messages by turning off discovery as described in the README.

Before you do that, if you wouldn’t mind, can you put it in TRACE mode in order to capture the Flex beacon announcement, then send that to me.

That would be log:set TRACE org.openhab.binding/globalcache in the karaf console.

Here you go:

2016-09-16 10:36:13.662 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener parsing announcement packet: AMXB<-UUID=GlobalCache_000C1EE0E330><-SDKClass=Utility><-Make=GlobalCache><-Model=iTachFlexEthernet><-Revision=710-3000-18><-Pkg_Level=><-Config-URL=><-PCB_PN=025-0034-12><-Status=Ready>
2016-09-16 10:36:13.662 [TRACE] [iscovery.GlobalCacheDiscoveryService] - Device of type iTachFlexEthernet discovered with MAC 000C1EE0E330 and IP
2016-09-16 10:36:13.662 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener looking up thing type for device model iTachFlexEthernet
2016-09-16 10:36:13.662 [ERROR] [balcache.discovery.MulticastListener] - Multicast listener unable to find a thing type for device model iTachFlexEthernet
2016-09-16 10:36:13.662 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener waiting for datagram on multicast port
2016-09-16 10:36:15.271 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener got datagram of length 100 from multicast port
2016-09-16 10:36:15.271 [WARN ] [balcache.discovery.MulticastListener] - Multicast listener beacon length is too short, length is 100
2016-09-16 10:36:15.271 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener waiting for datagram on multicast port
2016-09-16 10:36:18.271 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener waiting for datagram on multicast port
2016-09-16 10:36:20.146 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener got datagram of length 202 from multicast port
2016-09-16 10:36:20.146 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener parsing announcement packet: AMXB<-UUID=GlobalCache_000C1EE0EEEA><-SDKClass=Utility><-Make=GlobalCache><-Model=iTachFlexWiFi><-Revision=710-2000-18><-Pkg_Level=ÿ><-Config-URL=><-PCB_PN=025-0033-10><-Status=Ready>
2016-09-16 10:36:20.146 [TRACE] [iscovery.GlobalCacheDiscoveryService] - Device of type iTachFlexWiFi discovered with MAC 000C1EE0EEEA and IP
2016-09-16 10:36:20.146 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener looking up thing type for device model iTachFlexWiFi
2016-09-16 10:36:20.146 [ERROR] [balcache.discovery.MulticastListener] - Multicast listener unable to find a thing type for device model iTachFlexWiFi
2016-09-16 10:36:20.146 [TRACE] [balcache.discovery.MulticastListener] - Multicast listener waiting for datagram on multicast port

Note: if you want me to test those for you (both simply have the IR emitter/blaster cables attached - the ethernet one only uses on port, the wireless one uses two ports)

You have both models. That’s awesome.

This is good. It discovers it correctly as an itach. It just doesn’t know what to do with it because I haven’t defined the things for those models yet.

I’ll take you up on the offer to test it. I might not be able to get to it until Sunday, though.

Thanks for the logs.

@mhilbush That’s great you’ve got an OH2 binding working. This might be the best solution for the usability shortcoming in the OH1 binding, where you need a separate item for each IR command – just upgrade to OH2! When you’re ready to contribute the binding, you would submit a PR to the openhab2-addons repo with it.

It sounds like many people will be very pleased to have an OH2 binding with discovery included!

@tmrobert8 There’s a new jar file in the same location as the last one. This one should (hopefully) discover the ethernet and wifi flex devices, and add them to the inbox. I also copied the iTach IR channels to the flex thing definitions, so if the discovery works, the device might even accept an IR code. This is not the final solution, but it was an easy change.

BTW, which IR cables do you have connected to the flex?