Help with custom 'light' component - does not name a type

Hey folks. I really appreciate the help here.

I’m trying to get this library to work with ESPHome. I’m trying to follow GitHub - jesserockz/esphome-external-component-examples to create a custom component that calls the library.

Before I even started to import the library I wanted to get the basic “empty_light” example to work. So I have the following setup:

device.yaml

substitutions:
  device_name: office-test-1

esphome:
  name: ${device_name}
  platform: ESP32
  board: esp32dev

<<: !include .base-basic.yaml

external_components:
  - source:
      type: local
      path: custom_components

light:
  - platform: p9813_light
    name: Empty light
    output: pwm_output

output:
  - platform: ledc
    pin: GPIO19
    frequency: 1000 Hz
    id: pwm_output

And I have three files created:

/config/esphome/custom_components/p9813_light/light.py

import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import light, output
from esphome.const import CONF_OUTPUT_ID, CONF_OUTPUT

namespace = cg.esphome_ns.namespace('p9813_light')
P9813LightOutput = namespace.class_('P9813LightOutput', light.LightOutput)

CONFIG_SCHEMA = light.BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend({
    cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(P9813LightOutput),
    cv.Required(CONF_OUTPUT): cv.use_id(output.FloatOutput)
})

def to_code(config):
    var = cg.new_Pvariable(config[CONF_OUTPUT_ID])
    yield light.register_light(var, config)

    out = yield cg.get_variable(config[CONF_OUTPUT])
    cg.add(var.set_output(out))

/config/esphome/custom_components/p9813_light/p9813_light.h

#pragma once

#include "esphome/core/component.h"
#include "esphome/components/output/float_output.h"
#include "esphome/components/light/light_output.h"

namespace esphome {
    namespace p9813_light {
        
        class P9813LightOutput : public light::LightOutput, public Component {
         public:
          void setup() override;
          light::LightTraits get_traits() override;
          void set_output(output::FloatOutput *output) { output_ = output; }
          void write_state(light::LightState *state) override;
          void dump_config() override;
         
         protected:
          output::FloatOutput *output_;
        };
    
    }
}

/config/esphome/custom_components/p9813_light/p9813_light.cpp

#include "esphome/core/log.h"
#include "p9813_light.h"

namespace esphome {
    namespace p9813_light {
    
        static const char *TAG = "p9813_light.light";
        
        void P9813LightOutput::setup() {
           
        }
        
        light::LightTraits P9813LightOutput::get_traits() {
            auto traits = light::LightTraits();
            traits.set_supports_brightness(true);
            traits.set_supports_rgb(false);
            traits.set_supports_rgb_white_value(false);
            traits.set_supports_color_temperature(false);
        
            return traits;
        }
        
        void P9813LightOutput::write_state(light::LightState *state) {
        
        }
        
        void P9813LightOutput::dump_config(){
            ESP_LOGCONFIG(TAG, "p9813 custom light");
        }
    
    }
} 

When I compile I get:

src/main.cpp:37:1: error: 'p9813_light' does not name a type
 p9813_light::P9813LightOutput *p9813_light_p9813lightoutput;
 ^~~~~~~~~~~
/config/esphome/testing-1.yaml: In function 'void setup()':
/config/esphome/testing-1.yaml:236:3: error: 'p9813_light_p9813lightoutput' was not declared in this scope
/config/esphome/testing-1.yaml:236:38: error: 'p9813_light' does not name a type
*** [.pioenvs/h-office-test-1/src/main.cpp.o] Error 1

I keep thinking this is due to some typo I’ve made but I can’t spot it. Help?

Alright. After a day or so to come back to this fresh I made some progress.

First: you need a __init__.py file in the root of each custom component’s folder.

Second: set_supports_X is deprecated. Use traits.set_supported_color_modes({light::ColorMode::BRIGHTNESS}); (for example) instead.