B4A Library IrdaManager

The IrdaManager library is exclusively for use with Samsung devices.
It exposes the hidden Samsung IrdaManager system servcie, enabling you to use the device's IR transmitter to send IR codes.

For more info take a look at this thread: http://www.b4x.com/forum/basic4android-updates-questions/29902-what-hardware-does-b4a-support.html

IrdaManager
Version: 0.02
  • IrdaManager
    Methods:
    • Hex2Dec (HexData As String, Separator As String) As String
      Converts a String of Hex IR codes into a String of comma separated decimal codes suitable for use with WriteIrSend.
      Separator denotes the separator character used in the HexData input.
    • Initialize As Boolean
      Initialize the IrdaManager.
      Returns True if successfully initialized, otherwise False.
      If initialization fails the B4A LastException property will contain the related Exception.
    • IsInitialized As Boolean
      Returns whether or not the IrdaManager is initialized.
    • WriteIrSend (DecimalData As String) As Boolean
      Sends Data using the IrdaManager.
      Returns True if successfully sent, otherwise False.
      If send fails the B4A LastException property will contain the related Exception.

Here's a simple example showage usage syntax:

B4X:
Sub Process_Globals
End Sub

Sub Globals
   Dim IrdaManager1 As IrdaManager
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If IrdaManager1.Initialize Then
      Log("IrdaManager successfully initialized")
      Dim HexData As String="0000 006d 0022 0003 00a9 00a8 0015 003f 0015 003f 0015 003f 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 003f 0015 003f 0015 003f 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 003f 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0040 0015 0015 0015 003f 0015 003f 0015 003f 0015 003f 0015 003f 0015 003f 0015 0702 00a9 00a8 0015 0015 0015 0e6e"
      Dim DecData As String=IrdaManager1.Hex2Dec(HexData, " ")
      Log("DecData: "&DecData)
      
      If IrdaManager1.WriteIrSend(DecData) Then
         Log("WriteIrSend succeeded")
      Else
         Log("WriteIrSend failed: "&LastException)
      End If
   Else
      Log("Failed to initialize the IrdaManager: "&LastException)
   End If
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

As you can see the WriteIrSend (DecimalData As String) As Boolean method accepts a String and this String should be a decimal IR code sequence.
If you get a code from somewhere that is a hexadecimal IR sequence then you will need to use the Hex2Dec (HexData As String, Separator As String) As String method to convert the hex sequence to a decimal sequence suitable for use with WriteIrSend.

The library files, example project and library source code are attached.

Martin.
 

Attachments

  • IrdaManager_0.02.zip
    14.7 KB · Views: 652

aleung

Member
Licensed User
Longtime User
Hi, Does this support the IR code transmit continuously as if a real remote button pressed and stop transmit when button release?
Thanks.
 

merlin2049er

Well-Known Member
Licensed User
Longtime User
Ok. I tried the power codes from that site using my Samsung tablet to turn on my Samsung TV without any luck.

I'll try some other codes for my other sets.

It sure looked like it was blasting the Ir codes.
 

aleung

Member
Licensed User
Longtime User
When the Samsung S4 is upgraded to android version 4.4.2, the IrdaManager functions give out NullpointerException. Any idea why and how to fix this?

"...
** Activity (main) Resume **
main_activity_resume (B4A line: 222)
IrEngine.Initialize
java.lang.NullPointerException
at uk.co.martinpearman.b4a.irdamanager.IrdaManager.Initialize(IrdaManager.java:66)
..."
 

aleung

Member
Licensed User
Longtime User
Hi Warwound,

When looking at the android.com about the Android 4.4, It mention of a new infrared transmitters function (below). Is it possible to generate for B4A library for this?

IR Blasters
Android 4.4 introduces platform support for built-in IR blasters, along with a new API and system service that let you create apps to take advantage them.
Using the new API, you can build apps that let users remotely control nearby TVs, tuners, switches, and other electronic devices. The API lets your app check whether the phone or tablet has an infrared emitter, query it's carrier frequencies, and then send infrared signals.
Because the API is standard across Android devices running Android 4.4 or higher, your app can support the broadest possible range of vendors without writing custom integration code.

<and>

Infrared transmitters
When running on a device that includes an infrared (IR) transmitter, you can now transmit IR signals using the ConsumerIrManager APIs. To get an instance of ConsumerIrManager, call getSystemService() with CONSUMER_IR_SERVICE as the argument. You can then query the device's supported IR frequencies with getCarrierFrequencies() and transmit signals by passing your desired frequency and signal pattern with transmit().
You should always first check whether a device includes an IR transmitter by calling hasIrEmitter(), but if your app is compatible only with devices that do have one, you should include a <uses-feature> element in your manifest for "android.hardware.consumerir" (FEATURE_CONSUMER_IR).
 

warwound

Expert
Licensed User
Longtime User
Here we have a new library that wraps the new ConsumerIrManager API.

ConsumerIrManager
Comment:
ConsumerIrManager allows you to:
Check whether the device has an infrared emitter.
Query it's carrier frequencies.
Send infrared signals.
CarrierFrequencyRange represents a range of carrier frequencies (inclusive) on which the infrared transmitter can transmit.
ConsumerIrManager and CarrierFrequencyRange are only available when using android API 19+.
Version: 0.02
  • CarrierFrequencyRange
    Methods:
    • GetMaxFrequency As Int
      Get the maximum (inclusive) frequency in this range segment.
    • GetMinFrequency As Int
      Get the minimum (inclusive) frequency in this range segment.
    • Initialize (ConsumerIrManager1 As ConsumerIrManager, MinFrequency As Int, MaxFrequency As Int)
      Create a segment of a carrier frequency range.
    • IsInitialized As Boolean
  • ConsumerIrManager
    Methods:
    • GetCarrierFrequencies As CarrierFrequencyRange[]
      Query the infrared transmitter's supported carrier frequencies.
      Returns an array of CarrierFrequencyRange objects representing the ranges that the transmitter can support,
      or Null if there was an error communicating with the Consumer IR Service.
    • HasIrEmitter As Boolean
      Check whether the device has an infrared emitter.
    • Hex2Dec (HexData As String, Separator As String) As String
      Converts a String of Hex IR codes into a String of comma separated decimal codes.
      Separator denotes the separator character used in the HexData input.
    • Initialize
    • IsInitialized As Boolean
    • Transmit (CarrierFrequency As Int, Pattern() As Int)
      Transmit an infrared pattern.
      This method is synchronous; when it returns the pattern has been transmitted.
      Only patterns shorter than 2 seconds will be transmitted.
      CarrierFrequency - The IR carrier frequency in Hertz.
      Pattern - The alternating on/off pattern of pulses to transmit.
    Permissions:
    • android.permission.TRANSMIT_IR

And some example code showing basic syntax:

B4X:
Sub Process_Globals
End Sub

Sub Globals
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim ConsumerIrManager1 As ConsumerIrManager
    ConsumerIrManager1.Initialize
    If ConsumerIrManager1.HasIrEmitter Then
        Log("The device has an IR emitter")
        Dim CarrierFrequencyRanges() As CarrierFrequencyRange
        CarrierFrequencyRanges=ConsumerIrManager1.GetCarrierFrequencies
        If CarrierFrequencyRanges=Null Then
            Log("Failed to get carrier frequencies, there was an error communicating with the Consumer IR Service")
        Else
            Dim i As Int
            Log("CarrierFrequencyRanges:")
            For i=0 To CarrierFrequencyRanges.Length-1
                Log("Min: "&CarrierFrequencyRanges(i).GetMinFrequency&", Max: "&CarrierFrequencyRanges(i).GetMaxFrequency)
            Next
        End If
    Else
        Log("The device has no IR emitter")
    End If
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

On my Moto G (android 4.4.2) it logs "The device has no IR emitter" as expected, i have no devices with IR emitters.

On my Galaxy S3 (android 4.3) it force closes as expected with the exception "java.lang.NoClassDefFoundError:android.hardware.ConsumerIrManager".

I'll leave you all to test and work out how to use the Transmit method.
Then we can decide whether to keep this and the IrdaManager as separate libraries or merge them.

Library files and demo project attached.

Martin.
 

Attachments

  • ConsumerIrManager_v0.02_20140324.zip
    11.6 KB · Views: 370
Last edited:

Toley

Active Member
Licensed User
Longtime User
Hi Martin, it happens to be exactly what I was looking for. I have test it on my Galaxy S4 and it works very fine. This is why I have send you a little something (enough to get a beer I wish). Just a little clarification, the pattern data is not the length in microseconds but it's the number of pulse required to get that duration. There is a detailed explanation oh this site (it describe the Pronton protocol) http://www.hifi-remote.com/infrared/IR-PWM.shtml

In fact, Pronton files works directly with this library. Many files can be easily found on the Internet.

To demonstrate this I have a screen shot of my experimentation :

20140314_811311.jpg


The frequency I send is 36 kHz (27.778 us). The first data I send is 0x60 (96 dec), then 96 x 27.778us = 2.667 ms and this is what I get.

Also I would like if you can add your Hex2Dec method to this library.

Thanks again and good work.
 

aleung

Member
Licensed User
Longtime User
Martin, Toley, Thanks.

I tried with also the S4 and works. One point is when I tried with a pattern shorter than 4 bursts(standard IR may not be so short though), it sent strange pattern IR.
------------------------------
For example, this one works:
Dim tint(10) As Int
tint(0)=100
tint(1)=100
tint(2)=200
tint(3)=200
tint(4)=300
tint(5)=300
tint(6)=400
tint(7)=400
tint(8)=500
tint(9)=500
ConsumerIrManager1.Transmit(38000,tint)
------
But this one give strange output:
Dim tint(6) As Int
tint(0)=100
tint(1)=100
tint(2)=200
tint(3)=200
tint(4)=300
tint(5)=300
ConsumerIrManager1.Transmit(38000,tint)
------

The is just minor and can workaround.

The new library is good.

Thanks.
 

warwound

Expert
Licensed User
Longtime User
Ok i have updated the new library, adding the Hex2Dec method and updating the Transmit method documentation for the Pattern parameter to:

Pattern - The alternating on/off pattern of pulses to transmit.

Does that make better sense?
I see the bug in the official documentation was also reported here: http://stackoverflow.com/questions/20244337/consumerirmanager-api-19.
If anyone wants to suggest better documentation text please do.

Now should i merge both IrdaManager and ConsumerIrManager libraries into a single new library?
Or are they best left as separate libraries?

Martin.

PS @Toley - thanks for the donation.
 

ivan.tellez

Active Member
Licensed User
Longtime User
Well, I think its better to merge them. maybe just renamig the IrdaManager to something like SamsungIrda and adding some functions to the lib to determine the Android API level, so it will work on 4.2.2 and 4.3 with Samsung, and on 4.4.2 with other brands.

A drawback of this is that the IrdaManager.WriteIrSend() is not compatible with the ConsumerIrManager.Transmit()

Could you implement someting like:

ConsumerIrManager.Transmit2(DecimalData As String) as Bolean


Compatible with the IrdaManager.WriteIrSend()??


Just Ideas

Thanks
 

warwound

Expert
Licensed User
Longtime User
I think changing the IrdaManager object name is a good idea in theory but how as it'd break existing code perhaps not such a good idea?

It'd be good to have a single format of 'data to transmit' that both libraries can use.
But the two libraries use a different syntax to define a 'transmit'.
IrdaManager requires just a String of comma separated decimal values.
ConsumerIrManager requires and array of Integers and an Integer carrier frequency parameter.
I see no easy way to convert from one to the other but i do not actually have any experience of using these libraries.

If anyone can suggest a possible formula for conversion i'll take a look.

Martin.
 

ivan.tellez

Active Member
Licensed User
Longtime User
Well, actually converting it's the easiest part.

Both uses the same protocol, just need to convert the comma separated string into an array.

This code is on Galaxy S4:
  • IrdaManager works with android 4.2.2 and 4.3
  • IrdManager causes an error on 4.4.2 (Maybe Samsung´s service is not present on 4.4.2)
  • ConsumerIrManager Works on Android 4.4.2

On Irda Mannager:

B4X:
Dim MyIR As IrdaManager
MyIR.Initialize
MyIR.WriteIrSend("38028,169,168,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,63,21,63,21,63,21,63,21,63,21,63,21,1794,169,168,21,21,21,3694")
'Works Turning on/of a Samsung TV on Android 4.2.2 and 4.3

On ConsumerIrManager:

B4X:
        Dim ConsumerIrManager1 As ConsumerIrManager
        ConsumerIrManager1.Initialize
       
        Dim pat() As Int
        pat=Array As Int(169,168,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,63,21,63,21,63,21,63,21,63,21,63,21,1794,169,168,21,21,21,3694)
        ConsumerIrManager1.Transmit(38028,pat)
'Works Turning on/of a Samsung TV on Android 4.4.2



To avoid the broken code, you can just upgrade the IrdaManager to be aware of the Api level of Android and is is present the samsung's service.

In this case you will have somenting like this:

Pseudocode to put it clear:
B4X:
Dim IrdaManager1 as IrdaManager

IrdaManager.Initialize
'Internaly Checks Android api leve and samsung's services to determine which object to use.

IrdaManager.IsReady() As Boolean
'If the device has Samsung's Api, or if has an IRblaster on 4.4.2 returns True

IrdaManager.WriteIrSend(DecimalData as String) 'IrdaManager Format
'Uses the available object (Samsungs or ConsumerIrManager) if is ConsumerIrManager, converts the comma separated string to an array

IrdaManager.WriteIrSend2(CarrierFrequency As Int, Pattern() As Int) 'ConsumerIrManager Format
'Uses the available object (Samsungs or ConsumerIrManager) if is Samsung´s, Converts the array to a comma separated string


just ideas. Hope to be useful


Ivan
 

warwound

Expert
Licensed User
Longtime User
Here's an attempt to make working with the device's IR emitter a bit simpler.
The IrdaHelper library contains both ConsumerIrManager and IrdaManager objects plus a new IrdaHelper object.

IrdaHelper
Comment:
IrdaHelper creates a common interface to both IrdaManager and ConsumerIrManager.
IrdaManager exposes the hidden Samsung IrdaManager API to B4A.
ConsumerIrManager allows you to:
Check whether the device has an infrared emitter.
Query it's carrier frequencies.
Send infrared signals.
CarrierFrequencyRange represents a range of carrier frequencies (inclusive) on which the infrared transmitter can transmit.
ConsumerIrManager and CarrierFrequencyRange are only available when using android API 19+.
Version: 0.01beta
  • IrdaHelper
    Fields:
    • STATE_CONSUMER_IR_MANAGER As IrdaHelperState
      The ConsumerIrManager is initialized.
    • STATE_IRDA_MANAGER As IrdaHelperState
      The Samsung IrdaManager is initialized.
    • STATE_NOT_INITIALIZED As IrdaHelperState
      Neither ConsumerIrManager or IrdaManager are initialized.
    Methods:
    • GetConsumerIrManager As ConsumerIrManager
      Returns the ConsumerIrManager if it has been initialized, otherwise Null.
    • GetIrdaHelperState As IrdaHelperState
      Returns the state of the IrdaHelper.
      Values will be one of the STATE_???? fields.
    • GetIrdaManager As IrdaManager
      Returns the IrdaManager if it has been initialized, otherwise returns Null.
    • GetTransmitData (CarrierFrequency As Int, Pattern() As Int) As TransmitData
      Creates a TransmitData object from CarrierFrequency and Pattern.
    • GetTransmitData2 (DecimalData As String) As TransmitData
      Creates a TransmitData object from comma separated DecimalValues.
    • GetTransmitData3 (HexData As String, Separator As String) As TransmitData
      Creates a TransmitData object from HexData.
    • Hex2Dec (HexData As String, Separator As String) As String
      Converts a String of Hex IR codes into a String of comma separated decimal codes.
      Separator denotes the separator character used in the HexData input.
    • Initialize As Boolean
      Initialize the IrdaHelper.
      Returns a Boolean True if either:
      1) The device is running android API level 19+ and has an IR emitter.
      OR
      2) The device is running android API level less than 19, is a Samsung device and the Samsung IrdaManager API is available
      Note that on some Samsung devices the IrdaManager API is available but have no IR emitter.
    • Transmit (TransmitData1 As TransmitData)
      Transmits the TransmitData using using whichever object (ConsumerIrManager or IrdaManager) has been initialized.
      If no object has been initialized then the Transmit method simply logs an error.
  • TransmitData
    Properties:
    • CarrierFrequency As Int [read only]
      Returns the CarrierFrequency.
      Only available if the IrdaHelperState is STATE_CONSUMER_IR_MANAGER.
    • DecimalData As String [read only]
      Returns the comma separated DecimalData.
      Only available if the IrdaHelperState is STATE_IRDA_MANAGER.
    • Pattern() As Int [read only]
      Returns the Pattern.
      Only available if the IrdaHelperState is STATE_CONSUMER_IR_MANAGER.

And a simple example showing the syntax:

B4X:
Dim IrdaHelper1 As IrdaHelper
Dim Initialized As Boolean=IrdaHelper1.Initialize
If Initialized Then
   Log("Able to transmit IR codes")
   
   Select IrdaHelper1.GetIrdaHelperState
     Case IrdaHelper1.STATE_CONSUMER_IR_MANAGER
       Log("The ConsumerIrManager is initialized")
       '   you can get the instance of ConsumerIrManager using IrdaHelper1.GetConsumerIrManager
     Case IrdaHelper1.STATE_IRDA_MANAGER
       Log("The Samsung IrdaManager is initialized")
       '   you can get the instance of IrdaManager using IrdaHelper1.GetIrdaManager
     Case IrdaHelper1.STATE_NOT_INITIALIZED
       Log("Neither ConsumerIrManager or IrdaManager are initialized")
       '   this condition should not be met as IrdaHelper1.Initialize has returned True
   End Select
   
   '   examples showing how we can transmit IR codes formatted as either:
   '   CarrierFrequency As Int, Pattern() As Int
   '   DecimalData As String
   '   HexData As String, Separator As String
   
   IrdaHelper1.Transmit(IrdaHelper1.GetTransmitData(38028, Array As Int(169,168,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,63,21,63,21,63,21,63,21,63,21,63,21,1794,169,168,21,21,21,3694)))
   IrdaHelper1.Transmit(IrdaHelper1.GetTransmitData2("38028,169,168,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,63,21,63,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,63,21,21,21,21,21,21,21,21,21,21,21,21,21,64,21,21,21,63,21,63,21,63,21,63,21,63,21,63,21,1794,169,168,21,21,21,3694"))
   
   IrdaHelper1.Transmit(IrdaHelper1.GetTransmitData3("0000 006d 0022 0003 00a9 00a8 0015 003f 0015 003f 0015 003f 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 003f 0015 003f 0015 003f 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 003f 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0015 0040 0015 0015 0015 003f 0015 003f 0015 003f 0015 003f 0015 003f 0015 003f 0015 0702 00a9 00a8 0015 0015 0015 0e6e", " "))

Else
   Log("Unable to transmit IR codes")
   Log(IrdaHelper1.GetIrdaHelperState)
End If

The idea is that you initialize an instance of IrdaHelper, if it's Initialize method returns True you can continue and use it's various Transmit methods to send IR codes.
The IrdaHelper initializes the correct object ConsumerIrManager or IrdaManager and handles formatting your IR codes to the required format.
IrdaHelper has three Transmit methods enabling you to transmit IR codes in various formats.

If you need access to the underlying ConsumerIrManager or IrdaManager you can use the GetConsumerIrManager or GetIrdaManager methods.

Tested the above code on my KitKat Moto G and it simply logs (as expected);
Unable to transmit IR codes
STATE_NOT_INITIALIZED
I still have no device with an IR emitter to properly test on so will await some feedback from you all.

Demo project and IrdaHelper library attached.

Martin.
 

Attachments

  • IrdaHelper_20140327.zip
    20.6 KB · Views: 354
Top