#!/usr/bin/env python3

import serial

import time

import datetime

import os

import pynmea2

# --- GPS configuration ---

GPS_PORT = "/dev/ttyTHS1"

GPS_BAUD = 9600

# --- Arduino serial configuration ---

ARDUINO_PORT = "/dev/ttyACM0"

ARDUINO_BAUD = 115200

# --- Printing configuration ---

MAX_CHUNK_LENGTH = 12 # threshold for big words

LETTER_DELAY = 0.2 # delay per letter for big words

CHUNK_DELAY = 0.5 # delay between words

# --- Initialize GPS ---

def init_gps():

try:

return serial.Serial(GPS_PORT, GPS_BAUD, timeout=1)

except Exception as e:

print("GPS init error:", e)

return None

# --- Get GPS data ---

def get_gps_data(gps, timeout=10):

if gps is None:

return None, None, None

start = time.time()

while time.time() - start < timeout:

try:

line = gps.readline().decode('ascii', errors='replace')

if line.startswith('$GPGGA') or line.startswith('$GPRMC'):

msg = pynmea2.parse(line)

lat = getattr(msg, 'latitude', None)

lon = getattr(msg, 'longitude', None)

timestamp = getattr(msg, 'timestamp', datetime.datetime.utcnow().time())

if lat and lon:

return lat, lon, timestamp

except Exception:

continue

return None, None, None

# --- Send entry and GPS to Arduino ---

def send_entry_to_arduino(entry_lines, gps):

# --- compact GPS line ---

lat, lon, timestamp = get_gps_data(gps, timeout=10)

if lat is None or lon is None:

gps_line = f"FAILURE|{datetime.datetime.now().strftime('%H:%M:%S')}"

else:

gps_line = f"{lat:.6f},{lon:.6f}|{timestamp}"

# Combine GPS line + entry lines

full_text = gps_line + " " + " ".join(entry_lines)

words = full_text.split()

with serial.Serial(ARDUINO_PORT, ARDUINO_BAUD, timeout=1) as arduino:

time.sleep(2) # allow Arduino to reset

# --- Print GPS line letter by letter ---

for char in gps_line:

arduino.write(char.encode("ascii", "replace"))

arduino.flush()

time.sleep(LETTER_DELAY)

arduino.write(b"\n")

arduino.flush()

time.sleep(CHUNK_DELAY)

# --- Print entry words ---

for word in words[len(gps_line.split()):]:

if len(word) > MAX_CHUNK_LENGTH:

# Big word: print letter by letter

for char in word:

arduino.write(char.encode("ascii", "replace"))

arduino.flush()

time.sleep(LETTER_DELAY)

arduino.write(b" ") # space after big word

arduino.flush()

time.sleep(CHUNK_DELAY)

else:

# Small word: print normally with trailing space

arduino.write((word + " ").encode("ascii", "replace"))

arduino.flush()

time.sleep(CHUNK_DELAY)

# Final newline after all words

arduino.write(b"\n")

arduino.flush()

time.sleep(CHUNK_DELAY)

# --- Show live GPS location ---

def show_location(gps):

print("\n--- LIVE GPS LOCATION --- (CTRL+C to return)\n")

try:

while True:

lat, lon, timestamp = get_gps_data(gps, timeout=5)

os.system('clear')

if lat is None or lon is None:

print("FAILURE TO LOCATE!\n")

else:

print(f"Latitude: {lat:.6f}")

print(f"Longitude: {lon:.6f}")

print(f"UTC Time: {timestamp}")

time.sleep(1)

except KeyboardInterrupt:

pass

# --- Shutdown system ---

def shutdown_system():

print("\nSystem shutting down...\n")

os.system("sudo shutdown now")

# --- Escape backdoor ---

def unlock_desktop():

print("\n[** BACKDOOR ACTIVATED: DESKTOP UNLOCK **]\n")

os.system("sudo systemctl set-default graphical.target")

os.system("sudo systemctl start gdm")

exit(0)

# --- New journal entry ---

def new_entry(gps):

print("\n--- NEW JOURNAL ENTRY ---")

entry_lines = []

print("(Type/paste entry; empty line to finish)\n")

while True:

line = input()

if line.strip().upper() == "ESCAPE":

unlock_desktop()

if line.strip() == "":

break

entry_lines.append(line)

send_entry_to_arduino(entry_lines, gps)

print("\nEntry sent to Arduino.\n")

# --- Main menu ---

def main():

gps = init_gps()

os.system("clear")

while True:

print("================================")

print(" JOURNAL LOGGER MAIN MENU")

print("================================")

print("1. NEW ENTRY")

print("2. LOCATION")

print("3. SHUTDOWN")

print("================================")

choice = input("Select option: ").strip()

if choice.upper() == "ESCAPE":

unlock_desktop()

elif choice == "1":

new_entry(gps)

elif choice == "2":

show_location(gps)

elif choice == "3":

shutdown_system()

else:

print("Invalid selection.\n")

if __name__ == "__main__":

try:

main()

except KeyboardInterrupt:

print("\nExiting safely.\n")

Next
Next

Land of the Lost (archive)