Skip to content

grodcur22/Tesla-MCU1-Speed-Camera-Audio-Visual-Alert-System

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 

Repository files navigation

Tesla MCU Speed Camera Audio & Visual Alert System

This project enables custom audio alerts (such as speed camera warnings) to be played through the native audio system of a Tesla equipped with Media Control Unit (MCU). It also integrates synchronized visual alerts via a custom BLE LED setup.


Important Disclaimers & Prerequisites

  • MCU tegra or intel Only: This concept is specifically tailored for the MCU architecture.
  • Root & Firmware: It is unknown if this functionality persists in the latest firmware versions or if it strictly requires root access. It may be possible to trigger this simply by being on the internal network, but users must test this themselves.
  • Hardware Requirement: A Raspberry Pi (or similar) must be physically connected to an Ethernet port on the Tesla's internal car network.
  • Use at your own risk: Interacting with a vehicle's internal diagnostic/private network can have unpredictable results. Use this information for educational purposes only.

Inspiration & Credits

The core logic for audio injection over the Tesla's internal network is credited to Jasper Nuyens from his research:

https://www.slideshare.net/slideshow/tesla-hacking-presentation-fri3d/110535910

Specifically, Slide 41 details the discovery that sound data can be sent over Ethernet:

Sound is sent over the Ethernet network :)
cat gameofthrones.wav | nc 192.168.90.100 4102

Requires a specific format: RIFF (little-endian), WAVE audio, Microsoft PCM, 16 bit, mono 48000 Hz.

We apply this netcat (nc) pipeline to deliver real-time GPS-triggered warnings.


Audio Generation & Conversion

To ensure the MCU1 processes the audio correctly, the file must be converted to a specific raw format.

  1. Generate Voice:
    Use Narakeet to create an .mp3 alert (e.g., "Speed camera ahead").

https://www.narakeet.com/create/es-creador-de-voz-con-ia.html#trynow

  1. Convert to RAW:
    Use sox to transform the file into the signed-integer raw format the car expects:
sox /path/to/your/alert.mp3 -t raw -c 1 -r 22050 -b 16 -e signed-integer /path/to/your/alert_radar.raw

Visual Alerts (BLE LEDs)

This script integrates with the project:

https://github.com/grodcur22/led-lamp-ble-for-a-car

Integration Details:

  • Shared Hardware: Both systems utilize the same Ublox GPS module for positioning.
  • Control Mechanism: The LED project runs a local API (Port 5000). This script sends HTTP GET requests to trigger a "Flash Red" sequence on Bluetooth Low Energy lamps when a radar is detected, then restores the original ambient color.

Script Logic Breakdown

  • haversine: Calculates the great-circle distance between the car and the radar coordinates.
  • calculate_bearing_to: Determines the azimuth (0–360°) toward the radar.
  • visual_alert_flash: Fetches the current LED state from local files, sends a sequence of requests to flash the LEDs RED (FF0000) and OFF (000000) three times, and finally reverts to the saved color.

Filters

  • Distance/Cooldown: Ensures the radar is within 400m and prevents spamming the same alert for 60 seconds.
  • Cone Filter: Checks if the radar is within a 35° cone in front of the car's current heading (track).
  • Speed Filter: Only alerts if moving > 30 km/h.

Audio Execution

Uses nc -q 0 to pipe the .raw audio file to the Tesla's internal IP (192.168.90.100) on port 4102.


Python Implementation

import csv
import math
import os
import time
import requests
from gps import *

# --- CONFIGURATION ---

CSV_FILE = 'radar_locations.csv'
DISTANCE_ALERT = 0.4          # 400 meters
COOLDOWN = 60                 # Seconds
MIN_SPEED = 30                # km/h
CONE_THRESHOLD = 35           # Degrees (Forward cone)

# LED API CONFIG
AUTH = ('USERNAME', 'PASSWORD')
FRONT_MAC = "FRONT_DEVICE_MAC"
REAR_MAC = "REAR_DEVICE_MAC"

# Paths for color state and audio
FRONT_FILE = "/path/to/front_led_color.txt"
REAR_FILE = "/path/to/rear_led_color.txt"
AUDIO_ALERT = "/path/to/radar_alert.raw"

# Target Tesla Audio Interface
DEVICE_IP = "192.168.90.100"
DEVICE_PORT = "4102"


def haversine(lat1, lon1, lat2, lon2):
    R = 6371.0
    dlat = math.radians(lat2 - lat1)
    dlon = math.radians(lon2 - lon1)

    a = math.sin(dlat / 2)**2 + math.cos(math.radians(lat1)) * \
        math.cos(math.radians(lat2)) * math.sin(dlon / 2)**2

    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    return R * c


def calculate_bearing_to(lat1, lon1, lat2, lon2):
    dLon = math.radians(lon2 - lon1)

    y = math.sin(dLon) * math.cos(math.radians(lat2))
    x = math.cos(math.radians(lat1)) * math.sin(math.radians(lat2)) - \
        math.sin(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.cos(dLon)

    brng = math.atan2(y, x)
    return (math.degrees(brng) + 360) % 360


def get_saved_color(path):
    try:
        if os.path.exists(path):
            with open(path, "r") as f:
                color = f.read().strip().replace('#', '')
                return color if len(color) == 6 else "00ffff"
    except:
        pass

    return "00ffff"


def visual_alert_flash():
    original_front = get_saved_color(FRONT_FILE)
    original_rear = get_saved_color(REAR_FILE)

    try:
        for i in range(3):

            # Flash RED
            requests.get(f'http://127.0.0.1:5000/device_color/{FRONT_MAC}/FF0000', auth=AUTH, timeout=0.3)
            requests.get(f'http://127.0.0.1:5000/device_color/{REAR_MAC}/FF0000', auth=AUTH, timeout=0.3)
            time.sleep(0.2)

            # Off
            requests.get(f'http://127.0.0.1:5000/device_color/{FRONT_MAC}/000000', auth=AUTH, timeout=0.3)
            requests.get(f'http://127.0.0.1:5000/device_color/{REAR_MAC}/000000', auth=AUTH, timeout=0.3)
            time.sleep(0.1)

        # Restore original color
        requests.get(f'http://127.0.0.1:5000/device_color/{FRONT_MAC}/{original_front}', auth=AUTH, timeout=0.3)
        requests.get(f'http://127.0.0.1:5000/device_color/{REAR_MAC}/{original_rear}', auth=AUTH, timeout=0.3)

    except Exception as e:
        print(f"Visual alert error: {e}")


# --- LOAD RADAR DATABASE ---

radars = []

try:
    with open(CSV_FILE, mode='r', encoding='utf-8') as f:
        reader = csv.DictReader(f)

        for row in reader:
            try:
                radars.append({
                    'type': row.get('tipo', 'Camera'),
                    'lat': float(row['latitud']),
                    'lon': float(row['longitud']),
                    'last_alert': 0
                })
            except:
                continue

except FileNotFoundError:
    exit(f"Error: {CSV_FILE} not found")


print(f"Monitor active: {len(radars)} radars loaded.")

gpsd = gps(mode=WATCH_ENABLE | WATCH_NEWSTYLE)


try:
    while True:

        report = gpsd.next()

        if report['class'] == 'TPV':

            my_lat = getattr(report, 'lat', 0.0)
            my_lon = getattr(report, 'lon', 0.0)
            my_speed = getattr(report, 'speed', 0.0) * 3.6
            my_track = getattr(report, 'track', 0.0)

            if my_lat == 0.0 or my_lon == 0.0:
                continue

            for r in radars:

                dist = haversine(my_lat, my_lon, r['lat'], r['lon'])
                now = time.time()

                if dist < DISTANCE_ALERT and (now - r['last_alert'] > COOLDOWN):

                    radar_angle = calculate_bearing_to(my_lat, my_lon, r['lat'], r['lon'])
                    angle_diff = abs(my_track - radar_angle)

                    if angle_diff > 180:
                        angle_diff = 360 - angle_diff

                    if angle_diff <= CONE_THRESHOLD and my_speed >= MIN_SPEED:

                        print(f"[ALERT] {r['type']} at {dist*1000:.0f}m | Speed: {my_speed:.1f} km/h")

                        os.system(f'cat {AUDIO_ALERT} | nc -q 0 {DEVICE_IP} {DEVICE_PORT} &')

                        visual_alert_flash()

                        r['last_alert'] = now

        time.sleep(0.5)

except KeyboardInterrupt:
    print("\nStopping radar monitor.")

License & Disclaimers

License: This script is provided "as-is" for experimental use.

Tesla Warranty: Be aware that connecting third-party devices to the internal IC/CID network and attempting to send unauthenticated packets may void your warranty or cause system instability.

Local Laws: Ensure that using radar warning systems is legal in your jurisdiction.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors