[Custom Integration] Rental Control - for AirBnB, VRBO, etc

Though it’s possible that I’m just not getting the correct data as the URL you provided is giving me a 403. DM me a more appropriate URL if it has any user/password bits in it.

Ok, quick follow-up. I get a 403 if I try and pull it with HEAD, but if I pull it with wget I get told it’s getting text/html and the other platforms are all doing text/calendar like they are supposed to. So, still, bug on the platform side. They aren’t providing valid ical

Ah okay, thanks so much for the quick reply and checking it out for me! I’ve told Host Tools about it, hopefully it’s not too hard a fix.

Hi, thank you for your work! In Italy we don’t really use your z-wave lock since they are not compatible with our european cilinder lock. Different entrance doors :slight_smile: anyway, your integration is usefull to process the ICS and generate a code I can use to generate a pin code for my nuki lock.

There is something I really don’t understand about the “event” managing. What happens when event 0 finishes? Event 1 turns into 0 and so on?

The events are always in chronological order according to the calendar. Anything older than “today” is ignored by the system. So, Event 0 is going to be any event that is already happening today or is the first event that will happen in the future according to your calendar. Event 1, is the next one after that etc.

So, what happens when Event 0 expires, it will be removed and all events will move down one slot. So, event 1 becomes event 0, and event 2 becomes event 1, etc.

This all will happen when the following conditions occur:

  • The event at event 0 is removed from the upstream calendar
  • The event at event 0 ended that day and it hits midnight, as this now makes the event an event that is older that “today” it is removed from the active events

You should always be setting up a minimum of 2 events when configuring the integration. Otherwise, if you have a guest that is leaving and one that is arriving on the same day you will have no way of handling that since the guest leaving will still show as event 0 until at least midnight.

thank you for your reply, I understood how it work. Now I have to understand how to deal with it. Every time I create a new pincode, it contains the valid time frame and it expires at the check-out time.
I create a curl to the nuki web api extracting the data from the event attributes and since event 1 will turn in event 0 I don’t know when to do the curl. If I make the curl for event 0 and event 1, event 1 will be duplicated when it will turn event 0 but I cannot make the curl for event 0 only because, as you said, I will miss the reservation arriving the same day as event 0 check-out.

Is there a webhook API that you can call from HA to update your Nuki? If so, then you can create some automations based on calendar event going from off to on or event 0 and 1 having their ETA Minutes attribute going to < 1 / Unknown that triggers updates to your Nuki for you.

yep, it is a curl webhook and events are useful because inside their attributes there is everything I need to fill in for the webhook while the calendar entity doesn’t have them. I will find a way to avoid duplicates :slight_smile: maybe eta as you suggest. It would be easier with event 0 removed at check-out time and not at midnight so the automation can fire 2-3 hours before event 0 check-in time. I will work on it! Thanks again!

I keep event 0 around until it is removed from the upstream calendar or is one day in the past in case of situations in which a guest is being granted a later check-out but it happens at / after the standard check-out time. This has happened often enough on a few of my properties that I don’t want to just remove the event until it’s absolutely certain that it is done.

Yeah, I understood the reason and it’s fine! It works with Keymaster, but not with Nuki, since I have to set up the time/day for the key to expire when the key is created.

Any late check-out must be managed manually. Not a big deal, late check-outs are very, very rare :-p

Hi, something strange is happening! I have two instances of Home Assistant, they’re practically identical, Rental Control is working fine on one, but no matter what I do I can’t get it working with one of them. I’ve tried deleting Keymaster integrations, reinstalling Keymaster, deleting all Rental Control integrations, reinstalling Rental Control, but it keeps coming back with this message, how do I get more detailed logs on this and do you know why this is happening?

Have you checked the logs at config/home-assistant.log to see if there are any reported issues?

If there are no errors being reported in the log itself, with the default logging then you’ll need to increase the logging level of the integration. For setting this up see this earlier portion of the thread:

Once you have logging setup you will need to run through the config flow again and see if it produces any sort of usable error.

Unfortunately, given what the error is, I have no clue (it’s unknown :wink: ) I do return back far more helpful error messages on everything that I can explicitly return a message for during the configuration work flow.

Thanks so much for your advice, I looked in there and found this:

2024-04-30 21:11:20.611 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1025, in _wrap_create_connection
    return await self._loop.create_connection(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1120, in create_connection
    raise exceptions[0]
  File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1102, in create_connection
    sock = await self._connect_sock(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/base_events.py", line 1005, in _connect_sock
    await self.sock_connect(sock, address)
  File "/usr/local/lib/python3.12/asyncio/selector_events.py", line 641, in sock_connect
    return await fut
           ^^^^^^^^^
  File "/usr/local/lib/python3.12/asyncio/selector_events.py", line 649, in _sock_connect
    sock.connect(address)
OSError: [Errno 101] Network unreachable

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py", line 452, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_app.py", line 543, in _handle
    resp = await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_middlewares.py", line 114, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 77, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 88, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 236, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 32, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 71, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 222, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 73, in wrapper
    result = await method(view, request, data, *args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 122, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 356, in async_configure
    result = await self._async_configure(flow_id, user_input)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 402, in _async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 506, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/rental_control/config_flow.py", line 92, in async_step_user
    return await _start_config_flow(
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/rental_control/config_flow.py", line 335, in _start_config_flow
    resp = await session.get(user_input[CONF_URL])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/client.py", line 581, in _request
    conn = await self._connector.connect(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 544, in connect
    proto = await self._create_connection(req, traces, timeout)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 944, in _create_connection
    _, proto = await self._create_direct_connection(req, traces, timeout)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1257, in _create_direct_connection
    raise last_exc
  File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1226, in _create_direct_connection
    transp, proto = await self._wrap_create_connection(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/connector.py", line 1033, in _wrap_create_connection
    raise client_error(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host app.hosttools.com:443 ssl:default [Network unreachable]

It seems to be a network error, but why would that be? I don’t have network issues on the other instance of Home Assistant with Rental Control, and they’re both on separate 5G working networks. I am also accessing HA through HA Cloud so there should be a working connection?

The setup workflow does two things when you save:

  1. Validate that all inputs are correct for the type of data needed and in correct ranges
  2. Validate that ICS URL is actually reachable via an SSL encrypted connection and is returning a properly encoded ICS file

Give what you show there, the issue seems to be that your HA instance cannot reach app.hosttools.com at all. You should validate your ability to connect to the internet from that system and try again.

How do I check if the system can connect to the internet? As I said, I am managing it via HA Cloud and that’s working fine. Looking at my router statistics it seems to be uploading and downloading data. I can download add-ons from HACS. Is it possible that there is a network configuration that is limited to just Rental Control?

I assume you’ve got the ssh & terminal add-on installed? Open the terminal and try ping app.hosttools.com and see if it returns any data.

As for if there is a network configuration that is limited to just RC. No, as in integration it runs inside the main HA process space.

Is that what you’d expect?

Yes, that’s what I would expect.

You can also try the following in your terminal to see if it get’s anything back:

curl <YOUR_ICS_URL>

That’s weird! I’m getting this with the same URL on my other instance

What could it be?

It might be something to do with DuckDNS that I installed and configured, but then I uninstalled it?