{"id":3941,"date":"2024-02-03T19:36:52","date_gmt":"2024-02-03T17:36:52","guid":{"rendered":"https:\/\/mummila.net\/nuudelisoppa\/?p=3941"},"modified":"2024-02-03T19:36:52","modified_gmt":"2024-02-03T17:36:52","slug":"notes-as-i-go-my-attempt-to-develop-a-home-assistant-integration-part-2","status":"publish","type":"post","link":"https:\/\/mummila.net\/nuudelisoppa\/2024\/02\/03\/notes-as-i-go-my-attempt-to-develop-a-home-assistant-integration-part-2\/","title":{"rendered":"Notes as I go: my attempt to develop a Home Assistant integration, part 2"},"content":{"rendered":"<p>The documentation keeps referring to &#8220;my API&#8221;, but leaves everything about it up to imagination. How should I name the file? What code should I put there, and what should I not?<\/p>\n<hr>\n<p>The <code>MyEvent<\/code> example, which I adapted for my <code>event.py<\/code>, keeps failing to load, because it &#8220;has no attribute &#8216;async_setup_entry'&#8221;. I get it to shut up by adding a dummy by that name as a function \u2014 not as a method.<\/p>\n<hr>\n<p>I grab <a href=\"https:\/\/github.com\/jdeath\/rd200v2\/blob\/c50970ad2022caf9ab307e44f92b7f8bea408e59\/custom_components\/rd200_ble\/config_flow.py#L171\">some logging code<\/a> from someone else&#8217;s Bluetooth integration and adapt it to my <code>_async_has_devices()<\/code>, to see if I need to do any actual filtering. But none of it ever gets run, despite HA announcing a device being detected by my integration. <\/p>\n<p>In the end I decide it&#8217;s not going to be as easy as I&#8217;d hoped with the <code>config_flow_discovery<\/code> scaffolding. I&#8217;m going to have to invoke <a href=\"https:\/\/github.com\/hbldh\/bleak\">Bleak<\/a> to be able to subscribe to BLE notifications, which are what my button uses to communicate press events, and which, apparently, are <a href=\"https:\/\/developers.home-assistant.io\/docs\/core\/bluetooth\/bluetooth_fetching_data\">not part of HA core<\/a> for now. So I revert the <code>config_flow.py<\/code> changes and go back to the longer version.<\/p>\n<hr>\n<p>The first TODO there is for user data schema. I won&#8217;t have users input any configuration, so out it goes, as does all of <code>validate_input()<\/code>, and <code>async_step_user()<\/code> in <code>ConfigFlow<\/code>. Likewise for <code>PlaceholderHub<\/code> (&#8220;Remove this placeholder class and replace with things from your PyPI package&#8221;).<\/p>\n<p>According to &#8220;<a href=\"https:\/\/developers.home-assistant.io\/docs\/config_entries_config_flow_handler#discovery-steps\">Discovery steps<\/a>&#8220;,<\/p>\n<blockquote><p>&#8220;When an integration is discovered, their respective discovery step is invoked (ie async_step_dhcp or async_step_zeroconf) with the discovery information.&#8221;<\/p><\/blockquote>\n<p>This means it should be <code>async_step_bluetooth()<\/code> for mine. I wish it was listed, along with all other variants, instead of just the two examples, to help googling. An accompanying example would be even better.<\/p>\n<p>The last item on the list of things the discovery step should do is:<\/p>\n<blockquote><p>&#8220;Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user.&#8221;<\/p><\/blockquote>\n<p>Again, not even a hint about this in the documentation, but most core integrations appear to implement a <a href=\"https:\/\/github.com\/home-assistant\/core\/blob\/ad0ee7d781c78755b743324056004180e6796b2e\/homeassistant\/components\/xiaomi_ble\/config_flow.py#L179\"><code>async_step_bluetooth_confirm()<\/code><\/a>, and call it at the end of <code>async_step_bluetooth()<\/code>. There&#8217;s also <a href=\"https:\/\/github.com\/home-assistant\/core\/blob\/ad0ee7d781c78755b743324056004180e6796b2e\/homeassistant\/config_entries.py#L1777\"><code>_set_confirm_only()<\/code><\/a>, which seems like what I need, but again, no documentation anywhere.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The documentation keeps referring to &#8220;my API&#8221;, but leaves everything about it up to imagination. How should I name the file? What code should I put there, and what should I not? The MyEvent example, which I adapted for my event.py, keeps failing to load, because it &#8220;has no attribute &#8216;async_setup_entry&#8217;&#8221;. I get it to [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3941","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/posts\/3941","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/comments?post=3941"}],"version-history":[{"count":12,"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/posts\/3941\/revisions"}],"predecessor-version":[{"id":3953,"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/posts\/3941\/revisions\/3953"}],"wp:attachment":[{"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/media?parent=3941"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/categories?post=3941"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mummila.net\/nuudelisoppa\/wp-json\/wp\/v2\/tags?post=3941"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}