How to canbus.send direct from lambda

Hi,

I’m trying to programmatically change the can_id, it’s not templatable, and you can’t use globals or variables it wants nothing but a int, which doesn’t work for me.

Options?
Is there any way to send CAN messages directly from lambda, eg without using canbus.send?
There is this, but not sure how to access it from lambda
https://esphome.io/api/canbus_8cpp_source.html
Any ideas?

# Normal way to send on CAN
interval:
  - interval: 1000ms
    then:
      - canbus.send:
          can_id: 0x359 #(want to be able to change by program, so var or similar)
          data: [ 0x10, 0x20, 0x30 ]

# instead something like
  - lambda:
      send.canbus(id, data);

Thanks

I think the code for the lambda should be something along these lines…

canbus:
  - platform: esp32_can
    id: cb
    tx_pin: GPIO5
    rx_pin: GPIO4
    can_id: 4
    bit_rate: 50kbps


button:
  - platform: template
    name: "button"
    id: test_btn
    on_press:
      - lambda: |-
          uint32_t 	can_id = 55;
          bool 	use_extended_id = 0;
          std::vector< uint8_t > data{ 0x10, 0x20, 0x30 };
          id(cb)->send_data(can_id, use_extended_id, data);
3 Likes

Thanks for the suggestion, it looking promising and compiles, I will give it a test.

Thanks again!

So my next question is how do I receive canbus messages in lambda?

I want to receive many can ids and then decide how to process them programmatically, there could be 100’s so I don’t want to have a seperate can id code for each, and it nots templatable!

I guess my question is how do I receive all can ids?

eg this does not work

canbus:
  - platform: esp32_can
    tx_pin: GPIO21
    rx_pin: GPIO22
    id: cb    
    can_id: 4
    bit_rate: 500kbps
    on_frame:
    - can_id: !lambda |-
        return {0x359};
      then:

Worked it out!

on_frame:
- can_id: 0
  can_id_mask: 0
2 Likes

Thanks for posting this! I was able to read all CAN IDs too using it :slight_smile:

canbus:
  - platform: esp32_can
    tx_pin: GPIO5
    rx_pin: GPIO6
    can_id: 4
    bit_rate: 500kbps
    tx_queue_len: 1 # default is 5 I believe - 1 should make it drop extras?? 
    rx_queue_len: 1
    on_frame:
      - can_id: 0  # listen to all messages
        can_id_mask: 0
        then:
          - logger.log:
              level: INFO
              format: "CAN ID: 0x%03x Data: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
              args: [ '(uint)can_id', '(uint)x[7]', '(uint)x[6]', '(uint)x[5]', '(uint)x[4]', '(uint)x[3]', '(uint)x[2]', '(uint)x[1]', '(uint)x[0]' ]