Welcome to the most democratized ocean data feed on the internet. While Bob battles Pacific swells, every sensor reading and GPS coordinate streams live through Redis and InfluxDB. This isn't just telemetryβit's raw maritime adventure data from the middle of nowhere.
Why settle for boring dashboards when you can build something spectacular? Whether you're correlating wave heights with propeller efficiency, creating anxiety-inducing progress trackers, or just obsessing over real-time ocean data, these streams are your gateway to Bob's digital soul. Build AI mood predictors, whale encounter alerts, or the most beautiful ocean visualization the internet has ever seen.
This is citizen science at its finestβa floating sensor platform funded by internet strangers, transmitting data that anyone can access and transform into something amazing. Bob's journey is your data playground.
Drop Bob's live tracking map directly into your own website or application. Clean, borderless design with real-time GPS updates from Redis. Perfect for news articles, dashboards, or any page that needs live ocean tracking.
Lightning-fast key-value store with Bob's current state. Perfect for real-time dashboards and live applications.
sensors:gps:current_lat
- Current latitude (decimal degrees)sensors:gps:current_lon
- Current longitude (decimal degrees)sensors:gps:velocity_knots
- Speed over ground (knots)sensors:gps:velocity_mps
- Speed over ground (meters/second)sensors:gps:altitude
- GPS altitude (meters above sea level)sensors:gps:satellites
- Number of GPS satellites in viewsensors:gps:movement_heading
- Course over ground (degrees)sensors:gps:timestamp
- Unix timestamp of GPS fixsensors:gps:fix_quality
- GPS fix quality indicatorsensors:gps:hdop
- Horizontal dilution of precisionsensors:gps:geoid_height
- Height of geoid above WGS84sensors:gps:dgps_age
- Age of DGPS correctionssensors:mag:heading
- Magnetic compass heading (degrees)sensors:mag:raw_x
- Raw magnetometer X-axis readingsensors:mag:raw_y
- Raw magnetometer Y-axis readingsensors:mag:raw_z
- Raw magnetometer Z-axis readingsensors:mag:calibrated_x
- Calibrated magnetometer X-axissensors:mag:calibrated_y
- Calibrated magnetometer Y-axissensors:mag:calibrated_z
- Calibrated magnetometer Z-axissensors:navigation:heading
- Autopilot heading (degrees)sensors:navigation:target_bearing
- Bearing to next waypointsensors:navigation:distance_to_target
- Distance to waypoint (km)sensors:navigation:heading_error
- PID heading errorsensors:navigation:mode
- Navigation mode (auto/manual)sensors:mppt:battery_voltage
- Battery voltage (V)sensors:mppt:battery_current
- Battery charge current (A)sensors:mppt:battery_power
- Battery charge power (W)sensors:mppt:array_voltage
- Solar array voltage (V)sensors:mppt:array_current
- Solar array current (A)sensors:mppt:array_power
- Solar array power (W)sensors:mppt:array_voc
- Array open circuit voltagesensors:mppt:array_pmax
- Array maximum power pointsensors:mppt:charge_state
- Charge controller statesensors:mppt:charge_state_mapped
- Human-readable charge statesensors:mppt:load_current
- Load output current (A)sensors:mppt:battery_temperature
- Battery temperature (Β°C)sensors:odrive:power
- Motor electrical power consumption (W)sensors:odrive:current_a
- Motor phase A current (A)sensors:odrive:current_b
- Motor phase B current (A)sensors:odrive:velocity
- Motor shaft velocity (rev/s)sensors:odrive:position
- Motor shaft position (revolutions)sensors:odrive:voltage_bus
- DC bus voltage (V)sensors:odrive:temperature
- Motor driver temperature (Β°C)sensors:odrive:error_code
- Error status codesensors:odrive:control_mode
- Motor control modesensors:odrive:encoder_count
- Encoder countsensors:odrive:torque_target
- Target torque commandsensors:odrive:efficiency
- Motor efficiency percentagesensors:stepper:angle
- Rudder angle (degrees)sensors:stepper:position
- Stepper motor position (steps)sensors:stepper:target_angle
- Target rudder anglesensors:stepper:current
- Stepper motor current (mA)sensors:stepper:temperature
- Stepper driver temperaturesensors:stepper:enabled
- Motor enable statussensors:stepper:homed
- Homing statussensors:stepper:steps_per_degree
- Calibration factorsensors:stepper:max_angle
- Maximum rudder anglesensors:stepper:min_angle
- Minimum rudder anglesensors:stepper:velocity
- Stepper velocity (steps/s)sensors:stepper:stall_detection
- Stall guard statussensors:system:cpu_usage
- CPU utilization percentagesensors:system:cpu_temperature
- CPU temperature (Β°C)sensors:system:memory_usage
- RAM usage percentagesensors:system:disk_usage
- Storage usage percentagesensors:system:uptime
- System uptime (seconds)sensors:system:boot_time
- Last boot timestampsensors:system:network_rx
- Network bytes receivedsensors:system:network_tx
- Network bytes transmittedsensors:system:load_1min
- 1-minute load averagesensors:system:load_5min
- 5-minute load averagesensors:system:voltage_3v3
- 3.3V rail voltagesensors:system:voltage_5v
- 5V rail voltagesensors:power:load_motor:value
- Motor power switch statesensors:power:load_stepper:value
- Stepper power switch statesensors:power:load_sensors:value
- Sensor power switch statesensors:power:load_comms:value
- Communications power statesensors:power:usb_frontcam1:value
- Front camera 1 USB powersensors:power:usb_frontcam2:value
- Front camera 2 USB powersensors:power:total_consumption
- Total power consumption (W)sensors:power:battery_capacity
- Estimated battery capacity (%)sensors:power:time_to_empty
- Estimated battery runtime (hours)sensors:power:charging_efficiency
- Solar charging efficiencysensors:power:power_balance
- Net power (generation - consumption)sensors:power:emergency_mode
- Low power mode status#!/usr/bin/env python3 """ Project Bob - Comprehensive Redis Data Viewer This script connects to Project Bob's public Redis data stream and displays a comprehensive overview of the vessel's telemetry, organized by subsystem. - Connects to the Redis cloud instance with read-only credentials. - Fetches data from multiple subsystems: GPS, Navigation, Power, System, etc. - Displays the data in a clean, formatted, and continuously updating table. - Handles connection errors and missing data gracefully. """ import redis import time import os from datetime import datetime # --- Configuration --- REDIS_HOST = 'redis-17021.fcrce172.us-east-1-1.ec2.redns.redis-cloud.com' REDIS_PORT = 17021 REDIS_USERNAME = 'readonlyuser' REDIS_PASSWORD = 'Trawlingforlikes1!!' # --- Key Groups --- # Define the Redis keys we want to monitor, grouped by subsystem KEY_GROUPS = { "π’ Vessel Status": { "Position": "sensors:gps:current_lat", "Heading": "sensors:navigation:heading", "Speed (knots)": "sensors:gps:velocity_knots", "Mode": "sensors:navigation:mode" }, "π GPS System": { "Latitude": "sensors:gps:current_lat", "Longitude": "sensors:gps:current_lon", "Satellites": "sensors:gps:satellites", "Altitude (m)": "sensors:gps:altitude", "Fix Quality": "sensors:gps:fix_quality" }, "β‘ Power System": { "Battery (V)": "sensors:mppt:battery_voltage", "Solar Panel (W)": "sensors:mppt:array_power", "Motor Power (W)": "sensors:odrive:power", "Charge State": "sensors:mppt:charge_state_mapped" }, "π§ Navigation & Control": { "Compass Heading": "sensors:mag:heading", "Rudder Angle (Β°)": "sensors:stepper:angle", "Target Bearing": "sensors:navigation:target_bearing", "Distance to Target (km)": "sensors:navigation:distance_to_target" }, } def connect_to_redis(): """Establishes a connection to the Redis server.""" print("π Connecting to Bob's Redis data stream...") try: r = redis.Redis( host=REDIS_HOST, port=REDIS_PORT, username=REDIS_USERNAME, password=REDIS_PASSWORD, decode_responses=True, socket_connect_timeout=5, socket_timeout=5 ) r.ping() print("β Connection successful!") return r except redis.exceptions.AuthenticationError: print("β Authentication failed. Check username and password.") return None except redis.exceptions.ConnectionError as e: print(f"β Connection error: {e}") return None except Exception as e: print(f"β An unexpected error occurred: {e}") return None def fetch_data(redis_client, keys_to_fetch): """Fetches a batch of keys from Redis using a pipeline.""" pipe = redis_client.pipeline() for key in keys_to_fetch: pipe.get(key) try: values = pipe.execute() return values except redis.exceptions.ConnectionError: print("β οΈ Lost connection to Redis. Attempting to reconnect...") return None except Exception as e: print(f"β οΈ Error during data fetch: {e}") return None def display_data(data): """Clears the screen and displays the fetched data in a structured format.""" os.system('cls' if os.name == 'nt' else 'clear') timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print("=" * 60) print(f" PROJECT BOB - LIVE TELEMETRY | {timestamp}") print("=" * 60) for group_name, keys in KEY_GROUPS.items(): print(f"\n{group_name}") print("-" * 25) for name, key in keys.items(): value = data.get(key, "N/A") # Try to format numbers nicely, otherwise display as is try: value_str = f"{float(value):.2f}" except (ValueError, TypeError): value_str = str(value) if value is not None else "N/A" print(f" {name:<25}: {value_str}") print("\n" + "=" * 60) print("Press Ctrl+C to exit. Updating every 5 seconds...") def main(): """Main loop to connect, fetch, and display data.""" redis_client = connect_to_redis() if not redis_client: return all_keys = [key for group in KEY_GROUPS.values() for key in group.values()] unique_keys = sorted(list(set(all_keys))) try: while True: values = fetch_data(redis_client, unique_keys) if values is not None: data_dict = dict(zip(unique_keys, values)) display_data(data_dict) else: # Attempt to reconnect if fetch failed redis_client = connect_to_redis() if not redis_client: print("Could not re-establish connection. Exiting.") break time.sleep(5) # Wait before retrying after reconnect continue time.sleep(5) except KeyboardInterrupt: print("\n\nπ Exiting Bob's telemetry viewer. Safe travels!") except Exception as e: print(f"\nAn unexpected error occurred in the main loop: {e}") if __name__ == '__main__': main()
# Install required packages pip install redis
Historical data paradise. Every measurement Bob has ever taken, perfectly timestamped and ready for analysis.
current_lat
- Current latitude (float, degrees)current_lon
- Current longitude (float, degrees)velocity_knots
- Speed over ground (float, knots)velocity_mps
- Speed over ground (float, m/s)altitude
- GPS altitude (float, meters MSL)satellites
- Satellite count (integer)movement_heading
- Course over ground (float, degrees)fix_quality
- GPS fix quality (integer, 0-8)hdop
- Horizontal dilution of precision (float)geoid_height
- Geoid height above WGS84 (float, meters)dgps_age
- Age of DGPS corrections (float, seconds)timestamp_gps
- GPS receiver timestamp (integer, unix)heading
- Autopilot heading (float, degrees)target_bearing
- Bearing to next waypoint (float, degrees)distance_to_target
- Distance to waypoint (float, km)heading_error
- PID heading error (float, degrees)pid_p_term
- PID proportional term (float)pid_i_term
- PID integral term (float)pid_d_term
- PID derivative term (float)pid_total_output
- Total PID output (float)integral_value
- PID integral accumulator (float)integral_limit
- PID integral windup limit (float)mode
- Navigation mode (string: auto/manual)power_save
- Power save mode (boolean)battery_voltage
- Battery voltage (float, V)battery_current
- Battery charge current (float, A)battery_power
- Battery charge power (float, W)array_voltage
- Solar array voltage (float, V)array_current
- Solar array current (float, A)array_power
- Solar array power (float, W)array_voc
- Array open circuit voltage (float, V)array_pmax
- Maximum power point (float, W)charge_state
- Charge state code (integer)charge_state_mapped
- Charge state (string)load_current
- Load output current (float, A)battery_temperature
- Battery temp (float, Β°C)heading
- Magnetic compass heading (float, degrees)raw_x
- Raw magnetometer X-axis (float, Β΅T)raw_y
- Raw magnetometer Y-axis (float, Β΅T)raw_z
- Raw magnetometer Z-axis (float, Β΅T)calibrated_x
- Calibrated X-axis (float, Β΅T)calibrated_y
- Calibrated Y-axis (float, Β΅T)calibrated_z
- Calibrated Z-axis (float, Β΅T)magnitude
- Total field strength (float, Β΅T)declination
- Magnetic declination (float, degrees)inclination
- Magnetic inclination (float, degrees)calibration_offset_x
- X calibration offset (float)calibration_offset_y
- Y calibration offset (float)power
- Electrical power consumption (float, W)current_a
- Motor phase A current (float, A)current_b
- Motor phase B current (float, A)velocity
- Motor shaft velocity (float, rev/s)position
- Motor shaft position (float, revolutions)voltage_bus
- DC bus voltage (float, V)temperature
- Motor driver temperature (float, Β°C)error_code
- Error status code (integer)control_mode
- Motor control mode (integer)encoder_count
- Encoder position (integer, counts)torque_target
- Target torque command (float, Nm)efficiency
- Motor efficiency (float, percentage)angle
- Rudder angle (float, degrees)position
- Stepper position (integer, steps)target_angle
- Target rudder angle (float, degrees)current
- Stepper motor current (float, mA)temperature
- Stepper driver temp (float, Β°C)enabled
- Motor enable status (boolean)homed
- Homing completion status (boolean)steps_per_degree
- Calibration factor (float)max_angle
- Maximum rudder angle (float, degrees)min_angle
- Minimum rudder angle (float, degrees)velocity
- Stepper velocity (float, steps/s)stall_detection
- Stall guard status (boolean)cpu_usage
- CPU utilization (float, percentage)cpu_temperature
- CPU temperature (float, Β°C)memory_usage
- RAM usage (float, percentage)disk_usage
- Storage usage (float, percentage)uptime
- System uptime (integer, seconds)boot_time
- Last boot timestamp (integer, unix)network_rx_bytes
- Network RX bytes (integer)network_tx_bytes
- Network TX bytes (integer)load_1min
- 1-minute load average (float)load_5min
- 5-minute load average (float)voltage_3v3
- 3.3V rail voltage (float, V)voltage_5v
- 5V rail voltage (float, V)air_temperature
- Air temperature (float, Β°C)water_temperature
- Water temperature (float, Β°C)humidity
- Relative humidity (float, percentage)pressure
- Atmospheric pressure (float, hPa)wave_height
- Estimated wave height (float, meters)wind_speed
- Wind speed (float, knots)wind_direction
- Wind direction (float, degrees)uv_index
- UV radiation index (float)light_intensity
- Ambient light (float, lux)precipitation
- Rainfall rate (float, mm/hr)salinity
- Water salinity (float, PSU)turbidity
- Water turbidity (float, NTU)#!/usr/bin/env python3 """ Bob's Historical Data Analyzer Pulls complete InfluxDB telemetry into pandas DataFrame every 30 seconds Analyzes Bob's journey patterns, performance metrics, and ocean conditions """ import pandas as pd import time from datetime import datetime, timedelta from influxdb_client_3 import InfluxDBClient3 def connect_to_influx(): """Connect to Bob's InfluxDB historical data store""" print("π Connecting to Bob's InfluxDB time series database...") try: # InfluxDB connection parameters token = "RRp6hGho7p5rxi_BEUJzQcFdks6jWHSxHeW7ja21T0HR8lDXBLsvxPze93CmJnB5X_sl1qdya8CxdGnuOk3Jxg==" org = "bob" host = "https://us-east-1-1.aws.cloud2.influxdata.com" database = "bob-telemetry" # Create InfluxDB client connection client = InfluxDBClient3(host=host, token=token, org=org) print("β Connected to Bob's historical database!") return client, database except Exception as e: print(f"β InfluxDB connection failed: {e}") return None, None def fetch_complete_telemetry(client, database, hours_back=24): """Fetch comprehensive telemetry data from InfluxDB""" print(f"π Fetching last {hours_back} hours of Bob's complete telemetry...") try: # Comprehensive SQL query to get all major telemetry streams # This pulls GPS, power, navigation, and environmental data query = f''' SELECT time, -- GPS & Navigation Data gps_lat as latitude, gps_lon as longitude, gps_velocity_knots as speed_knots, gps_satellites, navigation_heading as compass_heading, navigation_mode, -- Power & Energy Systems battery_voltage, solar_power_watts, motor_power_watts, power_consumption_total, -- Environmental Conditions air_temperature_c, water_temperature_c, wave_height_meters, wind_speed_knots, wind_direction, -- System Health cpu_temperature, system_uptime_hours, memory_usage_percent, storage_usage_percent FROM "{database}"."autogen"."telemetry" WHERE time >= now() - interval '{hours_back} hours' ORDER BY time DESC LIMIT 10000 ''' # Execute query and convert to pandas DataFrame print("β³ Executing query...") table = client.query(query=query, database=database, language='sql') df = table.to_pandas() # Convert time column to datetime if it's not already if 'time' in df.columns: df['time'] = pd.to_datetime(df['time']) df.set_index('time', inplace=True) print(f"β Retrieved {len(df)} telemetry records!") return df except Exception as e: print(f"β Error fetching telemetry: {e}") # Fallback to simplified GPS-only query if comprehensive query fails try: print("π Trying simplified GPS query...") simple_query = f''' SELECT time, current_lat, current_lon, velocity_knots, satellites FROM "{database}"."autogen"."gps" WHERE time >= now() - interval '{hours_back} hours' ORDER BY time DESC LIMIT 5000 ''' table = client.query(query=simple_query, database=database, language='sql') df = table.to_pandas() if 'time' in df.columns: df['time'] = pd.to_datetime(df['time']) df.set_index('time', inplace=True) print(f"β Retrieved {len(df)} GPS records (simplified mode)") return df except Exception as e2: print(f"β Simplified query also failed: {e2}") return None def analyze_telemetry(df): """Analyze Bob's telemetry data and print insights""" if df is None or df.empty: print("β οΈ No data to analyze") return print("\n" + "="*80) print("π BOB'S TELEMETRY ANALYSIS") print("="*80) # Basic dataset info print(f"π Dataset Overview:") print(f" β’ Time Range: {df.index.min()} to {df.index.max()}") print(f" β’ Total Records: {len(df):,}") print(f" β’ Data Points: {len(df.columns)} metrics") print(f" β’ Duration: {(df.index.max() - df.index.min()).total_seconds()/3600:.1f} hours") # GPS Analysis (if available) if 'latitude' in df.columns or 'current_lat' in df.columns: lat_col = 'latitude' if 'latitude' in df.columns else 'current_lat' lon_col = 'longitude' if 'longitude' in df.columns else 'current_lon' print(f"\nπ GPS Position Analysis:") print(f" β’ Current Position: {df[lat_col].iloc[0]:.6f}Β°, {df[lon_col].iloc[0]:.6f}Β°") print(f" β’ Position Range: {df[lat_col].min():.4f}Β° to {df[lat_col].max():.4f}Β° latitude") print(f" β’ Distance Span: ~{abs(df[lat_col].max() - df[lat_col].min()) * 69:.1f} miles N-S") # Speed Analysis speed_col = None for col in ['speed_knots', 'velocity_knots']: if col in df.columns: speed_col = col break if speed_col: print(f"\nπ Speed Analysis:") print(f" β’ Current Speed: {df[speed_col].iloc[0]:.2f} knots") print(f" β’ Average Speed: {df[speed_col].mean():.2f} knots") print(f" β’ Max Speed: {df[speed_col].max():.2f} knots") print(f" β’ Speed Std Dev: {df[speed_col].std():.2f} knots") # Power Analysis (if available) if 'battery_voltage' in df.columns: print(f"\nπ Power System Analysis:") print(f" β’ Current Battery: {df['battery_voltage'].iloc[0]:.2f}V") print(f" β’ Battery Range: {df['battery_voltage'].min():.2f}V - {df['battery_voltage'].max():.2f}V") if 'solar_power_watts' in df.columns: print(f" β’ Avg Solar Power: {df['solar_power_watts'].mean():.1f}W") # Data Quality Assessment print(f"\nπ Data Quality:") missing_data = df.isnull().sum() total_possible = len(df) * len(df.columns) missing_percent = (missing_data.sum() / total_possible) * 100 print(f" β’ Data Completeness: {100-missing_percent:.1f}%") print(f" β’ Missing Values: {missing_data.sum():,} out of {total_possible:,}") # Show recent data sample print(f"\nπ Most Recent Data (last 5 records):") print(df.head().to_string()) def main(): """Main analysis loop - fetches and analyzes data every 30 seconds""" # Connect to InfluxDB client, database = connect_to_influx() if not client: return print("π Starting continuous telemetry analysis... (Press Ctrl+C to stop)") print("π Data will refresh every 30 seconds") try: while True: # Get current timestamp timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"\nπ [{timestamp}] Fetching latest telemetry data...") # Fetch comprehensive telemetry data df = fetch_complete_telemetry(client, database, hours_back=24) # Analyze the data analyze_telemetry(df) # Optional: Save data to CSV for further analysis if df is not None and not df.empty: filename = f"bob_telemetry_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv" df.to_csv(filename) print(f"\nπΎ Data saved to: {filename}") print(f"\nβ±οΈ Waiting 30 seconds for next update...") print("-" * 80) # Wait 30 seconds before next analysis time.sleep(30) except KeyboardInterrupt: print(f"\nπ Analysis stopped. Bob's data lives on!") print("π Check your directory for saved CSV files with Bob's telemetry data.") # Run the analyzer if __name__ == '__main__': main()
# Install required packages pip install influxdb-client-3 pandas
We can't wait to see what you create with Bob's data. Whether it's a beautiful visualization, a predictive model, or something completely unexpected, tag us when you ship it. The best community-built tools might just get featured on the main dashboard.
Remember: Bob's success depends on this data flowing freely. Build tools that help us understand his journey, predict his challenges, and celebrate his victories. The ocean is vast, but together we can make sense of every wave.