Skip to content

Abstract London Underground information from watch-side logic#2

Closed
CometDog wants to merge 1 commit intoC-D-Lewis:masterfrom
CometDog:master
Closed

Abstract London Underground information from watch-side logic#2
CometDog wants to merge 1 commit intoC-D-Lewis:masterfrom
CometDog:master

Conversation

@CometDog
Copy link

@CometDog CometDog commented Dec 18, 2025

We've discussed this briefly in private but I wanted to raise this as a reivew-able for if you're interested with no timeline or pressure to merge back at all.

For my own purposes to make Tube Status work for JR East Kanto, I've gone through a few iterations of design to get the London Underground information off of the watch so it can just take any data from the phone and present it the same way it does exactly today.

The goals here are:

  1. Touch as little as possible. I tried to not rework anything other than what needed to be done minimally without also causing poor patterns to develop. In this, I ended up changing how the data is populated, but kept the interface in tact for the UI to access
  2. Maintain existing platform compatbility. Some lines may require more than 25 alerts at once, but London Underground, at 18-19 lines, probably won't
  3. Maintain existing behavior to production Tube Status app. There were a couple spots where I added some warning/severe mappings for statuses that weren't clear if you were covering or not, but I think it's documented well enough to discuss
  4. Define a clear path forward for additional transit systems. I have a working JR East Kanto and NYC MTA Subway backend on my local machine using this exact same API that London is using. I am using an abstract class that, as long as fully implemented, will work. This gives each system the flexibility to resolve the data internally however it needs for the class to produce. Some logic, such as the mapping of statuses to configuration, are included for London even though they aren't needed, as some systems may return status and configuration on different APIs to be reconciled later (NYC MTA does this)
  5. Make all Tube Status concepts abstract without removing anything. I've preserved everything that Tube Status already does which is mostly generic. However some things I did not understand how you used them. For example "striped" is something that is a visual piece for lines that I don't understand. I kept it though because regardless of why it is used by you for London Underground, anything else can use it to signify something else. For example I use it for the major lines in JR East Kanto to help separate the city main lines from the local/thru lines.
  6. Make adding new transit systems as non-invasive as possible. I have 4 other transit system I'm interested (2 done, 2 in the works) that are just 4 files on my machine and no other changes. What is in this PR is the entirety of what would allow other backends to work.

Changes:

  • The watch code has no concept of specific lines. It now just sets a max of 25 and all the properties that a line needs (name, color, status, severity code, description, striped)
  • The phone sends two batches to the watch, the configuration data and the status information. It will only configure lines that actually have statuses to present so even if a transit system has 50 lines, it'll only overflow the 25 line limit if there are more than 25 active status issues
  • The backend for London Underground is abstracted away to conform to the generic TransitBackend class
  • Severity status for London uses the code rather than the description. I think I mapped them the same as you had still

Again I don't need you to merge this or not. I am going to continue working on it as my own project to be able to switch between transit systems that I feel are useful to me. But if it feels sufficient to you or when you have time discuss it, I think even if you never decide to support more systems than London in the Tube Status app, this at least sets up an easier system to work with overall even just for London.

London Underground:
pebble_screenshot_2025-12-17_21-09-11

JR East Kanto:
pebble_screenshot_2025-12-17_21-08-56

NYC MTA Subways:
pebble_screenshot_2025-12-17_21-09-37

@C-D-Lewis
Copy link
Owner

Thank you! I will read this today. I really like the idea of extending the UI to support more transit systems (and provide a pluggable way for others to add more!) - ideally for me the one repo would be able to continue publishing Tube Status in addition to some other version with all the extra backends. Maybe two package files? package.json.tubestatus and one other.

@CometDog
Copy link
Author

I think two package files would make the most sense since I wouldn't want to lose the purpose-built nature of Tube Status.

The only potential deviation would be if one wanted to provide a way in-app, rather than through configuration, to select different backend systems. That code would have to be gated behind something that wouldn't invade Tube Status either functionally or in app size.

One piece I hadn't considered either is the backend service for Tube Status that seems to be pushing Timelime Pins or App Glances. That would probably be something that would remain exclusive to Tube Status unless one felt compelled to rebuild that for every backend. So having the separate package is important for that as well

Copy link
Owner

@C-D-Lewis C-D-Lewis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! With a way to publish Tube Status and some new app that has additional transit system options, this is a neat abstraction!

reason = reason?.substring(0, MAX_REASON_LENGTH - 4) + '...';
}
for (const config of configs) {
const dict = {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think AppMessage buffers can be large enough to send config + status in one message

if (packet_contains_key(iter, MESSAGE_KEY_LineStatusSeverity)) {
line_data->severity = (StatusSeverity)packet_get_integer(iter, MESSAGE_KEY_LineStatusSeverity);
} else {
line_data->severity = StatusSeverityGood;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wary of assuming good if data goes missing - should there be an 'unknown' state?

/**
* London Underground / TfL transit backend
*/
class LondonUndergroundBackend extends TransitBackend {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'TfL' (Transport for London) might be a more succinct term to use in code symbols than 'londonunderground'

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do this. I switched it because conceptually other lines could exist so I didn't want to name it after the authority versus the actual line name.

However, and especially for the original Tube Status implementation, I can still change it back if that makes more sense for you

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used TfL because they provide the data, and it encompasses all the available lines. No big deal really.

index: number;
name: string;
color: number; // Hex color as uint32
striped: boolean; // Renders a visual difference, can be used to indicate special lines
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of the stripe on TfL lines seems arbitrary or biased towards newer ones that have re-used colors or colors similar to older lines

https://tfl.gov.uk/maps/track/tube

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured keeping it in the abstraction could be useful for other systems that are or aren't as arbitrary as London Underground.

For example JR East Kanto specifies a few lines with short codes like JY or JK while other lines, mainly local lines, lack short codes. On my own version, I'm passing those with short codes as stripes to designate that.

Do you think this should be more internal in the UI? Where if a color is to be reused it'll stripe it?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the backend should just say which are striped to align with a map (TfL) where known or however the dev wants to make use of it themselves.

const NUM_LINES = 19;
/** Max reason length */
const MAX_REASON_LENGTH = 512;
// TODO: Configure ACTIVE_BACKEND with settings in the future
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a simple Clay config page

Copy link
Author

@CometDog CometDog Dec 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I can remove the TODO until a PR is in place to handle two separate apps. I had considered this PR just abstraction and no route to a second .json file, so it doesn't actually need config at all, as Tube Status, right now.

I am actually considering something in the UI to enable this rather than Clay. Only because there are cases you'd have multiple lines overlapping and want to switch (JR East Kanto and Tokyo Metro operate in the same stations at times)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having an option in the UI makes sense - switch without getting your phone out

@CometDog
Copy link
Author

I'll be following up with all of this but I'll also be on vacation for 3 weeks so it won't be until after that that I round back!

@C-D-Lewis
Copy link
Owner

@CometDog No rush! Enjoy the vacation! I'll prototype multiple package files one day soon

@CometDog
Copy link
Author

CometDog commented Jan 14, 2026

I'm back and at it. I'm working at my day job again so it'll be after work hours I get to this but I plan to write out my mindset for Tube Status vs Transit Status (what I'm currently generically calling it) as a proposal for you and potentially some commits to either demonstrate or fully propose the multiple packages for building.

I intended for this to just be a more simple abstraction PR that causes no impact to Tube Status, but I think without at least a POC of how Transit Status would function as an extension of Tube Status, some of this either doesn't make sense or isn't fully solved enough to merge.

As an aside, I've tested my implementations I have for JR East Kanto and JR Central Tokaido-Sanyo Shinkansen during very bad delays recently and it works exactly as I'd expect Tube Status to work for London. Multiple alerts for the same line (multiple direction, pass thrus, etc) work as well

@C-D-Lewis
Copy link
Owner

Thanks! There's no rush. I experimented with the package files but since your PR is from a main branch I could not add any commits.

@CometDog
Copy link
Author

CometDog commented Jan 16, 2026

I'm currently finishing out a POC of the two apps side by side with transit system selection to hopefully give a fuller picture. When I do I'll have it in another branch to maybe restart the review process there (and I'll address comments here to not have to carry them over). Then we can compare strategies for separate packages because it's definitely a no man's land.

Sorry about the clunk on this review so far. I thought breaking it apart would be easier but it seems it wasn't going to be. Then posting it right before my vacation was a choice.

@C-D-Lewis
Copy link
Owner

This is my concept - a script that builds one of two app package definitions, and use of a #define or similar in JS to choose which backends are available, emulating either app as required.

https://github.com/C-D-Lewis/pebble-dev/compare/multi-packages?expand=1

@CometDog
Copy link
Author

CometDog commented Jan 16, 2026

I did something fairly different, using just the wscript though it could just get split to a separate file just as well.

It uses a separate package.json only to override values from the existing Tube Status, so in this case just the name and UUID. Then it does similar where it defines something you can check in C. This is all off the build command so you just pass the variant flag to pebble build. It puts the state of the files back to Tube Status after build finishes, so it's only ever Transit Status at build time.

The work I'm doing now is to make it so Tube Status can follow the same code flow as Transit Status, just omitting the ability to select a system and instead always requesting London. I've got that all figured out but I am working on the selection screen now.

I'll have something fairly complete in a few days as time allows and then I'll spin up a new PR to discuss that completely, and look over your work above on how to manage two apps in one project as well

CometDog@deebe31

@CometDog
Copy link
Author

Lets switch this over to the full POC since that seems like it'll be more relevant to the conversation than just this PR which was generifying Tube Status on its own.

I've taken notes of your comments here and will address them in that PR as well

#4

@CometDog CometDog closed this Jan 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants