Ford Transit USA Forum banner
541 - 560 of 989 Posts
In other Van Assistant related news...

I've got most of the various MaxxFan IR codes working and all... but I'm realizing that the optimal way to implement this is going to be to change the ESPHome config to present the MaxxFan as a "fan component." And that, of course, is all new (again) to me.

For those who understand this, please help.

For those who do not, here's what I'm able to communcate: I've got each IR signal that the remote sends built in the ESP YAML - each command as a "button press." These show up in Home Assistant as "button entities" that can easily be dropped into cards as buttons. Meaning a LOT of buttons. I've also got a pull-down working for the ten OUT speeds and plan to build a pull-down for the ten IN speeds.

So that looks like this in VASS:
Image



All that is pretty ugly compared to if I were to get it to function as a "fan" in HASS. The fan component /seems/ like it's supposed to be able to send these commands from a pretty-ish "fan" element in HASS and then offer options for on/off/speed/in/out. The example in the docs shows this:
Image


So... I suspect I can do both at the same time, so I'm going to work on that. Feel free to point me in the right direction.

Here's the ESPHome YAML for the ESP360 for the MaxxFan so far (using buttons):
Code:
button:
  - platform: template
    name: "MaxxFan Power On"
    id: maxxfan_poweron
    icon: "mdi:fan"
    on_press:
      remote_transmitter.transmit_raw:
        code: [1687, -849, 827, -1675, 827, -840, 828, -1673, 826, -844, 827, -842, 1656, -846, 
        827, -2507, 6660, -2516, 827, -5848, 800, -1701, 5806, -870, 825, -1673, 801, -5039, 801, 
        -2532, 4974, -870, 1630, -1702, 801, -4207, 801, -3365, 4146, -866, 2459, -1708, 2484, 
        -1689, 1630, -3369, 799, -872, 800, -1702, 3315, -1688, 1629, -3378, 2459, -1709, 800, 
        -3373, 1629, -874, 798, -1701, 799, -8378, 799, -1702, 2483, -854, 1628, -1706, 6632, 
        -2543, 800, -873, 5801] 
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Power Off"
    id: maxxfan_poweroff
    icon: "mdi:fan-off"
    on_press:
      remote_transmitter.transmit_raw:
        code: [1686, -849, 827, -1676, 827, -840, 828, -1672, 826, -844, 826, -842, 1655, -847, 
        828, -2506, 6659, -2515, 801, -5873, 801, -1701, 5828, -844, 827, -1672, 826, 
        -5014, 801, -2531, 4975, -868, 1654, -1679, 800, -4207, 800, -3366, 4145, -866, 
        2458, -1708, 2459, -1714, 1630, -3369, 2484, -857, 4144, -1690, 1629, -3377, 
        2458, -1710, 800, -3372, 1629, -873, 799, -1701, 799, -8375, 800, -1701, 2459, 
        -879, 1628, -1706, 798, -872, 1628, -875, 2457, -2544, 798, -874, 5800]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Auto Out"
    id: maxxfan_autoout
    icon: mdi:fan-auto
    on_press:
      remote_transmitter.transmit_raw:
        code: [1688, -846, 828, -1673, 828, -838, 827, -1669, 828, -843, 828, -839, 1657, -843, 828, -2502, 6655, -2514, 828, -5840, 803, -1697, 5802, -866, 803, -1695, 802, -5035, 801, -2529, 4973, -865, 1629, -1701, 803, -4200, 801, -3364, 4143, -862, 2459, -1706, 2459, -1712, 1630, -3365, 1629, -1710, 801, -863, 2459, -1705, 1629, -878, 800, -863, 3311, -1687, 800, -1704, 800, -866, 1629, -872, 799, -1697, 801, -8368, 801, -1700, 2458, -876, 1603, -1728, 798, -1704, 775, -893, 2456, -2542, 773, -898, 5772
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Auto In"
    id: maxxfan_autoin
    icon: mdi:fan-auto
    on_press:
      remote_transmitter.transmit_raw:
        code: [1687, -847, 827, -1648, 852, -814, 852, -1670, 828, -840, 828, -840, 1656, -820, 852, -2502, 6654, -2514, 802, -5866, 801, -1698, 5801, -867, 801, -1696, 801, -5033, 802, -2529, 4971, -867, 1629, -1700, 801, -4203, 800, -3363, 4141, -865, 2458, -1706, 2482, -1688, 1628, -3366, 1628, -877, 1627, -872, 2456, -1709, 1627, -878, 774, -890, 3286, -1738, 773, -1728, 773, -869, 1603, -897, 773, -1726, 797, -8396, 747, -1751, 2430, -879, 1601, -1755, 748, -3397, 2429, -2593, 747, -923, 5746
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Off Open"
    id: maxxfan_offopen
    icon: mdi:fan-off
    on_press:
      remote_transmitter.transmit_raw:
        code: [1687, -846, 828, -1672, 829, -838, 828, -1668, 829, -842, 828, -839, 1657, -844, 828, -2501, 6656, -2513, 828, -5840, 828, -1672, 5802, -867, 801, -1695, 802, -5035, 802, -2528, 4972, -865, 1630, -1702, 801, -4200, 801, -3363, 4144, -862, 2458, -1707, 2458, -1712, 1629, -3366, 3313, -859, 3311, -1684, 1628, -879, 798, -867, 3284, -1714, 798, -1705, 773, -893, 1601, -899, 773, -1724, 773, -8397, 773, -1752, 2404, -929, 1577, -1754, 747, -922, 748, -922, 746, -918, 1576, -2587, 747, -923, 5746
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Auto Out 65F"
    id: maxxfan_auto65f
    icon: mdi:fan-auto   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1684, -821, 853, -1672, 801, -841, 851, -1644, 852, -843, 827, -838, 1657, -844, 828, -2502, 6654, -2512, 827, -5816, 851, -1672, 5826, -841, 802, -1694, 827, -5009, 826, -2504, 4971, -864, 1655, -1675, 828, -4173, 802, -3362, 4142, -861, 2459, -1706, 2458, -1711, 1629, -3363, 1631, -3372, 2484, -1678, 2485, -852, 1630, -1704, 801, -1694, 801, -872, 4141, -855, 800, -1697, 800, -8366, 800, -1700, 2457, -876, 1629, -1701, 800, -2538, 1629, -4197, 825, -845, 5772
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Auto Out 70F"
    id: maxxfan_auto70f
    icon: mdi:fan-auto   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1712, -819, 828, -1648, 852, -814, 851, -1669, 828, -817, 853, -839, 1656, -819, 853, -2501, 6655, -2512, 828, -5816, 851, -1672, 5826, -840, 829, -1668, 827, -5010, 802, -2527, 4996, -840, 1655, -1677, 825, -4175, 825, -3338, 4170, -835, 2458, -1707, 2483, -1686, 1655, -3338, 1655, -3346, 2484, -1679, 2510, -827, 1630, -1706, 800, -1694, 1655, -1680, 2484, -849, 801, -1696, 801, -8366, 801, -1700, 2458, -874, 1629, -1701, 4996, -4170, 801, -869, 5799
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Auto Out 75F"
    id: maxxfan_auto75f
    icon: mdi:fan-auto   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1686, -847, 828, -1671, 827, -839, 828, -1668, 829, -841, 827, -839, 1656, -844, 828, -2502, 6654, -2512, 802, -5865, 827, -1672, 5826, -841, 827, -1669, 828, -5007, 826, -2503, 4971, -867, 1654, -1674, 827, -4175, 827, -3336, 4142, -863, 2458, -1704, 2483, -1688, 1630, -3361, 1630, -3372, 2458, -1707, 2509, -826, 1630, -1706, 801, -1694, 800, -1700, 801, -867, 1628, -871, 801, -1696, 800, -8367, 800, -1699, 2457, -876, 1628, -1702, 799, -869, 800, -1701, 800, -4195, 799, -870, 5798
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan Auto Out 80F"
    id: maxxfan_auto80f
    icon: mdi:fan-auto   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1686, -847, 828, -1671, 827, -815, 851, -1670, 802, -866, 828, -839, 1656, -844, 828, -2501, 6653, -2512, 827, -5839, 803, -1697, 5799, -867, 802, -1694, 826, -5008, 825, -2503, 4996, -841, 1656, -1673, 802, -4200, 802, -3359, 4143, -864, 2457, -1705, 2484, -1684, 1630, -3363, 1629, -1708, 801, -864, 2483, -1680, 2485, -852, 1628, -1707, 801, -1692, 4142, -860, 801, -866, 801, -1696, 800, -8366, 799, -1699, 2457, -876, 1629, -1702, 1628, -7535, 799, -871, 5797
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 10% Out"
    id: maxxfan_out10
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1683, -845, 828, -1646, 855, -837, 830, -1666, 829, -842, 829, -811, 1684, -818, 854, -2501, 6656, -2485, 854, -5812, 829, -1674, 5851, -839, 830, -1668, 829, -5006, 829, -2501, 4973, -863, 1658, -1673, 827, -4173, 830, -3334, 4170, -834, 2486, -1681, 2484, -1684, 1658, -3336, 828, -817, 853, -1670, 829, -838, 1683, -1647, 1632, -849, 855, -833, 3341, -1657, 829, -1649, 829, -862, 1657, -844, 802, -1671, 827, -8340, 852, -1672, 2487, -821, 1683, -1672, 4172, -1665, 828, -2502, 802, -867, 5828
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 20% Out"
    id: maxxfan_out20
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1684, -846, 828, -1670, 830, -839, 803, -1693, 829, -816, 855, -810, 1685, -840, 831, -2500, 6682, -2486, 831, -5837, 830, -1644, 5854, -840, 830, -1642, 855, -5007, 829, -2501, 4999, -837, 1658, -1672, 830, -4172, 829, -3335, 4170, -836, 2485, -1679, 2485, -1684, 1632, -3361, 803, -867, 828, -1672, 3340, -1655, 2514, -825, 827, -839, 2485, -1678, 803, -1701, 803, -864, 1630, -869, 802, -1695, 802, -8366, 827, -1673, 2485, -849, 1631, -1698, 1631, -2539, 2484, -2512, 802, -868, 5801
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 30% Out"
    id: maxxfan_out30
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1656, -846, 804, -1695, 829, -838, 829, -1643, 829, -865, 828, -816, 1759, -764, 854, -2453, 6704, -2460, 854, -5842, 854, -1620, 5932, -760, 804, -1693, 830, -5005, 854, -2476, 5001, -836, 1658, -1672, 803, -4200, 828, -3335, 4171, -836, 2484, -1678, 2487, -1683, 1685, -3309, 828, -842, 828, -1645, 3366, -1658, 1657, -3346, 2459, -1705, 826, -1675, 828, -839, 1658, -842, 831, -1667, 827, -8340, 828, -1670, 2511, -822, 1657, -1674, 2514, -825, 3341, -2487, 803, -868, 5826
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 40% Out"
    id: maxxfan_out40
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1685, -823, 851, -1670, 830, -837, 828, -1669, 828, -842, 828, -839, 1630, -844, 828, -2526, 6656, -2511, 829, -5838, 855, -1619, 5852, -840, 830, -1640, 855, -5008, 803, -2527, 4973, -862, 1658, -1672, 829, -4173, 856, -3282, 4196, -810, 2509, -1653, 2511, -1658, 1684, -3312, 853, -840, 855, -1620, 3366, -1655, 3341, -829, 829, -813, 1708, -1622, 852, -1677, 828, -811, 1683, -818, 853, -1668, 854, -8288, 855, -1672, 2511, -798, 1680, -1673, 1658, -845, 1656, -1652, 828, -2526, 804, -840, 5854
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 50% Out"
    id: maxxfan_out50
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1655, -846, 802, -1700, 824, -843, 828, -1667, 829, -842, 855, -810, 1682, -794, 852, -2501, 6656, -2511, 831, -5838, 853, -1622, 5852, -814, 882, -1615, 880, -4983, 825, -2504, 4996, -839, 1631, -1701, 855, -4120, 854, -3335, 4196, -810, 2459, -1706, 2485, -1660, 1707, -3285, 829, -867, 828, -1672, 3368, -1605, 1682, -850, 1630, -1700, 1656, -1672, 856, -1648, 830, -836, 1631, -870, 801, -1695, 826, -8341, 829, -1672, 2486, -848, 1630, -1700, 3340, -830, 828, -837, 830, -2475, 856, -839, 5828
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 60% Out"
    id: maxxfan_out60
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1630, -848, 852, -1671, 829, -839, 802, -1694, 803, -869, 798, -866, 1630, -869, 828, -2503, 6655, -2512, 802, -5866, 827, -1648, 5877, -814, 829, -1644, 878, -4981, 828, -2503, 4973, -862, 1659, -1673, 832, -4144, 828, -3361, 4169, -836, 2486, -1679, 2511, -1659, 1657, -3336, 804, -866, 827, -1648, 3365, -1631, 2537, -3301, 1680, -1673, 828, -1652, 852, -814, 1708, -792, 880, -1641, 830, -8338, 827, -1673, 2486, -849, 1657, -1671, 1656, -1683, 1657, -839, 828, -2478, 852, -843, 5854
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 70% Out"
    id: maxxfan_out70
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1685, -845, 828, -1674, 802, -839, 828, -1694, 854, -816, 828, -839, 1657, -818, 853, -2501, 6656, -2514, 829, -5813, 855, -1671, 5828, -840, 828, -1645, 852, -5009, 829, -2502, 5000, -837, 1631, -1700, 828, -4173, 829, -3336, 4169, -836, 2486, -1679, 2485, -1686, 1683, -3310, 803, -867, 802, -1698, 3340, -1658, 1656, -1681, 2486, -849, 803, -1693, 828, -1673, 803, -864, 1631, -868, 829, -1669, 828, -8340, 803, -1697, 2486, -849, 1655, -1675, 2484, -2519, 827, -3336, 802, -867, 5802
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 80% Out"
    id: maxxfan_out80
    icon: mdi:fan-chevron-up   
    on_press:
      remote_transmitter.transmit_raw:
        code: [1686, -845, 828, -1647, 853, -814, 879, -1642, 829, -841, 830, -836, 1659, -818, 851, -2504, 6656, -2511, 829, -5840, 830, -1669, 5802, -865, 829, -1669, 828, -5007, 830, -2501, 4998, -839, 1657, -1673, 828, -4174, 803, -3361, 4145, -861, 2485, -1680, 2485, -1684, 1633, -3361, 828, -843, 828, -1670, 3341, -1657, 4169, -835, 829, -840, 802, -1692, 828, -1676, 803, -863, 1632, -869, 802, -1695, 827, -8342, 801, -1700, 2484, -849, 1657, -1673, 1631, -872, 802, -865, 1631, -3366, 801, -869, 5800
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 90% Out"
    id: maxxfan_out90
    icon: mdi:fan-chevron-up
    on_press:
      remote_transmitter.transmit_raw:
        code: [1710, -820, 829, -1647, 853, -839, 828, -1668, 804, -866, 827, -841, 1656, -845, 828, -2500, 6654, -2514, 803, -5866, 828, -1671, 5828, -840, 803, -1695, 802, -5034, 829, -2502, 4971, -865, 1631, -1701, 801, -4200, 802, -3363, 4144, -861, 2483, -1682, 2459, -1711, 1656, -3339, 825, -844, 776, -1723, 3314, -1685, 1628, -877, 802, -1695, 800, -869, 802, -1694, 800, -1702, 802, -864, 1631, -870, 799, -1698, 801, -8368, 800, -1700, 2485, -849, 1630, -1700, 5801, -3367, 801, -871, 5798
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 100% Out"
    id: maxxfan_out100
    icon: mdi:fan-chevron-up
    on_press:
      remote_transmitter.transmit_raw:
        code: [1683, -820, 827, -1672, 829, -838, 828, -1668, 827, -842, 856, -812, 1631, -868, 828, -2503, 6656, -2512, 828, -5840, 856, -1643, 5827, -842, 854, -1644, 802, -5033, 828, -2502, 4999, -813, 1656, -1674, 855, -4148, 852, -3336, 4199, -806, 2513, -1654, 2484, -1684, 1658, -3337, 827, -842, 830, -1644, 829, -838, 1682, -1674, 2535, -803, 1655, -1679, 853, -1640, 829, -1675, 854, -813, 1683, -815, 804, -1694, 855, -8313, 827, -1673, 2537, -772, 1681, -1674, 1630, -3373, 829, -3332, 804, -868, 5853        
                ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
  - platform: template 
    name: "MaxxFan 100% In"
    id: maxxfan_in100
    icon: mdi:fan-chevron-down
    on_press:
      remote_transmitter.transmit_raw:
        code: [1686, -846, 828, -1650, 851, -838, 827, -1669, 829, -842, 827, -815, 1681, -843, 827, -2503, 6655, -2513, 802, -5866, 827, -1672, 5801, -867, 802, -1695, 828, -5009, 801, -2529, 4972, -864, 1630, -1701, 801, -4201, 800, -3364, 4142, -863, 2456, -1708, 2458, -1712, 1627, -3367, 799, -870, 1629, -871, 801, -866, 1627, -1728, 2457, -856, 1602, -1733, 798, -1696, 799, -1730, 748, -919, 1575, -899, 772, -1751, 747, -8420, 747, -1753, 2405, -929, 1575, -1754, 1576, -927, 748, -1753, 746, -3416, 746, -900, 5795
        ]
        transmitter_id: 'IR_TX'
        repeat:
          times: 1
          wait_time: 16ms
        carrier_frequency: 38kHz
 
@gregoryx : I had a similar issue converting a fireplace to a fan component. The core pieces are: the Fan component, an output template, and a script, which allows the previous request to finish (queue) before moving to the next attempt to set the state on a physical object. In your case, you would probably just be doing a large if statement inside the script for each power level with the associated IR codes.

YAML:
substitutions:
  device_name: fireplace
  friendly_name: Fireplace

packages:
  hardware: !include common/hardware/kincony-kc868-a4.yaml
  common: !include common/common.yaml
logger:
  level: DEBUG

globals:
  - id: fireplace_level
    type: float
    restore_value: no
    initial_value: "0.00"

output:
  - platform: template
    id: fireplace
    type: float
    write_action:
      - script.execute:
          id: set_fireplace_state
          level: !lambda return state;
wifi:
  power_save_mode: none

script:
  - id: set_fireplace_state
    mode: queued  # this allows subsequent requests to stack so that
                  # the fireplace doesn't lose track of current state
    parameters:
      level: float               
    then:
      - if: # Check if we need to turn it off
          condition:
            lambda: return level == 0;
          then: # turn off fireplace
            - logger.log: "Turning off fireplace..."
            - lambda: id(fireplace_state).publish_state("Turning Off");
            # Explicit setting of all relays each time for safety
            - switch.turn_on: relay1
            - switch.turn_on: relay2
            - switch.turn_on: relay3
            - delay: 1 sec
            - switch.turn_off: relay1
            - switch.turn_off: relay2
            - switch.turn_off: relay3
            - delay: 60 sec # (to try 50)
            - logger.log: "Fireplace off."
            - lambda: id(fireplace_level) = 0.0;
            - lambda: id(fireplace_state).publish_state("Off");
          else:
            - if: # turn on fireplace if needed
                condition:
                  lambda: return id(fireplace_level) == 0.0;
                then:
                  - logger.log: "Turning on fireplace..."
                  - lambda: id(fireplace_state).publish_state("Turning On");
                  #- rtttl.play: 'LightMyF:d=16,o=5,b=140:8b6,g6,a6,8b6,8d7,8c7,8b6,8a6,8g6,8a6,f6,a6,8c7,8f7,d7,c7,a#6,g6,8g#6,8g6,8g#6,g6,a6,8b6,8c#7,b6,a6,g6,f6,8e6,8f6,1a6'
                  - switch.turn_off: relay1
                  - switch.turn_on:  relay2
                  - switch.turn_off: relay3
                  - delay: 2 sec
                  - switch.turn_off: relay1
                  - switch.turn_off: relay2
                  - switch.turn_off: relay3
                  - delay: 30 sec
                  # start with fireplace on max in order to make sure it lights
                  - switch.turn_on:  relay1
                  - switch.turn_off: relay2
                  - switch.turn_off: relay3
                  - delay: 13 sec # extra second just to make sure
                  - switch.turn_off: relay1
                  - switch.turn_off: relay2
                  - switch.turn_off: relay3
                  - delay: 1 sec # Allow time to register the all off
                  - lambda: id(fireplace_level) = 1.0;
                  - lambda: id(fireplace_state).publish_state("On");
                  - logger.log: "Fireplace on."
                  
            # finally turn the knob to set level
          
            - if:  # we have to turn the fireplace up
                condition:
                  lambda: return id(fireplace_level) - level < 0.0;
                then:
                  - lambda: id(fireplace_state).publish_state("Turning Up");
                  - switch.turn_on:  relay1
                  - switch.turn_off: relay2
                  - switch.turn_off: relay3
            - if: # we have to turn the fireplace down
                condition:
                  lambda: return id(fireplace_level) - level > 0.0;
                then:
                  - lambda: id(fireplace_state).publish_state("Turning Down");
                  - switch.turn_off: relay1
                  - switch.turn_off: relay2
                  - switch.turn_on:  relay3
            # wait to arrive at desired level
            # Note: 12 seconds is the time it takes to sweep from min to max
            - delay: !lambda "return 12000 * fabs(id(fireplace_level) - level);"
            - switch.turn_off: relay1
            - switch.turn_off: relay2
            - switch.turn_off: relay3
            - lambda: id(fireplace_level) = level;
            - lambda: id(fireplace_state).publish_state("On");


fan:
  - platform: speed
    output: fireplace
    name: "Fireplace"
    #restore_mode: ALWAYS_OFF # Don't wan't to assume state


text_sensor:
  - platform: template
    id: fireplace_state
    name: Fireplace State

dallas:
  - pin: 13
    update_interval: 15s

# Individual sensors
sensor:
  - platform: dallas
    address: 0x270301979406c828
    id: ${device_name}_ambient_temp
    name: "${friendly_name} Ambient Temp"
    filters:
      - lambda: return x * (9.0/5.0) + 32.0;
    unit_of_measurement: "°F"
    on_value:
      then:
        - lambda: id(temp_diff).publish_state(fabs(id(${device_name}_ambient_temp).state - id(${device_name}_temp).state));

  - platform: dallas
    address: 0x3d030797941f8528
    id: ${device_name}_temp
    name: "${friendly_name} Temp"
    filters:
      - lambda: return x * (9.0/5.0) + 32.0;
    unit_of_measurement: "°F"
    on_value:
      then:
        - lambda: id(temp_diff).publish_state(fabs(id(${device_name}_ambient_temp).state - id(${device_name}_temp).state));
        - lambda: id(fireplace_temp_median).publish_state(id(${device_name}_temp).state);
        - lambda: id(fireplace_temp_change).publish_state(id(${device_name}_temp).state - id(fireplace_temp_median).state);


  - platform: template
    name: "${friendly_name} Temp Diff"
    id: temp_diff
    update_interval: 60s
    unit_of_measurement: "°F"

  - platform: template
    name: "${friendly_name} Median"
    id: fireplace_temp_median
    filters:
      - median:
          window_size: 7 # pulls from the middle one every 15 seconds, so it is roughly a 1 minute lag
          send_every: 1
    unit_of_measurement: "°F"

  - platform: template
    name: "${friendly_name} Temperature Change"
    id: fireplace_temp_change
    unit_of_measurement: "°F"

switch:
  - platform: gpio
    id: relay1
    name: relay1
    pin: 2
  - platform: gpio
    id: relay2
    name: relay2
    pin: 15
  - platform: gpio
    id: relay3
    name: relay3
    pin: 5
  - platform: gpio
    id: relay4
    name: relay4
    pin: 4


binary_sensor:
  - platform: template
    name: "Fireplace Lit"
    id: fireplace_lit
    lambda: |-
      if (id(fireplace_temp_change).state > 4.0 || id(${device_name}_temp).state > 150.0 ) {
        return true;
      } else if (id(fireplace_temp_change).state < -2.0 ) {
        return false;
      } else {
        return {};
      }
  - platform: gpio
    name: "input1"
    pin:
      number: 36
      inverted: true
  - platform: gpio
    name: "input2"
    pin:
      number: 39
      inverted: true
  - platform: gpio
    name: "input3"
    pin:
      number: 27
      inverted: true
  - platform: gpio
    name: "input4"
    pin:
      number: 14
      inverted: true
 
@gregoryx : I had a similar issue converting a fireplace to a fan component. The core pieces are: the Fan component, an output template, and a script, which allows the previous request to finish (queue) before moving to the next attempt to set the state on a physical object. In your case, you would probably just be doing a large if statement inside the script for each power level with the associated IR codes.
...
Great guidance, @Tuckie. I'll look it over.

I may be wrong, but I think the "smartir" function includes a "fan" element that changes how things work - turns them into some sort of unique-ish device - and segregates the IR codes into a separate file. But all the examples for it are using the Broadcom IR and I haven't found an example of how it works with ESPHome - they're different.

I'm going to study your code to try to understand this, "lamda," thing... 🤔
 
I'm going to study your code to try to understand this, "lamda," thing... 🤔
I'm guessing that you already understand this, but for the benefit of anyone who doesn't:

In HASS and ESPhome, "Lambda" is an instruction to the interpreter of their ridiculous YAML-based programming language. What it does is to let you insert an arbitrary chunk of C++ code at a particular point in the flow of the program that you are struggling to express in YAML. You do this in the common case in which some operation you need is missing from the YAML version of some operator. You also do it when you can no longer stand the absurd syntax that is foisted on you by virtue of trying to use a markup language (YAML) to do the job of a programming language. For example, doing complex if/then/else structures in YAML will drive you crazy, so you can revert to the C syntax involving nested curly-brackets which, although not great, is a lot better than YAML.

In many contexts, a LAMBDA is passed a parameter in the creatively-named variable "x". You can optionally return a value using the "return" in the c++ code. If you don't use a return in a YAML context that expects one, you will get a useful error message. In essence, a LAMBDA is an anonymous (i.e., has no name) in-line function (hence the name).

I am a little hazy as to the rules for local variables in LAMBDAs, but I do know that they are locally scoped in each LAMBDA. You can get around this by declaring GLOBALs that share state among all LAMBDAs. You don't do this in a LAMBDA, though--you do it in the enclosing YAML, typically up near the top. When I need state, I usually just declare a bunch of GLOBALs and be done with it. Probably bad programming practice, but it keeps me sane.

Finally, note that the YAML interpreter doesn't know much about C++, so it mostly treats the C code as an opaque string. This leads to strange error messages, when the C code is finally interpreted later in the process.

In summary, LAMBDAs are often absolutely necessary, and are confusing because you end up with one piece of code that contains the syntax of two completely different languages.

Did I mention that I hate YAML?
 
I'm guessing that you already understand this, but for the benefit of anyone who doesn't:
Nope. I don't understand this at ALL. So I'm really grateful that you're explaining it. 😄


In HASS and ESPhome, "Lambda" is an instruction to the interpreter of their ridiculous YAML-based programming language. What it does is to let you insert an arbitrary chunk of C++ code at a particular point in the flow of the program that you are struggling to express in YAML. You do this in the common case in which some operation you need is missing from the YAML version of some operator. You also do it when you can no longer stand the absurd syntax that is foisted on you by virtue of trying to use a markup language (YAML) to do the job of a programming language. For example, doing complex if/then/else structures in YAML will drive you crazy, so you can revert to the C syntax involving nested curly-brackets which, although not great, is a lot better than YAML.

In many contexts, a LAMBDA is passed a parameter in the creatively-named variable "x". You can optionally return a value using the "return" in the c++ code. If you don't use a return in a YAML context that expects one, you will get a useful error message. In essence, a LAMBDA is an anonymous (i.e., has no name) in-line function (hence the name).

I am a little hazy as to the rules for local variables in LAMBDAs, but I do know that they are locally scoped in each LAMBDA. You can get around this by declaring GLOBALs that share state among all LAMBDAs. You don't do this in a LAMBDA, though--you do it in the enclosing YAML, typically up near the top. When I need state, I usually just declare a bunch of GLOBALs and be done with it. Probably bad programming practice, but it keeps me sane.

Finally, note that the YAML interpreter doesn't know much about C++, so it mostly treats the C code as an opaque string. This leads to strange error messages, when the C code is finally interpreted later in the process.

In summary, LAMBDAs are often absolutely necessary, and are confusing because you end up with one piece of code that contains the syntax of two completely different languages.

Did I mention that I hate YAML?
This is actually very helpful to me. I haven't written "code" in a couple decades; but I've dealt with Javascript and HTML and stuff like that to deal with Raspberry Pi and Home Automation projects. Your explanation of what YAML and Lambdas are jibes with what I've been struggling with: things like arrays and if... then / while... do sort of stuff still cause me crazy headaches because it just doesn't make sense compared to anything I've done before. And Lambdas just sounded like an even worse version of the same. So... the way you describe Lambdas as actual C code will help me understand it better.

If it isn't obvious yet, I really struggle with understanding the code stuff... but if I can find enough examples and get moderate error-code feedback, I can often stumble my way through it to a functional state - if typically rather weak execution.

I realized after gathering many of the MaxxFan RAW IR codes into functional "buttons" in the ESPHome YAML (that work as expected in Home Assistant), that actually making these things usable in the UI wouldn't be pretty. So I looked at things I've already learned with HASS to see which could help bridge the function-to-form gap. Pull-downs are the only thing in my bag-o-tricks so far that would present one UI interaction with 10+ options in the pull-down.

Then I decided to search for other options. And came across the Smart IR Integration, which - if I'm understanding it correctly - segregates the IR/RF codes into a single pre-set format JSON file that then has a more limited pre-set format YAML to ultimately present what appears to be a well-integrated "device" to be controlled.

But it has some of this "Lambda" stuff as one problem. And very few examples using ESPHome / RAW codes. So that's what I'm trying to understand now. I'm going to keep spending hours on this until I can either produce some success or give up (for now). "Success" /should/ result in a single JSON file with all the IR codes in it AND a YAML for the MaxxFan that should both be usable by anyone else and /should/ look like the pretty interface that such a fan deserves.

So... thanks, again, for the useful rant / help! 😁
 
One possible annoyance that anyone who uses my YAML may or may not like is I'm keeping with "mvictron" in everything, which was initially to differentiate from the previous "victron" stuff. I'm fine with it, so I'm leaving it that way.
I've been messing around with your files and making some tweaks. In my testing, unique_id is really meant to be an ID. I'm using IDs generated by this site, Cuid2 Generator | Generate Cuid2s online | uuid.lol

The entity id, that you use elsewhere in your config (like dashboards), is a combination of the Device name and the sensor name.
The Model shows up in the Device Info as does the Manufacturer.


Image
 
I've been messing around with your files and making some tweaks. In my testing, unique_id is really meant to be an ID. I'm using IDs generated by this site, Cuid2 Generator | Generate Cuid2s online | uuid.lol

The entity id, that you use elsewhere in your config (like dashboards), is a combination of the Device name and the sensor name.
The Model shows up in the Device Info as does the Manufacturer.


View attachment 201349
Guessing there's a better / simpler way to do it?

I started using the id field because there were some things that didn't work the same without a unique_id. Can't remember what now. But I couldn't see the benefit to it being randomized. I don't /think/ it gets used in the GUI really - as you point out - but I don't see the benefit for a random-ish id. Is there one?

That bottom part for the "device", I didn't use at first but then thought it was convenient / nice to have the devices show up in a group, basically. That part is definitely optional. But maybe it serves that additional case you're showing of making the GUI name better?

I'm open to whatever works - and clearly still not understanding WHY it works on a lot of this.
 
but I don't see the benefit for a random-ish id. Is there one?
As a card-carrying member of the Church of the UUID, I will chime in here:

Every digital object in the world (literally) should have a UUID, and they should all be semantics-free meaningless numbers (with a sufficiently-large random number being more than adequate). The more random an identifier is, the less likely it is to accidentally clash with some other identifier. Meaningful names are very un-random and so are dangerous.

The advantage of meaning-free UUIDs is that they clearly distinguish "indentifiers" from "names". By separating the name of a digital object (which can change) from its identity (which can't), the problem of links and other external references breaking due to somebody changing a name sowewhere is solved once and for all. If everything has an unambiguous identity independent of its name, vastly-distributed systems with decentralized management start to become tractable. I believe this as strongly as I believe anything in tech.

Now, I admit that this borders on philosophy ("architecture", actually), and that I am not always as careful as my beliefs would dictate, but this is one thing that the HASS devs got right. If everything has a unique and permanent identity that is never changed or reused, it will be a Happy Situation.
 
To answer @gregoryx, yeah what @brío said, it feels more correct to me (I work in software).
Using proper UUIDs is also what HA does when it creates things (see automations.yaml).
But yes, you can use anything you want, as long as it is unique, you're not wrong.

It did help me sort out what what going on, when I knew the ID was not part of the name, because originally, I thought they were the entity_ids.

I'm now working on the device section and the entity names a bit more to get things a little cleaner.
Specifically, only putting "Victron" in the manufacturer property.

I am also trying to think through a "device" schema which lines up better with the actual devices I have.
Even in the hass-victron HACS integration, I didn't like the devices.
When I look at some of the payloads in MQTT Explorer, it will say if it is from my Lynx Smart BMS not the Cerbo GX for example.

I do think this is 100% the right path now which is great!
When I'm a little further along, I'll make a clear how-to, because I stumbled a lot with the initial setup.
 
Just wanted to thank everyone again here and in particular @gregoryx for all the work on the Victron MQTT stuff. I got fed up with the HASS plugin/modbus stuff being flaky and now am using the MQTT stuff and it appears stable so far. Having that big YAML file from @gregoryx sure saved me a lot of time!
 
...
Every digital object in the world (literally) should have a UUID, and they should all be semantics-free meaningless numbers (with a sufficiently-large random number being more than adequate). The more random an identifier is, the less likely it is to accidentally clash with some other identifier. Meaningful names are very un-random and so are dangerous.

The advantage of meaning-free UUIDs is that they clearly distinguish "indentifiers" from "names". By separating the name of a digital object (which can change) from its identity (which can't), the problem of links and other external references breaking due to somebody changing a name sowewhere is solved once and for all. If everything has an unambiguous identity independent of its name, vastly-distributed systems with decentralized management start to become tractable. I believe this as strongly as I believe anything in tech.
...
...
It did help me sort out what what going on, when I knew the ID was not part of the name, because originally, I thought they were the entity_ids.
...
Great explanation. I agree. I have encountered this problem. It is, of course, part of why my MQTT Victron stuff is named, "mvictron" to differentiate them for my initial testing. In hind-sight, this would have kept some of my renaming mess much simpler. I wasn't appreciating the value of a non-categoric name - even as I've had to rebuild dashboards and such. 🤣

Thanks for the thorough explanation, gents. (y)
 
Just wanted to thank everyone again here and in particular @gregoryx for all the work on the Victron MQTT stuff. I got fed up with the HASS plugin/modbus stuff being flaky and now am using the MQTT stuff and it appears stable so far. Having that big YAML file from @gregoryx sure saved me a lot of time!
I'm glad to hear someone else is testing it all!

How hard was the search-and-replace part to get everything working?

Did you change much else in it? Find any errors or anything like that? Or just better ways to do things, as @Captadv did?

I feel like I'm less committed to what I have now... willing to be flexible and change things and/or dump the database if necessary... so this is still a good time for me to change things.
 
Discussion starter · #553 ·
With my van finally scheduled for production I’m getting ready to pull the plug for some hardware to house Home Assistant.
Well, I ended up getting the Home Assistant Yellow kit. The RPi CM4 module should be here in a few days and then I can put everything together and install the HA software.
Image
 
Well, I ended up getting the Home Assistant Yellow kit. The RPi CM4 module should be here in a few days and then I can put everything together and install the HA software.
That's what I'm running on as well.
 
Discussion starter · #557 ·
Are you using the SSM on the CM4 or a standalone SSD module on the Yellow board?
I decided to start with 32GB of eMMC so I purchased a CM4 with 4GB of RAM and 32GB of eMMC without wireless. Minimum requirements per HA is 2GB RAM and 16GB eMMC (no wireless). My thinking was I can add the SSD later if needed. If I need Bluetooth I'll add an ESPHome board.
 
I'm glad to hear someone else is testing it all!

How hard was the search-and-replace part to get everything working?

Did you change much else in it? Find any errors or anything like that? Or just better ways to do things, as @Captadv did?

I feel like I'm less committed to what I have now... willing to be flexible and change things and/or dump the database if necessary... so this is still a good time for me to change things.
Search-and-replace was very easy!
Didn't change much - I think the only error I noticed is a typo in some payloads that were originally '{"value": 4 }' and I changed them to '{"value": 4}' (notice the lack of space before the digit). That allowed homeassistant to display the current state of the switch. Other than that I think it all just worked great as-is.
 
541 - 560 of 989 Posts