Bus Arrival API v2 deprecated
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
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
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
- Replacing the import:
# from ltapysg import get_bus_arrival # comment this out
from aiohttp import ClientSession, ClientConnectorError # add this instead
- 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 Thanks so much. Your amendments work well.
- 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 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.