How do i use track_time_interval?

I’m trying to build a component that calls an api every 6 seconds and stores the result. In order to call the method every 6 seconds i have imported and used track_time_interval. However this seems to only call the method once and looking at my logs it gives the following error (every 6 seconds) which i can’t really decipher:

2018-07-18 11:51:49 INFO (MainThread) [homeassistant.core] Bus:Handling <Event system_log_event[L]: 
timestamp=1531907509.0991945, level=ERROR, message=Error doing job: Future exception was never 
retrieved, exception=Traceback (most recent call last):
File "C:\Users\tschrauwen\AppData\Local\Programs\Python\Python36\lib\concurrent\futures\thread.py", line 
56, in run
result = self.fn(*self.args, **self.kwargs)
TypeError: 'NoneType' object is not callable
, source=C:\Users\tschrauwen\AppData\Local\Programs\Python\Python36\lib\site- 
packages\homeassistant\core.py>

I’ve added the component to my configuration with a username and password attribute.

my code: https://hastebin.com/poxaluyupa.py
my logs: https://hastebin.com/girumayuge.rb

I can’t really find anything in the documentation on how to do this. So i might be aproaching this from a completely wrong angle. if anyone can tell me how to call the api and update the values over an interval that would be a great help.

thanks in advance.

You’re calling track_time_interval like this:

track_time_interval(hass, get_values(vehicle, hass), INTERVAL)

The second parameter, however, is a function. I.e., you’re supposed to pass it a function to execute. However, you’re calling get_values and then passing the return value (which is None) into the second parameter of track_time_interval. So, every six seconds it’s trying to call None.

What you need to do instead is to pass just the name of the function. And then that function needs to get any data it needs by some other means.

thanks for the advise. I would have never figured that out myself.

I’m still kind of stuck though. As you said i have to somehow call the function and get the hass and vehicle parameters from somewhere else. I’ve tried doing the following:

def setup(hass, config):
    tesla_email = config[DOMAIN].get(CONF_USERNAME, "no username")
    tesla_password = config[DOMAIN].get(CONF_PASSWORD, "no password")
    connection = setup_connection(tesla_email, tesla_password)
    carname = "213197"

    def get_values():
        _LOGGER.info("get_values")
        speed = get_speed(vehicle)
        temperature = get_temp(vehicle)
        sensor_data = {"speed": speed,
                   "temperature": temperature}

        _LOGGER.info("before set states")
        ##hass.states.set("tesla_logger.speed", sensor_data["speed"])
        hass.states.set("tesla_logger.temperature", str(sensor_data["temperature"]))

    for vehicle in connection.vehicles:
        if vehicle["display_name"] == carname:
            track_time_interval(hass, get_values, INTERVAL)
            # speed = get_speed(vehicle)
            # temperature = get_temp(vehicle)
    return True

This way the get_values method will (as i think it works) just get all it needs from its outer scope.
However i still seem to get errors. It now says the following in my logs:

TypeError: get_values() takes 0 positional arguments but 1 was given

which i think is strange because i’m not passing any arguments at all.

my full logs: https://hastebin.com/ugepohupox.coffeescript

Well, per the code above, no, that error shouldn’t happen. Which means maybe you didn’t save your latest changes???

Anyway, what you have might work if the last vehicle in the for loop matched carname. But, if not, then vehicle would change to a different car when the rest of the loop finishes. At the very least I’d add a break statement to the if statement inside the for statement:

    for vehicle in connection.vehicles:
        if vehicle["display_name"] == carname:
            track_time_interval(hass, get_values, INTERVAL)
            break

Hopefully not more than one vehicle will match carname.

The other issue is, if no vehicle matches carname, you never setup the timed callback (which is probably fine), but you still return True from setup. I would think if no vehicle matches, you’d want setup to return False.

That is actually a good idea. I’ll implement it like that.

I already figured out what my problem was. Apparently i had to add a “call” parameter to the function i called in the track_time_interval like so:

def get_values(call):
    ....