Starlink Dishy: getting some deeper status

This blog post contains details on some hidden status method from Starlink’s user terminal, including what satellite it’s currently talking to.

I’ve been hacking around a bit with Dishy, the Starlink user satellite terminal. They provide some nice consumer tools for basic status: am I connected, what kind of bandwidth am I getting, a basic graph of history of outages. And a new feature, a fancy 2d map of where it thinks obstructions are (ie: the trees around you).

Behind the scenes Dishy implements a gRPC server with lots and lots of data. And happily the server supports reflection, so you can interrogate it for features. They keep adding new features! Mostly I’ve interacted with this using the starlink-grpc-tools package; it hides all the gRPC and just provides some command line programs for dumping data to CSV, InfluxDB, whatever. It’s quite nice! But it’s limited in that it only supports some of Dishy’s methods. There are others!

gRPC software

Ironically I have no experience working with gRPC. The hacking tool of choice seems to be grpcurl which lets you invoke methods via the command line. That’s a little low level so I am using grpcui which gives a simple web UI to gRPC servers that support reflection. There’s lots of other options for a tool like that btw.

So, what other gRPC methods are hiding in there?


First try is a jackpot; dishGetContext. It mostly returns some stuff in other methods; device_info, obstructions, etc.

Update: lol that didn’t last long. Now when I call the method I get “PermissionDenied”, I think because of a firmware update. It was working on firmware a4908729. It’s now failing on firmware 4990ce8d.

But it also returns a bunch of information that looks to be about which satellite Dishy is currently talking to! It will tell me my cell ID (shouldn’t change?), a satellite ID, a gateway ID, and a “seconds to slot end”. It looks like Dishy swaps satellites every 15 seconds. The satellite IDs correlate pretty well with what a satellite tracker says. There’s also a “backup beam” that turns on sometimes after packet loss. It’s all super cool!

id	ut01000000-00000000-000XXXXX
hardware_version	rev1_pre_production
software_version	990b956d-a7fc-4c9b-a3ab-c09a309ac425.uterm.release
country_code	US
utc_offset_s	-28799
obstruction_fraction	0.0064355433
obstruction_valid_s	178496
cell_id	1142511
pop_rack_id	38
seconds_to_slot_end	3.531043
uptime_s	178780
initial_satellite_id	1186
initial_gateway_id	544
on_backup_beam	true

Here’s a quick little shell script to monitor cell, satellite, gateway, and also a ping to once a second.

while :; do
  grpcurl -plaintext -d '{ "dishGetContext": {} }' SpaceX.API.Device.Device/Handle | 
    jq  '.dishGetContext|.cellId,.initialSatelliteId,.initialGatewayId,.onBackupBeam,.secondsToSlotEnd' | tr '\n' ' '; 
  ping -c 1 -W 1 | awk -F/ '/^rtt/ { print $5 }' ; 
  sleep 1;

Unimplemented methods

I went through all the other methods in the gRPC stuff. I skipped the ones that starlink-grpc-tools already supports like “status”, etc. Sorry to anyone else but for me I already knew what those did.

Unfortunately all the other interesting looking methods I could find returned errors suggesting they aren’t implemented. get_next_id, get_location, a bunch of wifi_ methods I suspect are in the router (not Dishy).

dish_emc: Fast Switching

One last method looked interesting, dish_emc. That API call seems mostly to be about RF radio state; channels, modulation details, etc. But there’s a fast_switching flag. Maybe fast switching is a frequency thing. But my hope is that it’s related to a promised feature where Dishy predicts obstructions and switches to new satellites to avoid them. My real hope is that this feature isn’t yet turned on and turning it on will magically make my Internet better.

So I turned it on: "dish_emc":{"fast_switching": true}}. I did that today around 11am on 2021-06-27. It didn’t immediately break my Internet so.. good? I’ll check back in 24 hours to see if it had any change. It may amount to nothing though.

Update: after 24 hours I think making this API call did nothing. Either the API isn’t implemented at all, or fast_switching was already on, or it doesn’t make a difference whatever it does. My money is on the “not implemented at all”. Here’s a graph of drop rate; I made the change right about the middle of the time axis here.

dish_emc looks like it returns status data too. But calling it, all the results are 0 or false. Maybe it’s not implemented or has some lockout. Here’s the result from that set call:

is_test_device	false
timestamp	0
snr	0
seconds_until_schedule	0
snr_uptime	0
cplane_uptime	0
percent_scheduled	0
cplane_updates	0
downlink_throughput	0
uplink_throughput	0
connected	false
sys_uptime	0
gps_latitude	0
gps_longitude	0
gps_pdop	0
rf_mode	0
phi	0
theta	0
rx_channel	0
tx_channel	0
t_dbf_max	0
t_center	0
baseline_heating	0
additional_heating	0
total_heating	0
target_total_heating	0
auto_power_snow_melt_enabled	false
voltage	0
rx_beam_state	0
tx_beam_state	0
half_duplex_state	0
manual_tilt_enabled	false
tilt_angle	0
pll_tx_lock_detected	0
eirp_exceeded_threshold	false
eirp_scale_override	0
idle_override_enabled	false
theta_override_enabled	false
theta_override_value	0
phi_override_enabled	false
phi_override_value	0
rx_chan_override_value	0
tx_chan_override_value	0
sky_search_override_enabled	false
fast_switching_enabled	false
modulation_override_value	0
force_eirp_failure	false
force_pll_unlock	false
ut_ine_success	0
rf_ready	false

One thought on “Starlink Dishy: getting some deeper status

  1. Fast switching may be for mobile implementations, such as plane, train, or (fast moving) RV…

Comments are closed.