ha-lta icon indicating copy to clipboard operation
ha-lta copied to clipboard

Bus Arrival API v2 deprecated

Open dexmorgan8888 opened this issue 6 months ago • 5 comments

As of 1 Jun 2025, version 2 has stopped functioning. There is now a version 3. https://datamall.lta.gov.sg/content/dam/datamall/datasets/LTA_DataMall_API_User_Guide.pdf

This integration has been extremely useful. Please consider updating to version 3. Thank you

dexmorgan8888 avatar Jun 02 '25 13:06 dexmorgan8888

Thanks @dexmorgan8888 for pointing that out. I raised a PR on the dependency which should update the API accordingly. Hopefully it gets picked up.

https://github.com/Codestian/ltapysg/pull/2

flaskr avatar Jun 07 '25 06:06 flaskr

For those waiting for a new release of this, I got mine to work by using FileEditor on the following file: /homeassistant/custom_components/lta/sensor.py

  1. Replacing the import:
# from ltapysg import get_bus_arrival # comment this out
from aiohttp import ClientSession, ClientConnectorError # add this instead
  1. and adding the following updated functions from the dependency:
BASE_URL = "https://datamall2.mytransport.sg/ltaodataservice/"

# Base async function to call api, receive response and handle errors.
async def call(api_key, url):
    async with ClientSession() as session:
        try:
            async with session.get(
                BASE_URL + url,
                headers={"Accept": "application/json", "AccountKey": api_key},
            ) as response:
                if response.status == 200:
                    return await response.json()
                else:
                    raise Exception(
                        "Received status code " + str(response.status)
                    ) from None
        except ClientConnectorError as err:
            raise Exception(str(err)) from None

# Retrieve arrival timings for all buses operating for specified bus stop. Each bus has 3 recurring timings.
async def get_bus_arrival(api_key, bus_stop_code):
    data = await call(api_key, "v3/BusArrival?BusStopCode=" + str(bus_stop_code))
    return data["Services"]

flaskr avatar Jun 07 '25 07:06 flaskr

@flaskr Thanks so much. Your amendments work well.

dexmorgan8888 avatar Jun 09 '25 10:06 dexmorgan8888

  1. and adding the following updated functions from the dependency:
BASE_URL = "https://datamall2.mytransport.sg/ltaodataservice/"

# Base async function to call api, receive response and handle errors.
async def call(api_key, url):
    async with ClientSession() as session:
        try:
            async with session.get(
                BASE_URL + url,
                headers={"Accept": "application/json", "AccountKey": api_key},
            ) as response:
                if response.status == 200:
                    return await response.json()
                else:
                    raise Exception(
                        "Received status code " + str(response.status)
                    ) from None
        except ClientConnectorError as err:
            raise Exception(str(err)) from None

# Retrieve arrival timings for all buses operating for specified bus stop. Each bus has 3 recurring timings.
async def get_bus_arrival(api_key, bus_stop_code):
    data = await call(api_key, "v3/BusArrival?BusStopCode=" + str(bus_stop_code))
    return data["Services"]

Hi @flaskr , it's my first time using github and i'm not really a coder or programmer myself. Just wish to understand where did you place the code in Pointer 2? Is it in the same sensor.py file? Are you able to share how your sensor.py file looks like?

Oscarooijh avatar Jun 18 '25 14:06 Oscarooijh

@Oscarooijh here is how my sensor.py looks like after performing the change recommended by @flaskr Take note as I am unable to upload .py, I updated the file extension to .txt. But you can simply change it back to .py and then sub your original sensor.py with this file.

sensor.txt

wh1t35m1th avatar Jun 26 '25 10:06 wh1t35m1th