Help us shape the future of Go! Take the 2026 Go Developer Survey

tirelow

package
v0.40.22 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package tirelow sends the tire-low alert: an opt-in push when the truck itself reports a tire low (DA's ruling, Sprint 8 item 3). It repeats what the truck says and nothing more.

  • Only Rivian's own per-wheel status counts (rivian.TireStatusLow). Never our own pressure floor: a cold night trips a fixed one. A missing or unfamiliar word is no claim either way, so it never alerts and never clears.
  • A wheel must have been low for SustainedFor: first seen low on a fresh frame at least that long ago, still low on the latest fresh frame, with no fresh "not low" in between (that resets the clock). Frames need not arrive every minute: low after a cold night, woken, driven off and parked again is the common case, and it must fire.
  • It fires only with the truck in P (stated), never while driving. A parked, awake truck with the owner nearby is exactly the moment to say it.
  • A wheel's episode ends only after EndAfter of fresh "not low" time, accumulated: a status that flickers at a threshold does not make new episodes, and a gap with no frames never counts as "not low". It is cumulative across awake periods (a gap does not reset it), so a truck awake two hours a day takes days to end an episode; the 7-day Cooldown and restarts govern repeats more than this does.
  • A repeat for the same wheels waits out Cooldown; a wheel that was not in the last alert and goes low inside the cooldown alerts again.
  • The text is fixed (internal/push.TireLowPayload): the model and the wheel positions. No pressure, no place.

The marker (tire_low_alerts) records only that an alert went out for these wheels, so a restart or a second pod never repeats it. The job reads the monitor's latest state and calls nothing on Rivian. That is the merged state: a status the truck has not changed since an earlier frame still stands, which is the word the Truck card shows too. It can miss one case: if the vehicleState stream drops while Parallax keeps the state's time fresh, an old status can stand; the marker and the cooldown limit any repeat, which is acceptable for v1. A pod that does not run the vehicle's monitor does nothing.

Index

Constants

View Source
const (
	// SustainedFor is how long a wheel must have been low (the owner's N). One constant.
	SustainedFor = 30 * time.Minute
	// EndAfter is how much fresh "not low" time, accumulated, ends a wheel's episode.
	EndAfter = 12 * time.Hour
	// Cooldown: no repeat alert for the same wheels within this long.
	Cooldown = 7 * 24 * time.Hour
	// CheckEvery is the timer.
	CheckEvery = time.Minute
	// FreshFrame is how recent a state must be to say anything about a tire, low or not.
	FreshFrame = 10 * time.Minute
	// PruneAfter is how long a marker is kept.
	PruneAfter = 30 * 24 * time.Hour
)

Variables

View Source
var Positions = []string{"fl", "fr", "rl", "rr"}

Positions are the four wheels, as internal/push.JoinWheels knows them.

Functions

func Parked

func Parked(st *rivian.State) bool

Parked says the state states park. Unknown gear is not park.

func Statuses

func Statuses(st *rivian.State) map[string]Status

Statuses reads each wheel's status from the state.

Types

type Job

type Job struct {
	Source Source
	// Deliver sends the push to the account's devices that have the alert on.
	Deliver func(ctx context.Context, uid uuid.UUID, model string, low, puncture []string) error
	// Live turns the real push on (a server flag, off by default). Off, the whole path runs for every account's truck but
	// no push, no marker and no opt-in is involved: each episode that would have sent one is counted by WouldSend instead
	// (the class label only: the low word) and logged. Counted per episode, in memory: a restart can count one again.
	Live      bool
	WouldSend func(class string)
	Now       func() time.Time
	Logger    *slog.Logger
	// contains filtered or unexported fields
}

Job is the timer.

func (*Job) Run

func (j *Job) Run(ctx context.Context)

Run ticks every CheckEvery until ctx ends.

func (*Job) Tick

func (j *Job) Tick(ctx context.Context)

Tick checks every candidate vehicle once.

type LatestFunc

type LatestFunc func(uid uuid.UUID, rivianID string) (*rivian.State, time.Time)

LatestFunc reads a vehicle's newest state from the monitor this pod runs (nil state: not this pod's).

type Source

type Source interface {
	// Vehicles are the trucks of accounts with the alert on for some device; with all set (the dry run), every enabled
	// account's truck.
	Vehicles(ctx context.Context, all bool) ([]Vehicle, error)
	// Latest is the monitor's newest state for the vehicle and when it was last updated; nil when this pod does not run
	// that vehicle's monitor.
	Latest(uid uuid.UUID, rivianID string) (*rivian.State, time.Time)
	// Claim records an alert for these wheels (sorted positions) and reports whether this call was the one: false when
	// the same episode was already claimed or a recent alert already named all of these wheels.
	Claim(ctx context.Context, uid, vehicleID uuid.UUID, newest time.Time, wheels []string) (bool, error)
	// Prune deletes markers older than the cutoff.
	Prune(ctx context.Context, before time.Time) (int64, error)
}

Source reads what the job needs.

func NewSource

func NewSource(db *sql.DB, latest LatestFunc, skip uuid.UUID) Source

NewSource reads candidates and records markers in Postgres, and states from latest. skip is excluded (the demo user).

type Status

type Status int

Status is what the truck's own per-wheel status says about a wheel.

const (
	Unknown Status = iota // no word, or one we have no claim for
	Low
	NotLow
)

type Vehicle

type Vehicle struct {
	UserID    uuid.UUID
	VehicleID uuid.UUID // the database id
	RivianID  string
	Model     string
}

Vehicle is a truck whose owner has the alert on.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL