Or, how to control your A/C from your phone
You may have seen my earlier post about my new home automation setup. Well I just upgraded it! I just finished testing out a new infrared remote control send and receive capability and it is pure awesome. Here’s what I can do now from within home-assistant:
- Turn on and off my new DeLonghi portable air conditioner from Costco, and set the temperature to whatever
- Turn on and off the TV and press any buttons from its remote control
- Turn on and off the stereo and virtually press any buttons from its remote control (which I never even had!)
- Use an old random blueray remote control to set scenes, turn lights on and off, etc. (basically do anything under home-assistant’s control)
This post is about how I did it on my Raspberry Pi.
Update: A video!
Setting up LIRC and learning the A/C remote
LIRC is a linux library to interface with infrared (IR) remotes. Setting it up, including schematics for hooking the IR receiver and emitter to the GPIO ports of the Pi are well-described here. So following those instructions is the first step.
(2019 Update: See this info, as some raspberry pi internals related to LIRC have changed!)
Then I had to teach LIRC about my equipment. The one I was most worried about was my DeLonghi “Pinguino” portable air conditioning unit from Costco (AN125HPEK). I was able to successfully learn the commands from the remote using LIRC in raw-capture mode. This post was very useful in figuring it out. A/C units send full packets, including information about what mode it’s in, what numerical temperature it’s set to (not just up and down), etc. Here’s what I did:
- I recorded a bunch of raw data and remember the order of buttons you pressed. For example, first I had the remote at the maximum temperature and then after I started recording I pressed “decrease temperature” a bunch of times until I was at the minimum:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
begin remote name DELONGHI flags RAW_CODES eps 30 aeps 100 gap 183413 begin raw_codes name OFF 8941 4531 505 1699 506 1697 510 621 508 … name AC_23 ... end raw_codes end remote |
3. Then I used irrecord in analyze mode to process the raw signals and extract the hex codes:
1 |
irsend SEND_ONCE DELONGHI FAN_LOW |
blew my mind when it worked. Yay. Excellent progress. I used irrecord in its normal learn mode to learn my Sony remote and it just asks you to name each key before you press it. That worked great. The codes I recorded for this A/C are available here.
Writing a new home-assistant component for lirc
With what I had up to this point, I could use home-assistant as is and use the shell_command component to control things around my house. This was what was recommended last time a lirc component was requested. I tried it out and it worked great:
1 2 3 4 5 6 7 |
shell_command: ac_on: irsend SEND_ONCE DELONGHI AC_25 ac_off: irsend SEND_ONCE DELONGHI OFF stereo_on: irsend SEND_ONCE STR-DE205 KEY_POWER stereo_video1: irsend SEND_ONCE STR-DE205 KEY_VIDEO1 stereo_off: irsend SEND_ONCE STR-DE205 KEY_POWER stereo_video2: irsend SEND_ONCE STR-DE205 KEY_VIDEO2 |
But then I got thinking that it’d be cool if I could have a IR remote control various aspects in home-assistant. My wife sometimes complains that she has to go find a phone to turn on the lights. If I had a remote laying on the table it’d be really easy to select scenes and whatnot. So I thought I’d write a lirc component.
Conveniently, there’s a python-lirc package in pip that brings lirc capabilities into Python3. So making a component was just a matter of interfacing between that package and home-assistant. I whipped up a component and tested it out by having KEY_1 turn on a scene and KEY_0 turn all lights off. It works! SO AWESOME!
I will open a pull request and try to get this feature into home-assistant for all to enjoy.
Now I can make rules that, you know, turn on my tv, my stereo, and put up a fireplace video like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
lirc: automation: - alias: Full fire sequence trigger: platform: event event_type: ir_command_received event_data: button_name: X_KEY_NETFLIX action: service: script.fire_sequence script: - fire_sequence: alias: Fire Sequence sequence: - service: shell_command.fire - delay: seconds: 1 - service: shell_command.tv_power - delay: seconds: 1 - service: shell_command.stereo_line_in # turns on stereo |
So awesome. I have submitted the code as PR 2139 and maybe it will go in the next release.
I’ve started toying with the shell_command to allow it to build the command from slider input so I can set the A/C to any value I want. Will open another PR if this guys doesn’t.
When you are going to give the pull request so we can also enjoy it ?
It’s already been merged and will be in the next release which should come out I think tomorrow.
hi there
i really like your post
but also really needs your help in recording my A/C
i followed the link but i couldn’t follow with all the comments
can you please write your own one in details? like how to manage the raw file and when to stop holding the key on in my remote…
thanks
(can i write you an email?)
Hey, nice! I’m not using LIRC and can’t manage getting the IR codes, could you please share the ones you recorded? Many Thanks!
Sure. I’ll update the post but they’re here. Might not be too useful without LIRC. Not sure.
Right, I tried to c&p those into the eventghost usb-uirt transmit-ir plugin but it did not work. Not sure if its the wrong code (I own a pac-cn92) or if the codes would need to be converted.
Don’t know if you need this anymore: You are right, the codes are completely different for this model. I recorded them, and here they are:
begin remote
name DELONGHI
bits 32
flags SPACE_ENC
eps 30
aeps 100
header 9111 4465
one 574 1626
zero 574 525
ptrail 581
gap 183413
toggle_bit_mask 0x0
begin codes
AC_16 0x12181100
AC_17 0x12181180
AC_18 0x12181140
AC_19 0x121811C0
AC_20 0x12181120
AC_21 0x121811A0
AC_22 0x12181160
AC_23 0x121811E0
AC_24 0x12181110
AC_25 0x12181190
AC_26 0x12181150
AC_27 0x121811D0
AC_28 0x12181130
AC_29 0x121811B0
AC_30 0x12181170
AC_31 0x121811F0
AC_32 0x12181108
MODE_SILENT 0x12481108
MODE_MED 0x12281108
MODE_MAX 0x12181108
MODE_DEHUMIDIFY 0x12421150
MODE_FAN 0x12111150
TEMPERATURE_FAHRENHEIT 0x121817F2
TEMPERATURE_CELCIUS 0x12181350
TIMER_ON 0x12181350
TIMER_OFF 0x12181150
TIMER_1 0x12188350
TIMER_2 0x12184350
TIMER_3 0x1218C350
TIMER_4 0x12182350
TIMER_5 0x1218A350
TIMER_6 0x12186350
TIMER_7 0x1218E350
TIMER_8 0x12181350
TIMER_9 0x12189350
TIMER_10 0x12185350
TIMER_11 0x1218D350
TIMER_12 0x12183350
TIMER_13 0x1218B350
TIMER_14 0x12187350
TIMER_15 0x1218F350
TIMER_16 0x12180B50
TIMER_17 0x12188B50
TIMER_18 0x12184B50
TIMER_19 0x1218CB50
TIMER_20 0x12182B50
TIMER_21 0x1218AB50
TIMER_22 0x12186B50
TIMER_23 0x1218EB50
TIMER_24 0x12181B50
end codes
end remote
Some codes seem to be the same and I suspect that actually the codes do not represent a press on a certain button at all but rather contain information about all states of operation (mode, temperature etc.)
Sorry for my lack of knowledge in H.A… but how did you get your scene “Bright” to display as an icon?
No worries. Actually I don’t have that anymore. A few versions ago hass changed scenes so they’re not badges at the top anymore. I don’t think it’s possible anymore.
Any suggestions on finding the gap? I tired using irrecord in raw mode, but I can’t get more than 2 dots to show up. I am trying to figure out the codes for my SPT portable AC unit.
I couldn’t get anything useful out of irrecord directly either. I had to switch over to the mode2 command and then post-process the results with irrecord -a.
This is my result from mode2
4426 4410 569 1627 561 541
563 1637 562 1637 563 539
565 537 567 1630 568 537
568 537 568 1632 571 532
568 535 569 1626 563 1635
564 539 565 1637 567 538
562 1634 565 1632 566 1631
568 1629 575 528 562 1639
570 1629 570 1633 565 538
567 535 589 519 586 512
593 1604 594 509 595 509
596 1607 592 1609 590 1602
567 535 599 505 590 512
592 511 594 510 594 511
594 513 591 518 586 1604
596 1600 568 1632 567 1628
562 1635 563 5267 4492 4366
567 1628 569 532 592 1609
588 1607 562 541 593 510
595 1602 597 508 596 509
595 1606 593 509 596 507
597 1600 589 1607 592 511
593 1610 589 516 588 1609
590 1606 593 1605 564 1632
567 536 598 1602 597 1602
597 1606 563 539 595 508
596 506 589 514 590 1606
593 509 596 509 600 1601
594 1603 595 1601 598 504
590 513 592 510 599 504
595 509 596 508 596 507
588 515 589 1611 598 1598
596 1600 594 1602 597 1601
567
But this is the result when trying to use irrecord -a
irrecord: decoding of OFF failed
#
# this config file was automatically generated
# using lirc-0.9.0-pre1(emulation) on Fri Sep 2 22:30:51 2016
#
# contributed by
#
# brand: SPT
# model no. of remote control:
# devices being controlled by this remote:
#
begin remote
name SPT
bits 98
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100
header 4448 4414
one 579 1620
zero 579 523
ptrail 565
gap 548544
toggle_bit_mask 0x0
begin codes
end codes
end remote
Ok I’m onto something here. I took your raw codes and hand-split them into this file:
begin remote
name MYREMOTE
flags RAW_CODES
eps 30
aeps 100
gap 183413
begin raw_codes
name BUTTON1
4426 4410 569 1627 561 541
563 1637 562 1637 563 539
565 537 567 1630 568 537
568 537 568 1632 571 532
568 535 569 1626 563 1635
564 539 565 1637 567 538
562 1634 565 1632 566 1631
568 1629 575 528 562 1639
570 1629 570 1633 565 538
567 535 589 519 586 512
593 1604 594 509 595 509
596 1607 592 1609 590 1602
567 535 599 505 590 512
592 511 594 510 594 511
594 513 591 518 586 1604
596 1600 568 1632 567 1628
562 1635 563
name BUTTON2
4492 4366
567 1628 569 532 592 1609
588 1607 562 541 593 510
595 1602 597 508 596 509
595 1606 593 509 596 507
597 1600 589 1607 592 511
593 1610 589 516 588 1609
590 1606 593 1605 564 1632
567 536 598 1602 597 1602
597 1606 563 539 595 508
596 506 589 514 590 1606
593 509 596 509 600 1601
594 1603 595 1601 598 504
590 513 592 510 599 504
595 509 596 508 596 507
588 515 589 1611 598 1598
596 1600 594 1602 597 1601
567
end raw_codes
end remote
I did that by recognizing two ~4000 length ones as the header of a new button. I deleted the ~5000 length gap between the two buttons. You can continue the process and probably get all the buttons. Let me know how it goes.
Then when I ran irrecord, I got:
begin remote
name MYREMOTE
bits 48
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100
header 4459 4388
one 582 1616
zero 582 519
ptrail 564
gap 272054
toggle_bit_mask 0x0
begin codes
BUTTON1 0xB24D7B84E01F
BUTTON2 0xB24D7B84E01F
end codes
end remote
try it out! Good luck.
I will try this, thanks. I should mention though that that is all output from pressing just one button, the on/off.
Interesting. It’s definitely two distinct packets. Did you press the button twice? There’s probably an On command and an Off command. These A/C units tend to send full packets at each press, so instead of temperature up, temperature down, it’s always “AC to 65 degrees” or something. Anyway let me know how it goes!!
No luck, I am only pressing the button once. The same button is used for both on, and off. If the remote is facing away from the unit and I press the button I have to press it twice to get it back in sync. So, if the unit is on and I press the button facing away from it, then come back and press it facing the unit nothing happens. When I press it a second time it will then turn off.
Below is me pressing the button for what should be an on signal, wait a seconds, and then pressing it again for what should be an off signal.
7370948
4448 4400 568 1628 561 542
562 1648 551 1637 562 541
563 539 566 1631 568 537
574 557 542 1633 565 538
567 536 568 1629 560 1663
543 533 565 1638 561 1642
567 536 569 1632 567 1636
563 1628 561 1635 564 1634
565 1633 566 539 565 1632
567 536 569 534 570 533
562 541 563 540 565 539
568 537 565 1632 567 1630
569 1654 535 541 564 540
564 540 565 538 566 1637
562 541 564 539 565 538
567 1634 565 1631 568 1629
569 1629 561 5275 4444 4403
568 1629 570 533 562 1639
570 1652 537 540 564 540
565 1631 568 536 568 537
568 1633 566 536 568 535
570 1627 562 1634 564 539
566 1636 563 1640 570 541
553 1639 570 1628 561 1636
563 1634 565 1631 568 1631
568 537 568 1629 570 532
562 541 564 538 566 537
568 535 569 536 569 535
569 1627 562 1635 564 1639
560 537 568 534 560 543
562 543 562 1640 569 534
570 533 561 541 594 1606
563 1635 564 1632 569 1631
618
3423643
4444 4403 568 1627 562 540
564 1637 562 1634 565 538
566 562 543 1654 535 543
561 570 535 1665 544 532
562 541 564 1659 540 1629
569 561 534 1642 567 537
568 1629 569 1626 564 1633
565 1631 568 542 562 1631
569 1629 570 1633 565 537
568 562 542 566 528 569
536 1635 564 565 540 538
566 1663 535 1635 565 1631
568 535 569 560 535 568
536 540 565 566 539 539
565 564 540 536 569 1632
567 1629 569 1628 562 1635
563 1635 564 5269 4455 4401
556 1633 565 539 565 1636
563 1633 566 537 568 534
570 1653 536 543 561 543
562 1639 570 533 562 541
563 1633 566 1631 568 534
570 1632 568 537 567 1630
569 1627 562 1634 565 1631
567 536 569 1631 568 1630
569 1641 558 538 566 537
568 535 569 533 561 1661
539 538 566 539 573 1629
563 1633 565 1632 567 535
570 533 561 541 564 539
565 540 565 539 565 538
567 562 542 1631 568 1629
560 1635 564 1633 566 1633
616
Here is my “manually-decoded” version of that:
begin remote
name MYREMOTE
flags RAW_CODES
eps 30
aeps 100
gap 183413
begin raw_codes
name BUTTON1
4448 4400 568 1628 561 542
562 1648 551 1637 562 541
563 539 566 1631 568 537
574 557 542 1633 565 538
567 536 568 1629 560 1663
543 533 565 1638 561 1642
567 536 569 1632 567 1636
563 1628 561 1635 564 1634
565 1633 566 539 565 1632
567 536 569 534 570 533
562 541 563 540 565 539
568 537 565 1632 567 1630
569 1654 535 541 564 540
564 540 565 538 566 1637
562 541 564 539 565 538
567 1634 565 1631 568 1629
569 1629 561
name BUTTON2
4444 4403
568 1629 570 533 562 1639
570 1652 537 540 564 540
565 1631 568 536 568 537
568 1633 566 536 568 535
570 1627 562 1634 564 539
566 1636 563 1640 570 541
553 1639 570 1628 561 1636
563 1634 565 1631 568 1631
568 537 568 1629 570 532
562 541 564 538 566 537
568 535 569 536 569 535
569 1627 562 1635 564 1639
560 537 568 534 560 543
562 543 562 1640 569 534
570 533 561 541 594 1606
563 1635 564 1632 569 1631
618
name BUTTON3
4444 4403 568 1627 562 540
564 1637 562 1634 565 538
566 562 543 1654 535 543
561 570 535 1665 544 532
562 541 564 1659 540 1629
569 561 534 1642 567 537
568 1629 569 1626 564 1633
565 1631 568 542 562 1631
569 1629 570 1633 565 537
568 562 542 566 528 569
536 1635 564 565 540 538
566 1663 535 1635 565 1631
568 535 569 560 535 568
536 540 565 566 539 539
565 564 540 536 569 1632
567 1629 569 1628 562 1635
563 1635 564
name BUTTON4
4455 4401
556 1633 565 539 565 1636
563 1633 566 537 568 534
570 1653 536 543 561 543
562 1639 570 533 562 541
563 1633 566 1631 568 534
570 1632 568 537 567 1630
569 1627 562 1634 565 1631
567 536 569 1631 568 1630
569 1641 558 538 566 537
568 535 569 533 561 1661
539 538 566 539 573 1629
563 1633 565 1632 567 535
570 533 561 541 564 539
565 540 565 539 565 538
567 562 542 1631 568 1629
560 1635 564 1633 566 1633
616
end raw_codes
end remote
and here is the result from arecord -i. In this case, it appears that it’s sending double packets. Two “ON” commands the first time, and two “OFF” commands the second time, perhaps?
begin remote
name MYREMOTE
bits 48
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100
header 4447 4401
one 562 1635
zero 562 541
ptrail 589
gap 272083
toggle_bit_mask 0x0
begin codes
BUTTON1 0xB24DBF40708F
BUTTON2 0xB24DBF40708F
BUTTON3 0xB24D7B84E01F
BUTTON4 0xB24D7B84E01F
end codes
end remote
The EO1F one is the same as I got last time (I didn’t notice BUTTON1 and BUTTON2 were exactly identical). If you load this up in LIRC and have it send two of one or the other of these codes one right after the other, does anything happen?
Good catch, didn’t see those were the same either. Still no luck however, not sure how to send it quick enough. Tried calling it twice in a shell script and watching the LED with a camera and it is noticeably two blink, which isn’t what the remote looks like.
Dang. What a pain. Try:
irsend SEND_ONCE MYREMOTE BUTTON1 BUTTON1
or
irsend SEND_ONCE MYREMOTE BUTTON3 BUTTON3
I’m not sure how much of a delay that will incur but hopefully not a large one.
Also try shortening the gap setting for the remote. Try as short as 5000.
Ooh and try fiddling with the repeat_gap (try 5000) and min_repeat settings (set it to 1 for one repetition).
I’m getting these from here: http://lirc.org/html/lircd.conf.html
Awesome, thanks for the help. I’ll try these when I get home from work tomorrow. I’ll let you know how it goes.
🙁 still no luck with lirc. However I was able to take the raw code from above, put that into some Arduino code and get the AC to turn off. I am using the same setup as I am on the pi, but can’t get it to work further than about 4 feet. Any idea why?
I think it is possible the issue I am having with the pi is a range thing. I will try to test this closer and see what happens, but I am not sure I will be able to get the pi/lircs timing quick enough all of the repeat_gaps/gaps I tried I was still able to see two distinct flashes of the LED, not the case on the Arduino.
This is great stuff! Thanks for sharing!
Your HA interface (especially AC control part) is awesome! Do you mind sharing the configuration?
Also, I am trying to get the IR transmitter on a ESP8266. Any advice?
Again, very inspiring post. Thanks!
I just ordered some ESP8266’s to play with, they look awesome. You’d have to code it up to somehow receive over the network the raw timing for the IR code from LIRC and then blink the IR emitter with those precise timings (using one of the GPIOs on the base of a transistor, just like I did with the pi). Let me know if you get that working because it sounds like an excellent idea.
Hi ntouran and thanks for sharing the video, code and everything!
Don’t you have the problem that the states (of the TV for example) are not recorded such that if you activate the fire_sequence twice, it would actually turn off the tv and stereo?
Hi. Yes that is definitely a problem. You can only do fire_sequence when everything is off in the first place. Fortunately, my stereo always turns on when you press an input selecting button but never turns off so for music I’m lucky and OK. For TV, it’s a challenge. I have a camera that can see the TV so I can check it if I get confused about it being on or off when I’m away.
Other stereos don’t have the on-only command and they’re a real pain. so you just have to try to keep track of things. Definitely suboptimal.
Hello,
I’m trying to do the same but I’m facing some problems : how to get the gap parameter ?
I’m doing a :
sudo irrecord -a clim.conf > lircd.conf
to have a more readable file but it returns me :
irrecord: could not find gap.
irrecord: decoding of OFF failed
Sometimes you have to hand-edit the codes and manually split the button presses based on very long delays you might see between the buttons (e.g 20000+ in my case). I did this for a guy in the comments earlier: https://partofthething.com/thoughts/?p=1010#comment-3233 and I hope it ended up working. If you want to send me the results of your mode2 recording I can take a look.
Thank you for your answer,
Here is the result of my mode2 recording when hitting button decrease temperature (first value is for decreasing to 31°C, last is for decreasing to 16°C) :
https://www.dropbox.com/s/giu0vzvmet8zv7k/ac_going_down_in_celcius.dat?dl=0
Wow, that’s huge packet! I tried for a while but was not able to process it to codes with irrecord. You might be able to use it as a totally raw conf file though. Give this a whirl as your lircd.conf
Dunno if it will work or not. Sorry I couldn’t get it.
You too are having the “irrecord: could not find gap” error when trying to process the file (irrecord -a) ?
Indeed.
You don’t have to convert the raw data from mode2 into binaries, just paste the timing figures into lircd.conf as is. I did this for my Toshiba air cond and it works so great!
Do you know why ?
Hi everyone
Thanks to Nick’s detailed description i am able to control my air conditioner from the raspberry pi. Now that the that part is done i want to control other air conditioners too. I have 2 Ac’s of the same company(same model) that i want to control independently from the raspberry pi. Is it possible that i can do this
Hi Nick,
I am trying to set my AC to any temperature using an input slider and IR commands but unable to do it.
I can turn ON and OFF the AC using scripts but changing the temperature using the input slider is not working for me can you help me in that.
Hey! I have this. Here’s what I did.
1. Create a shell_command with a template that fills in the number from the slider:
set_ac_to_slider: ‘irsend SEND_ONCE DELONGHI AC_{{states.input_slider.ac_temperature.state|int}}_AUTO’
2. Call the command when you want. I made mine so it triggers as a script so I can press a button to have it send the command rather than having it go whenever the slider changes:
216 ac_set:
217 alias: Set AC to any value
218 sequence:
219 – service: shell_command.set_ac_to_slider
3. If you really want it to happen whenever you change the slider, make an automation that triggers off the slider state like this:
624 trigger:
625 platform: state
626 entity_id: input_slider.ac_temperature
Thanks for your help. It worked
Could you share some of your Home Assistant configs? I’m really interested in how to get the slider working to control the temp/fan. Please let me know if you still do anything with this project, as I have just built the circuit and I’m trying to get lirc working with home assistant. Any help would be much appreciated.
Sure!
Here’s the slider:
input_number:
ac_temperature:
name: A/C Setting
initial: 24
min: 18
max: 32
step: 1
Then in the shell command section:
shell_command:
set_ac_to_slider: 'ssh pi@rpi irsend SEND_ONCE DELONGHI AC_{{states.input_number.ac_temperature.state|int}}_AUTO'
A script:
ac_set:
alias: Set AC to any value
sequence:
- service: shell_command.set_ac_to_slider
Then I just put that script on the UI and press it when I want to apply the slider value.