[FL-2792] AC Universal Remote (#1725)

* Add Universal AC Remote scene
* Implement AC gui
* Basic working implemetation
* Another Universal AC Remote implementation
* Update icons
* Adjust button positions
* Revert old ButtonPanel class
* Update resource manifest
* [FL-2627] Flipper applications: SDK, build and debug system (#1387)
* Update api definitions
* Add UniversalRemotes documentation
* Use more Flipper-friendly signal names

Co-authored-by: SG <who.just.the.doctor@gmail.com>
This commit is contained in:
Georgii Surkov 2022-09-20 08:09:37 +03:00 committed by GitHub
parent f5ff6438d1
commit 066da4080b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 207 additions and 5 deletions

View file

@ -15,6 +15,7 @@ ADD_SCENE(infrared, remote, Remote)
ADD_SCENE(infrared, remote_list, RemoteList)
ADD_SCENE(infrared, universal, Universal)
ADD_SCENE(infrared, universal_tv, UniversalTV)
ADD_SCENE(infrared, universal_ac, UniversalAC)
ADD_SCENE(infrared, debug, Debug)
ADD_SCENE(infrared, error_databases, ErrorDatabases)
ADD_SCENE(infrared, rpc, Rpc)

View file

@ -2,8 +2,8 @@
typedef enum {
SubmenuIndexUniversalTV,
SubmenuIndexUniversalAC,
SubmenuIndexUniversalAudio,
SubmenuIndexUniversalAirConditioner,
} SubmenuIndex;
static void infrared_scene_universal_submenu_callback(void* context, uint32_t index) {
@ -21,6 +21,12 @@ void infrared_scene_universal_on_enter(void* context) {
SubmenuIndexUniversalTV,
infrared_scene_universal_submenu_callback,
context);
submenu_add_item(
submenu,
"Air Conditioners",
SubmenuIndexUniversalAC,
infrared_scene_universal_submenu_callback,
context);
submenu_set_selected_item(submenu, 0);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewSubmenu);
@ -35,12 +41,12 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
if(event.event == SubmenuIndexUniversalTV) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalTV);
consumed = true;
} else if(event.event == SubmenuIndexUniversalAC) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
consumed = true;
} else if(event.event == SubmenuIndexUniversalAudio) {
//TODO Implement Audio universal remote
consumed = true;
} else if(event.event == SubmenuIndexUniversalAirConditioner) {
//TODO Implement A/C universal remote
consumed = true;
}
}

View file

@ -0,0 +1,109 @@
#include "../infrared_i.h"
#include "common/infrared_scene_universal_common.h"
void infrared_scene_universal_ac_on_enter(void* context) {
infrared_scene_universal_common_on_enter(context);
Infrared* infrared = context;
ButtonPanel* button_panel = infrared->button_panel;
InfraredBruteForce* brute_force = infrared->brute_force;
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/ac.ir"));
button_panel_reserve(button_panel, 2, 3);
uint32_t i = 0;
button_panel_add_item(
button_panel,
i,
0,
0,
3,
22,
&I_Off_25x27,
&I_Off_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Off");
button_panel_add_item(
button_panel,
i,
1,
0,
36,
22,
&I_Dehumidify_25x27,
&I_Dehumidify_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Dh");
button_panel_add_item(
button_panel,
i,
0,
1,
3,
59,
&I_CoolHi_25x27,
&I_CoolHi_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Cool_hi");
button_panel_add_item(
button_panel,
i,
1,
1,
36,
59,
&I_HeatHi_25x27,
&I_HeatHi_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Heat_hi");
button_panel_add_item(
button_panel,
i,
0,
2,
3,
91,
&I_CoolLo_25x27,
&I_CoolLo_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Cool_lo");
button_panel_add_item(
button_panel,
i,
1,
2,
36,
91,
&I_HeatLo_25x27,
&I_HeatLo_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Heat_lo");
button_panel_add_label(button_panel, 6, 10, FontPrimary, "AC remote");
view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);
infrared_show_loading_popup(infrared, true);
bool success = infrared_brute_force_calculate_messages(brute_force);
infrared_show_loading_popup(infrared, false);
if(!success) {
scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases);
}
}
bool infrared_scene_universal_ac_on_event(void* context, SceneManagerEvent event) {
return infrared_scene_universal_common_on_event(context, event);
}
void infrared_scene_universal_ac_on_exit(void* context) {
infrared_scene_universal_common_on_exit(context);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View file

@ -0,0 +1,38 @@
Filetype: IR library file
Version: 1
#
name: Off
type: raw
frequency: 38000
duty_cycle: 0.33
data: 502 3436 510 475 509 476 508 477 507 477 507 479 505 480 504 480 504 490 504 481 502 482 501 483 563 420 511 474 510 475 509 476 508 485 561 423 508 476 508 477 507 478 506 479 505 480 504 481 503 517 508 476 508 478 506 479 505 479 505 481 503 483 521 1456 501 498 507 479 505 480 504 481 503 482 501 483 563 421 562 422 509 499 506 479 505 480 504 481 503 482 502 484 510 1451 506 479 505 1542 562 1396 509 471 502 476 508 469 504 3425 511
#
name: Dh
type: raw
frequency: 38000
duty_cycle: 0.33
data: 507 3430 506 479 505 480 504 481 503 481 503 483 501 485 509 1453 504 1465 503 482 502 483 511 473 500 485 509 476 508 477 507 478 506 487 507 477 507 478 506 479 505 480 504 482 502 483 501 484 500 523 503 482 502 484 500 485 509 476 508 476 508 478 506 1456 501 501 504 482 502 483 501 484 500 485 509 476 508 477 507 1455 502 509 506 479 505 1457 500 485 509 476 508 1454 503 482 502 483 501 568 499 1459 509 1450 507 471 502 474 510 3421 505
#
name: Cool_hi
type: raw
frequency: 38000
duty_cycle: 0.33
data: 504 3433 503 482 502 484 510 474 510 475 509 476 508 478 506 1456 564 1405 510 475 509 476 508 502 482 477 507 478 506 479 505 480 504 489 505 480 504 481 503 482 502 483 511 473 511 474 510 475 509 509 506 479 505 480 504 481 503 482 512 473 511 474 510 476 508 1469 509 475 509 476 508 477 507 478 506 479 505 480 504 481 503 505 510 475 509 502 482 503 481 504 480 505 478 507 477 1459 509 560 507 1451 506 473 511 493 480 1450 507 3422 503
#
name: Cool_lo
type: raw
frequency: 38000
duty_cycle: 0.33
data: 525 3615 530 506 561 474 562 474 562 473 563 473 531 505 562 1502 528 1542 562 474 562 474 530 505 531 504 532 504 532 504 616 419 533 510 589 447 526 509 527 509 527 509 527 508 528 508 528 507 529 542 525 510 526 509 527 509 527 509 527 508 528 508 528 1535 527 524 533 503 533 503 533 502 534 502 534 502 534 501 535 501 525 534 533 502 534 502 534 501 535 502 534 1529 533 503 533 503 533 587 533 497 528 501 524 1536 526 501 524 3609 526
#
name: Heat_hi
type: raw
frequency: 38000
duty_cycle: 0.33
data: 531 3406 530 455 529 456 528 457 537 447 537 448 535 450 534 1429 528 1442 536 448 536 449 534 451 532 452 532 453 530 454 530 455 529 464 530 454 529 456 528 457 537 448 536 449 535 450 533 451 533 490 535 449 534 450 534 451 533 452 532 453 531 455 529 1433 534 1443 535 449 535 450 534 452 531 453 530 454 530 455 529 456 538 472 532 452 532 454 530 1433 535 1427 530 1432 536 1427 530 1431 537 1511 530 448 536 1422 535 1423 534 1422 535 3395 530
#
name: Heat_lo
type: raw
frequency: 38000
duty_cycle: 0.33
data: 506 3430 506 478 506 479 505 480 504 481 503 482 502 484 500 1463 505 1465 503 482 502 483 501 484 500 485 509 476 508 477 507 478 506 486 508 477 507 478 506 479 505 480 504 481 503 482 502 483 500 523 502 482 502 483 501 484 500 485 509 476 508 478 506 1455 502 498 507 478 506 479 505 481 503 482 501 483 500 484 500 485 509 500 505 481 502 482 502 1461 507 1455 502 1459 509 476 508 477 507 563 504 1453 504 1454 503 1454 503 1453 504 3426 499

View file

@ -0,0 +1,36 @@
# Universal Remotes
## Air Conditioners
### Recording signals
Air conditioners differ from most other infrared-controlled devices because their state is tracked by the remote.
The majority of A/C remotes have a small display which shows current mode, temperature and other settings.
When the user presses a button, a whole set of parameters is transmitted to the device, which must be recorded and used as a whole.
In order to add a particular air conditioner to the universal remote, 6 signals must be recorded: `Off`, `Dh`, `Cool_hi`, `Cool_lo`, `Heat_hi`, `Heat_lo`.
Each signal (except `Off`) is recorded using the following algorithm:
1. Get the remote and press the **Power Button** so that the display shows that A/C is ON.
2. Set the A/C to the corresponding mode (see table below), while leaving other parameters such as fan speed or vane on **AUTO** (if applicable).
3. Press the **POWER** button to switch the A/C off.
4. Start learning a new remote on Flipper if it's the first button or press `+` to add a new button otherwise.
5. Point the remote to Flipper's IR receiver as directed and press **POWER** button once again.
6. Save the resulting signal under the specified name.
7. Repeat the steps 2-6 for each signal from the table below.
| Signal | Mode | Temperature | Note |
| :-----: | :--------: | :---------: | ----------------------------------- |
| Dh | Dehumidify | N/A | |
| Cool_hi | Cooling | See note | Lowest temperature in cooling mode |
| Cool_lo | Cooling | 23°C | |
| Heat_hi | Heating | See note | Highest temperature in heating mode |
| Heat_lo | Heating | 23°C | |
Finally, record the `Off` signal:
1. Make sure the display shows that A/C is ON.
2. Start learning a new signal on Flipper and point the remote towards the IR receiver.
3. Press the **POWER** button so that the remote shows the OFF state.
4. Save the resulting signal under the name `Off`.
The resulting remote file should now contain 6 signals. Any of them can be omitted, but that will mean that this functionality will not be used.
Test the file against the actual device. Every signal must do what it's supposed to.
If everything checks out, add these signals to the [A/C universal remote file](/assets/resources/infrared/assets/ac.ir)
and open a pull request.

View file

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,1.6,,
Version,+,1.7,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -2580,8 +2580,14 @@ Variable,+,I_Circles_47x47,const Icon,
Variable,+,I_Clock_18x18,const Icon,
Variable,+,I_Connect_me_62x31,const Icon,
Variable,+,I_Connected_62x31,const Icon,
Variable,+,I_CoolHi_25x27,const Icon,
Variable,+,I_CoolHi_hvr_25x27,const Icon,
Variable,+,I_CoolLo_25x27,const Icon,
Variable,+,I_CoolLo_hvr_25x27,const Icon,
Variable,+,I_Cry_dolph_55x52,const Icon,
Variable,+,I_DFU_128x50,const Icon,
Variable,+,I_Dehumidify_25x27,const Icon,
Variable,+,I_Dehumidify_hvr_25x27,const Icon,
Variable,+,I_Detailed_chip_17x13,const Icon,
Variable,+,I_DolphinCommon_56x48,const Icon,
Variable,+,I_DolphinMafia_115x62,const Icon,
@ -2605,6 +2611,10 @@ Variable,+,I_FaceNopower_29x14,const Icon,
Variable,+,I_FaceNormal_29x14,const Icon,
Variable,+,I_GameMode_11x8,const Icon,
Variable,+,I_Health_16x16,const Icon,
Variable,+,I_HeatHi_25x27,const Icon,
Variable,+,I_HeatHi_hvr_25x27,const Icon,
Variable,+,I_HeatLo_25x27,const Icon,
Variable,+,I_HeatLo_hvr_25x27,const Icon,
Variable,+,I_InfraredArrowDown_4x8,const Icon,
Variable,+,I_InfraredArrowUp_4x8,const Icon,
Variable,+,I_InfraredLearnShort_128x31,const Icon,
@ -2622,6 +2632,8 @@ Variable,+,I_Mute_25x27,const Icon,
Variable,+,I_Mute_hvr_25x27,const Icon,
Variable,+,I_NFC_manual_60x50,const Icon,
Variable,+,I_Nfc_10px,const Icon,
Variable,+,I_Off_25x27,const Icon,
Variable,+,I_Off_hvr_25x27,const Icon,
Variable,+,I_Ok_btn_9x9,const Icon,
Variable,+,I_Ok_btn_pressed_13x13,const Icon,
Variable,+,I_Percent_10x14,const Icon,

1 entry status name type params
2 Version + 1.6 1.7
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
2580 Variable + I_Clock_18x18 const Icon
2581 Variable + I_Connect_me_62x31 const Icon
2582 Variable + I_Connected_62x31 const Icon
2583 Variable + I_CoolHi_25x27 const Icon
2584 Variable + I_CoolHi_hvr_25x27 const Icon
2585 Variable + I_CoolLo_25x27 const Icon
2586 Variable + I_CoolLo_hvr_25x27 const Icon
2587 Variable + I_Cry_dolph_55x52 const Icon
2588 Variable + I_DFU_128x50 const Icon
2589 Variable + I_Dehumidify_25x27 const Icon
2590 Variable + I_Dehumidify_hvr_25x27 const Icon
2591 Variable + I_Detailed_chip_17x13 const Icon
2592 Variable + I_DolphinCommon_56x48 const Icon
2593 Variable + I_DolphinMafia_115x62 const Icon
2611 Variable + I_FaceNormal_29x14 const Icon
2612 Variable + I_GameMode_11x8 const Icon
2613 Variable + I_Health_16x16 const Icon
2614 Variable + I_HeatHi_25x27 const Icon
2615 Variable + I_HeatHi_hvr_25x27 const Icon
2616 Variable + I_HeatLo_25x27 const Icon
2617 Variable + I_HeatLo_hvr_25x27 const Icon
2618 Variable + I_InfraredArrowDown_4x8 const Icon
2619 Variable + I_InfraredArrowUp_4x8 const Icon
2620 Variable + I_InfraredLearnShort_128x31 const Icon
2632 Variable + I_Mute_hvr_25x27 const Icon
2633 Variable + I_NFC_manual_60x50 const Icon
2634 Variable + I_Nfc_10px const Icon
2635 Variable + I_Off_25x27 const Icon
2636 Variable + I_Off_hvr_25x27 const Icon
2637 Variable + I_Ok_btn_9x9 const Icon
2638 Variable + I_Ok_btn_pressed_13x13 const Icon
2639 Variable + I_Percent_10x14 const Icon