<div dir="ltr"><div>I thought about posting this to only NANOG, but since a great concentration of beta testers of a technical/network engineering inclination are located in the Pacific NW, decided to also include the SIX chat list.<br></div><div><br></div><div>You may have seen the Starlink android or ios consumer-friendly app, which displays network traffic, uptime/downtime, and other link stats. I believe this to be polled directly from the antenna unit itself over grpc.</div><div><br></div><div>The beta antennas are always 192.168.100.1. If you are using your own router with the starlink beta system, in addition to its WAN interface being an ordinary DHCP client in cgnat IP space, you'll need to manually give it an address in that /24 and set up routing to reach the .1 IP as needed.<br></div><div><br></div><div>reference: <a href="https://github.com/sparky8512/starlink-grpc-tools">https://github.com/sparky8512/starlink-grpc-tools</a></div><div><br></div><div>reference: <a href="https://github.com/fullstorydev/grpcui">https://github.com/fullstorydev/grpcui</a></div><div><br></div><div>you'll need a fairly normal Linux or BSD box with:<br></div><div><br></div><div>git<br></div><div>go<br></div><div>python3</div><div>pip</div><div><br></div><div>use pip to install grpcio and grpcio-tools</div><div><br></div><div>install grpcurl: <a href="https://github.com/fullstorydev/grpcurl">https://github.com/fullstorydev/grpcurl</a></div><div><br></div><div>do a git clone of the starlink-grpc-tools url above, also take a look at its readme info<br></div><div><br></div><div><span style="font-family:monospace">get the dish's protoset file and write it to new file dish.protoset , this is an index of all data that can be polled<br>cd /home/eric/starlink-grpc-tools<br>/home/eric/go/bin/grpcurl -plaintext \<br>-protoset-out dish.protoset \<br><a href="http://192.168.100.1:9200">192.168.100.1:9200</a> \<br>describe SpaceX.API.Device.Device<br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">/home/eric/go/bin/grpcurl \<br>-plaintext \<br>-d {\"get_history\":{}} \<br><a href="http://192.168.100.1:9200">192.168.100.1:9200</a> \<br>SpaceX.API.Device.Device/Handle | python parseJsonHistory.py<br><br>output of the above looks like this:<br>2021-02-06T08:15:56,3600,19.92034332,14,2,0.3125,0,0,0.0,0<br><br>full CSV header for the above:<br>datetimestamp_utc,samples,total_ping_drop,count_full_ping_drop,count_obstructed,total_obstructed_ping_drop,count_full_obstructed_ping_drop,count_unscheduled,total_unscheduled_ping_drop,count_full_unscheduled_ping_drop<br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">since we are able to acquire the above in a comma-delimited csv format, it's fairly easy to write a script storing the integers from any one of those particular columns into a mariadb db, sqlite, influxdb, or whatever.<br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">the following will output about 3.8MB of text for the full history (I believe this to be the full copy of the ring buffer stored in RAM for the terminal's statistics) , pipe it into a text file if you want to manually look at it. <br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">/home/eric/go/bin/grpcurl -plaintext -d {\"get_history\":{}} <a href="http://192.168.100.1:9200">192.168.100.1:9200</a> SpaceX.API.Device.Device/Handle</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">same as the above but human readable output<br><br>/home/eric/go/bin/grpcurl \<br>-plaintext \<br>-d {\"get_history\":{}} \<br><a href="http://192.168.100.1:9200">192.168.100.1:9200</a> \<br>SpaceX.API.Device.Device/Handle | python parseJsonHistory.py -v<br><br>current counter:       299673<br>All samples:           43200<br>Valid samples:         43200<br>Parsed samples:        3600<br>Total ping drop:       20.03700998<br>Count of drop == 1:    14<br>Obstructed:            2<br>Obstructed ping drop:  0.3125<br>Obstructed drop == 1:  0<br>Unscheduled:           0<br>Unscheduled ping drop: 0.0<br>Unscheduled drop == 1: 0<br><br><br>see the get_history_notes.txt file for more info<br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">SOME EXAMPLE QUERIES<br>these should match with what the json query is in the grpc GUI<br># get status<br>/home/eric/go/bin/grpcurl \<br>-plaintext \<br>-d {\"getStatus\":{}} \<br><a href="http://192.168.100.1:9200">192.168.100.1:9200</a> \<br>SpaceX.API.Device.Device/Handle<br><br># get device info<br>/home/eric/go/bin/grpcurl \<br>-plaintext \<br>-d {\"getDeviceInfo\":{}} \<br><a href="http://192.168.100.1:9200">192.168.100.1:9200</a> \<br>SpaceX.API.Device.Device/Handle<br><br># get history, this outputs a huge amount of data<br>/home/eric/go/bin/grpcurl \<br>-plaintext \<br>-d {\"getHistory\":{}} \<br><a href="http://192.168.100.1:9200">192.168.100.1:9200</a> \<br>SpaceX.API.Device.Device/Handle<br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">The following is copied/pasted from my notes file on things we can acquire, and then use a tiny shell script with awk, sed, regex, whatever as needed to trim out just the numbers, and put them somewhere else for polling by snmp extend</span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">/home/eric/go/bin/grpcurl \<br>-plaintext \<br>-d {\"getStatus\":{}} \<br><a href="http://192.168.100.1:9200">192.168.100.1:9200</a> \<br>SpaceX.API.Device.Device/Handle<br></span></div><div><span style="font-family:monospace"><br></span></div><div><span style="font-family:monospace">notes on what's what:<br>figures we care about to parse out and turn into just the integers<br>snr can never be higher than 9<br>fractionobstructed appears to be the percentage of the time that the view is obstructed, as long as the view<br>remains unobstructed, this number appears to slowly decrement over time<br>validS is valid seconds? i think<br>the S is almost likely always Seconds of time<br><br>"uptimeS": "304439"<br>"snr": 9,<br>"fractionObstructed": 0.0013524292,<br>"validS": 61815.74,<br>"last24hObstructedS": 53<br>"downlinkThroughputBps": 47915.73,<br>"uplinkThroughputBps": 34980.496,<br>"popPingLatencyMs": 29.266666<br><br><br>example of running the command above twice, the second time a few minutes after the first, <br>to see that fractionObstructed does decrement itself over time</span></div><div><span style="font-family:monospace">first run:  0.0013524292<br>second run: 0.0013467998<br></span></div><div><br></div><div><br></div><div><br></div></div>