Merge pull request #1 from cimryan/master

Update fork
This commit is contained in:
skipfire
2018-10-25 06:55:13 -05:00
committed by GitHub
34 changed files with 694 additions and 475 deletions

View File

@@ -1,43 +0,0 @@
# Setting up the Pi without a monitor using a Mac or Linux
You can setup the Pi to connect to your Wifi network, and also provide the option to connect over USB networking (Rasberry Pi Zero W or other recent Pi's).
**What is USB networking?**
Basically what you're doing is using the Pi's capability to emulate a network connection over USB. So you need to get the Pi (the guest) set up to load the proper modules to do so, and then connect from your machine (the host) using a shell (like iTerm+SSH on macOS). It's an alternative to Wifi if needed.
## Use the update script to setup Wifi and USB networking
A [script](https://raw.githubusercontent.com/cimryan/teslausb/master/mac_linux_archive/setup-piForHeadlessConfig.sh is provided to automatically update your SD card so the first time you boot it on your Pi, USB networking and Wifi will automatically be configured.
If you prefer not to run the script, it's also a useful reference for the steps you'll need to take.
> It's important you do these steps **before you boot the Pi the first time with the SD card inserted**.
1. Ensure you've flashed your Raspbian image to your SD card.
1. If the `boot` folder isn't showing on your computer, eject and re-insert the SD card into your computer, **not the Raspberry Pi**.
1. Change to the directory where the SD card's `boot` folder (containing `cmdline.txt`) is located. On a Mac, this will be `/Volumes/boot`. On Linux the location may vary.
1. Run the following commands:
```
wget https://raw.githubusercontent.com/cimryan/teslausb/master/mac_linux_archive/setup-piForHeadlessConfig.sh
chmod +x setup-piForHeadlessConfig.sh
```
1. Set your SSID (Wifi network name) and WIFIPASS environment variables. The script will insert them into the `wpa_supplicant.conf` when creating it:
```
export SSID=your_ssid_here
export WIFIPASS=your_wifi_password_here
```
1. Run the script:
`./setup-piForHeadlessConfig.sh`
1. If all goes well, the script will report:
`-- Files updated and ready for Wifi and SSH over USB --`
1. Eject the SD card safely, insert into your Pi, and reboot. If the Pi is connected over USB to your host, and/or if the Wifi setup went correctly, you should be able to `ssh pi@raspberrypi.local`. The default password is `raspberry`.
> Note: If you receive an error indicating that the host id has changed, edit your computer's `~/.ssh/known_hosts` file. Find the line with the IP address of your Pi, or labeled "raspberrypi.local" and delete the entire line. You're especially likely to encounter this error if you're following these instructions for a second time.
## Manual/other resources
* [Gist (text file) showing example steps to setup USB networking](https://gist.github.com/gbaman/975e2db164b3ca2b51ae11e45e8fd40a)
If manually configuring the Pi vs using the update script, be sure to delete the `init=/usr/lib/raspi-config/init_resize.sh` parameter from cmdline.txt to prevent the os partition from being expanded to fill the drive.

View File

@@ -50,19 +50,25 @@ Download and install:
* [Etcher](http://etcher.io) * [Etcher](http://etcher.io)
## Create your archive ## Create your archive
### Hosting on Windows ### Hosting on Windows File Shares, MacOS Sharing, or Samba on Linux
Set up a share on a Windows (or macOS using Sharing, or Linux using Samba) machine to host the archive. These instructions assume that you created a share named "SailfishCam" on the server "Nautilus". It is recommended that you create a new user. Grant the user you'll be using read/write access to the share. These instructions will assume that the user you've created is named "sailfish" and that the password for this user is "pa$$w0rd". Set up a share to host the archive. These instructions assume that you created a share named "SailfishCam" on the server "Nautilus". It is recommended that you create a new user. Grant the user you'll be using read/write access to the share. These instructions will assume that the user you've created is named "sailfish" and that the password for this user is "pa$$w0rd".
Get the IP address of the archive machine. You'll need this later, so write it down, somewhere. You can do this by opening a command prompt on the archive machine and typing ipconfig. Get the IP address from the line labeled "IPv4 Address". These instructions will assume that the IP address of the archive server is 192.168.0.41. Get the IP address of the archive machine. You'll need this later, so write it down, somewhere.
* On Windows you can do this by opening a command prompt on the archive machine and typing ipconfig. Get the IP address from the line labeled "IPv4 Address". These instructions will assume that the IP address of the archive server is 192.168.0.41.
* On MacOS or Linux open a terminal and type ifconfig.
### TODO Other hosting solutions ### Hosting via SFTP/rsync
**EXPERIMENTAL - Hosting the archive on SFTP hasn't been thoroughly tested**
Since sftp/rsync is accessing a computer through SSH, the only requirement for hosting an SFTP/rsync server is to have a box running Linux. An example can be another Raspberry Pi connected to your local network with a USB storage drive plugged in. The official Raspberry Pi site has a good example on [how to mount an external drive](https://www.raspberrypi.org/documentation/configuration/external-storage.md). You will need the username and host/IP of the storage server, as well as the path for the files to go in, and the storage server will need to allow SSH.
### ***TODO: Other hosting solutions***
## Set up the Raspberry Pi ## Set up the Raspberry Pi
There are four phases to setting up the Pi: There are three phases to setting up the Pi:
1. Get the OS onto the micro sd card. 1. Get the OS onto the micro sd card.
1. Get a shell on the Pi. 1. Get a shell on the Pi.
1. Set up the USB storage functionality. 1. Set up the USB storage functionality.
1. Get the Pi set up for your Tesla.
### Get the OS onto the micro SD card ### Get the OS onto the micro SD card
@@ -72,14 +78,18 @@ There are four phases to setting up the Pi:
> Note: you don't need to uncompress the zip file you downloaded. > Note: you don't need to uncompress the zip file you downloaded.
### Get a shell on the Pi ### Get a shell on the Pi
If you used a Windows computer to flash the OS onto the MicroSD card, follow these [Instructions](GetShellWithoutMonitorOnWindows.md). If you used a Windows computer to flash the OS onto the MicroSD card, follow these [Instructions](doc/GetShellWithoutMonitorOnWindows.md).
If you used a Mac or a Linux computer, follow these [Instructions](GetShellWithoutMonitorOnLinux.md).
If you used a Mac or a Linux computer, follow these [Instructions](doc/GetShellWithoutMonitorOnLinux.md).
### Set up the USB storage functionality ### Set up the USB storage functionality
Now that you have Wifi up and running, it's time to set up the USB storage and scripts that will manage the dashcam and (optionally) music storage. Now that you have Wifi up and running, it's time to set up the USB storage and scripts that will manage the dashcam and (optionally) music storage.
1. SSH to the Pi and run `sudo -i` 1. SSH to the Pi and run
```
sudo -i
```
1. Try to ping your archive server from the Pi. In this example the server is named `nautilus`. 1. Try to ping your archive server from the Pi. In this example the server is named `nautilus`.
``` ```
ping -c 3 nautilus ping -c 3 nautilus
@@ -89,47 +99,54 @@ Now that you have Wifi up and running, it's time to set up the USB storage and s
ping 192.168.0.41 ping 192.168.0.41
``` ```
1. If you can't ping the archive server by IP address from the Pi, you should go do whatever you need to on your network to fix that. If you can't reach the archive server by name, from the Pi but you can by IP address, then use its IP address, below, in place of its name. 1. If you can't ping the archive server by IP address from the Pi, you should go do whatever you need to on your network to fix that. If you can't reach the archive server by name, from the Pi but you can by IP address, then use its IP address, below, in place of its name.
1. Run these commands, subsituting your values. The last line is the percent of the drive you want to allocate for dashcam storage. The remaining percentage will be allocated for music. 1. Determine how much, as a percentage, of the drive you want to allocate to recording dashcam footage by using:
```
export campercent=<number>
```
For example, using `export campercent=100` would allocate 100% of the space to recording footage from your car, and would not create a separate music partition. `export campercent=50` would be only allocate half of the space for a dashcam footage drive, and allocates the other half to be a music storage drive.
1. If you are trying to archive on an SFTP/rsync server, then follow these [instructions](doc/SetupRSync.md) and skip step 7. Otherwise, skip this step.
1. If you are trying to archive on a shared drive, run these commands, subsituting your values for your shared drive:
``` ```
export archiveserver=Nautilus export archiveserver=Nautilus
export sharename=SailfishCam export sharename=SailfishCam
export shareuser=sailfish export shareuser=sailfish
export sharepassword=pa$$w0rd export sharepassword=pa$$w0rd
export campercent=100
``` ```
1. If you'd like to receive a text message when your Pi finishes archiving clips follow these [Instructions](ConfigureNotificationsForArchive.md). 1. If you'd like to receive a text message when your Pi finishes archiving clips follow these [Instructions](doc/ConfigureNotificationsForArchive.md).
1. Run these commands: 1. Run these commands:
``` ```
wget https://raw.githubusercontent.com/cimryan/teslausb/master/windows_archive/setup-teslausb wget https://raw.githubusercontent.com/cimryan/teslausb/master/setup/pi/setup-teslausb
chmod +x setup-teslausb chmod +x setup-teslausb
./setup-teslausb ./setup-teslausb
``` ```
1. Run this command: 1. Run this command:
``` ```
reboot halt
``` ```
1. Disconnect the Pi from the computer.
After reboot, the Pi hostname will become `teslausb`, so future `ssh` sessions will be `ssh pi@teslausb.local`. On the next boot, the Pi hostname will become `teslausb`, so future `ssh` sessions will be `ssh pi@teslausb.local`.
### Get the Pi set up for your Tesla. Your Pi is now ready to be plugged into your Tesla. If you want to add music to the Pi, follow the instructions in the next section.
If you set up the Pi with a keyboard and a monitor disconnect it and connect it to a PC. If you're using a cable be sure to use the port labeled "USB" on the circuitboard.
1. Wait for the Pi to show up on the PC as a USB drive. ## (Optional) Add music to the Pi
1. Create a directory named TeslaCam at the root of the drive labeled CAM. Connect the Pi to a computer. If you're using a cable be sure to use the port labeled "USB" on the circuitboard.
1. Wait for the Pi to show up on the computer as a USB drive.
1. Copy any music you'd like to the drive labeled MUSIC. 1. Copy any music you'd like to the drive labeled MUSIC.
1. Eject the drives. 1. Eject the drives.
1. Unplug the Pi from the PC. 1. Unplug the Pi from the PC.
1. Plug the Pi into your Tesla. 1. Plug the Pi into your Tesla.
## Making changes to the system after setup ## Making changes to the system after setup
The setup process configures the Pi with read-only file systems for the operating system but with read-write access through the USB The setup process configures the Pi with read-only file systems for the operating system but with read-write
interface. This means that you'll be able to record dashcam video and add and remove music files but you won't be able to make changes access through the USB interface. This means that you'll be able to record dashcam video and add and remove
to files on / or on /boot. This is to protect against corruption of the operating system when the Tesla cuts power to the Pi. music files but you won't be able to make changes to files on / or on /boot. This is to protect against
corruption of the operating system when the Tesla cuts power to the Pi.
To make changes to the system partitions: To make changes to the system partitions:
``` ```
ssh pi@teslausb. ssh pi@teslausb.
sudo -i sudo -i
mount / -o remount,rw /root/bin/remountfs_rw
mount /boot -o remount,rw
``` ```
Then make whatever changes you need to. The next time the system boots the partitions will once again be read-only. Then make whatever changes you need to. The next time the system boots the partitions will once again be read-only.

View File

@@ -0,0 +1,35 @@
# Getting a shell on the Pi without a monitor using a Mac or Linux
These instructions will configure a Raspberry Pi so that you can proceed with the next step of setting it up as a smart USB drive for your Tesla. Specifically, these intructions will configure your Pi to join your wireless network and also enable you to ssh to the Pi, either over your wireless network or through a USB connection.
**Important:** Do these steps before you boot the Pi for the first time.
1. Ensure you've flashed your Raspbian image to your SD card.
1. If the `boot` folder isn't showing on your computer, eject and re-insert the SD card into your computer, **not the Raspberry Pi**.
1. Change to the directory where the SD card's `boot` folder (containing `cmdline.txt`) is located. On a Mac, this will be `/Volumes/boot`. On Linux the location may vary; on recent Ubuntu installations it will be /media/$USER/boot
1. Run the following commands:
```
wget https://raw.githubusercontent.com/cimryan/teslausb/master/setup/macos_linux/setup-piForHeadlessConfig.sh
chmod +x setup-piForHeadlessConfig.sh
```
1. Set your SSID (Wifi network name) and WIFIPASS environment variables. The script will insert them into the `wpa_supplicant.conf` when creating it:
```
export SSID=your_ssid_here
export WIFIPASS=your_wifi_password_here
```
1. If you're using a Mac, run this command
```
./setup-piForHeadlessConfig.sh /Volumes/boot
```
1. If you're using Ubuntu, run this command:
```
./setup-piForHeadlessConfig.sh /media/$USER/boot
```
> If you're using another Linux distribution figure out the path to where the boot partitio of the SD card is mounted and specify that path, instead.
1. If all goes well, the script will report:
```
-- Files updated and ready for Wifi and SSH over USB --
```
1. Eject the SD card safely, insert into your Pi, and reboot. If the Pi is connected over USB to your host, and/or if the Wifi setup went correctly, you should be able to `ssh pi@raspberrypi.local`. The default password is `raspberry`.
> Note: If you receive an error indicating that the host id has changed, edit your computer's `~/.ssh/known_hosts` file. Find the line with the IP address of your Pi, or labeled "raspberrypi.local" and delete the entire line. You're especially likely to encounter this error if you're following these instructions for a second time.

View File

@@ -14,7 +14,8 @@
1. Run the following commands: 1. Run the following commands:
``` ```
cd ~ cd ~
wget https://raw.githubusercontent.com/cimryan/teslausb/master/windows_archive/setup-piForHeadlessConfig.ps1 -OutFile setup-piForHeadlessConfig.ps1 wget https://raw.githubusercontent.com/cimryan/teslausb/master/setup/windows/setup-piForHeadlessConfig.ps1 -OutFile setup-piForHeadlessConfig.ps1
wget https://raw.githubusercontent.com/cimryan/teslausb/master/setup/windows/WpaSupplicantConf.psm1 -OutFile WpaSupplicantConf.psm1
./setup-piForHeadlessConfig.ps1 -Verbose ./setup-piForHeadlessConfig.ps1 -Verbose
``` ```
1. Enter the single letter of the "boot" drive and press Enter. 1. Enter the single letter of the "boot" drive and press Enter.

43
doc/SetupRSync.md Normal file
View File

@@ -0,0 +1,43 @@
# Introduction
This guide will show you how to utilize [rsync](https://rsync.samba.org/) to archive your saved TeslaCam footage on a remote storage server. In my case, I use this for a networked pi storage server.
This guide makes the following assumptions:
1. You are running your own ftp/rsync server that you have admin rights to, or can at least add a public key to its `~/.ssh/authorized_keys` file
1. The ftp/rsync server has rsync installed (raspbian automatically does)
2. You have **NOT** run the `setup-teslacam` script yet
# Step 1: Authentication
Similar to sftp, rsync by default utilizes ssh to connect to a remote server and transfer files. This guide will use a generated ssh keypair, hence the first assumption above.
1. On your teslausb pi, run `ssh-keygen` to generate an ssh key **for the ROOT user!** If you followed the previous steps, you should have already ran `sudo -i` to become the root user on the telsausb pi. If you didn't, run `sudo -i` and re-run `ssh-keygen`. You can be sure that it is generating for root if it asks to store the key in `/root/.ssh/` (versus something like `/home/pi/.ssh`).
1. Add the contents of the newly generated `/root/.ssh/id_rsa.pub` file from your teslausb pi to the storage server's `~/.ssh/authorized_keys` file. This will allow a nice and easy connection through rsync, no passwords needed!
1. Lastly, you will need to authorize the connection to the FTP/Rsync server and test that the key works, so try connecting to the server (through ssh), and **if it asks if you wish to continue connecting, make sure to type `yes`!** If you do not do this, rsync will fail to connect and thus fail to archive your clips.
# Step 2: Exports
To be able to configure the teslausb pi use rsync, you'll need to export a few things. On your teslausb pi, run:
```
export RSYNC_ENABLE=true
export RSYNC_USER=<ftp username>
export RSYNC_SERVER=<ftp IP/host>
export RSYNC_PATH=<destination path to save in>
```
Explanations for each:
* `RSYNC_ENABLE`: `true` for enabling rsync
* `RSYNC_USER`: The user on the FTP server
* `RSYNC_SERVER`: The IP address/hostname of the destination machine
* `RSYNC_PATH`: The path on the destination machine where the files will be saved
An example (of my) config is listed below:
```
export RSYNC_ENABLE=true
export RSYNC_USER=pi
export RSYNC_SERVER=192.168.1.254
export RSYNC_PATH=/mnt/PIHDD/TeslaCam/
```
***Note: RSYNC_ENABLE=true is going to disable the default archive server. Perhaps future releases will allow both to be defined and function at the same time, for redundancy, but for now just pick one that you'll want the most.***
You should be ready to run the setup script now, so return back to step 8 of the [Main Instructions](README.md).

View File

@@ -0,0 +1,35 @@
#!/bin/bash -eu
export LOG_FILE=/tmp/archive-teslacam-clips.log
export ARCHIVE_MOUNT=/mnt/archive
function log () {
echo "$( date )" >> "$LOG_FILE"
echo "$1" >> "$LOG_FILE"
}
function disconnect_usb_drives_from_host () {
log "Disconnecting usb from host..."
modprobe -r g_mass_storage
log "Disconnected usb from host."
}
export -f log
log "Starting..."
/root/bin/connect-archive.sh
disconnect_usb_drives_from_host
ensure_cam_file_is_mounted
fix_errors_in_cam_file
/root/bin/archive-clips.sh
/root/bin/disconnect-archive.sh
unmount_cam_file
connect_usb_drives_to_host

View File

@@ -1,7 +1,5 @@
#!/bin/bash -eu #!/bin/bash -eu
ARCHIVE_HOST_NAME="$1"
# Change the value on the right side of the equal sign to the name of the server hosting the archive.
ARCHIVE_HOST_NAME=archiveserver
LOG_FILE=/tmp/archiveloop.log LOG_FILE=/tmp/archiveloop.log

View File

@@ -0,0 +1,18 @@
#!/bin/bash -eu
log "Moving clips to archive..."
NUM_FILES_MOVED=0
for file_name in "$CAM_MOUNT"/TeslaCam/saved*; do
[ -e "$file_name" ] || continue
log "Moving $file_name ..."
mv -- "$file_name" "$ARCHIVE_MOUNT" >> "$LOG_FILE" 2>&1 || echo ""
log "Moved $file_name."
NUM_FILES_MOVED=$((NUM_FILES_MOVED + 1))
done
log "Moved $NUM_FILES_MOVED file(s)."
/root/bin/send-pushover "$NUM_FILES_MOVED"
log "Finished moving clips to archive."

View File

@@ -0,0 +1,26 @@
#!/bin/bash -eu
function configure_archive () {
local archive_server_ip_address="$1"
echo "Configuring the archive..."
local archive_path="/mnt/archive"
if [ ! -e "$archive_path" ]
then
mkdir "$archive_path"
fi
local credentials_file_path="/root/.teslaCamArchiveCredentials"
/root/bin/write-archive-credentials-to.sh "$credentials_file_path"
echo "//$archive_server_ip_address/$sharename $archive_path cifs vers=${cifs_version},credentials=${credentials_file_path},iocharset=utf8,file_mode=0777,dir_mode=0777 0" >> /etc/fstab
echo "Configured the archive."
}
ARCHIVE_SERVER_IP_ADDRESS="$( /root/bin/get-archiveserver-ip-address.sh )"
configure_archive "$ARCHIVE_SERVER_IP_ADDRESS"

View File

@@ -0,0 +1,9 @@
#!/bin/bash -eu
function ensure_archive_is_mounted () {
log "Ensuring cam archive is mounted..."
ensure_mountpoint_is_mounted_with_retry "$ARCHIVE_MOUNT"
log "Ensured cam archive is mounted."
}
ensure_archive_is_mounted

View File

@@ -0,0 +1,2 @@
#!/bin/bash -eu
# Nothing to do. It's okay to leave the archive mounted.

View File

@@ -0,0 +1,47 @@
#!/bin/bash -eu
function check_archive_server_reachable () {
echo "Verifying that the archive server $archiveserver is reachable..."
local serverunreachable=false
ping -c 1 -w 1 "$archiveserver" 1>/dev/null 2>&1 || serverunreachable=true
if [ "$serverunreachable" = true ]
then
echo "STOP: The archive server $archiveserver is unreachable. Try specifying its IP address instead."
exit 1
fi
echo "The archive server is reachable."
}
function check_archive_mountable () {
local archive_server_ip_address="$1"
local test_mount_location="/tmp/archivetestmount"
if [ ! -e "$test_mount_location" ]
then
mkdir "$test_mount_location"
fi
local tmp_credentials_file_path="/tmp/teslaCamArchiveCredentials"
/root/bin/write-archive-credentials-to.sh "$tmp_credentials_file_path"
local mount_failed=false
mount -t cifs "//$archive_server_ip_address/$sharename" "$test_mount_location" -o "vers=${cifs_version},credentials=${tmp_credentials_file_path},iocharset=utf8,file_mode=0777,dir_mode=0777" || mount_failed=true
if [ "$mount_failed" = true ]
then
echo "STOP: The archive couldn't be mounted with CIFS version ${cifs_version}. Try specifying a lower number for the CIFS version like this: export cifs_version=2"
exit 1
fi
umount "$test_mount_location"
}
check_archive_server_reachable
ARCHIVE_SERVER_IP_ADDRESS="$( /root/bin/get-archiveserver-ip-address.sh )"
check_archive_mountable "$ARCHIVE_SERVER_IP_ADDRESS"

View File

@@ -0,0 +1,6 @@
#!/bin/bash -eu
FILE_PATH="$1"
echo "username=$shareuser" > "$FILE_PATH"
echo "password=$sharepassword" >> "$FILE_PATH"

View File

@@ -0,0 +1,3 @@
#!/bin/bash -eu
echo "$(ping -c 1 -w 1 $archiveserver 2>/dev/null | head -n 1 | grep -o -e "(\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\})" | tr -d '()')"

View File

@@ -0,0 +1,16 @@
#!/bin/bash -eu
log "Archiving through rsync..."
source /root/.teslaCamRsyncConfig
num_files_moved=$(rsync -auvh --stats --log-file=/tmp/archive-rsync-cmd.log /mnt/cam/TeslaCam/saved* $user@$server:$path | awk '/files transferred/{print $NF}')
/root/bin/send-pushover "$num_files_moved"
if [ $num_files_moved > 0 ]
then
log "Successfully synced files through rsync."
else
log "No files to archive through rsync."
fi

View File

@@ -0,0 +1,16 @@
#!/bin/bash -eu
function configure_archive () {
local archive_server_ip_address="$1"
echo "Configuring the archive..."
echo "Configuring for Rsync..."
echo "user=$RSYNC_USER" > /root/.teslaCamRsyncConfig
echo "server=$RSYNC_SERVER" >> /root/.teslaCamRsyncConfig
echo "path=$RSYNC_PATH" >> /root/.teslaCamRsyncConfig
}
ARCHIVE_SERVER_IP_ADDRESS="$( /root/bin/get-archiveserver-ip-address.sh )"
configure_archive "$ARCHIVE_SERVER_IP_ADDRESS"

View File

@@ -0,0 +1,2 @@
#!/bin/bash -eu
# Nothing to do.

View File

@@ -0,0 +1,2 @@
#!/bin/bash -eu
# Nothing to do.

View File

@@ -0,0 +1 @@
#!/bin/bash -eu

21
run/send-pushover Normal file
View File

@@ -0,0 +1,21 @@
#!/bin/bash -eu
NUM_FILES_MOVED="$1"
function log () {
echo "$( date )" >> "$LOG_FILE"
echo "$1" >> "$LOG_FILE"
}
if [ -r "/root/.teslaCamPushoverCredentials" ] && [ $NUM_FILES_MOVED > 0]
then
log "Sending Pushover message for moved files."
source /root/.teslaCamPushoverCredentials
curl -F "token=$pushover_app_key" \
-F "user=$pushover_user_key" \
-F "title=Dashcam Copy Complete" \
-F "message=$NUM_FILES_MOVED file(s) were copied." \
https://api.pushover.net/1/messages
fi

View File

@@ -21,6 +21,12 @@ function add_drive () {
echo "$filename $mountpoint vfat noauto,users,umask=000 0 0" >> /etc/fstab echo "$filename $mountpoint vfat noauto,users,umask=000 0 0" >> /etc/fstab
} }
function create_teslacam_directory () {
mount /mnt/cam
mkdir /mnt/cam/TeslaCam
umount /mnt/cam
}
FREE_1K_BLOCKS="$(df --output=avail --block-size=1K /backingfiles/ | tail -n 1)" FREE_1K_BLOCKS="$(df --output=avail --block-size=1K /backingfiles/ | tail -n 1)"
CAM_DISK_SIZE="$(( $FREE_1K_BLOCKS * $CAM_PERCENT / 100 ))" CAM_DISK_SIZE="$(( $FREE_1K_BLOCKS * $CAM_PERCENT / 100 ))"
@@ -36,3 +42,5 @@ then
else else
echo "options g_mass_storage file=$CAM_DISK_FILE_NAME removable=1 ro=0 stall=0 iSerialNumber=123456" > "$G_MASS_STORAGE_CONF_FILE_NAME" echo "options g_mass_storage file=$CAM_DISK_FILE_NAME removable=1 ro=0 stall=0 iSerialNumber=123456" > "$G_MASS_STORAGE_CONF_FILE_NAME"
fi fi
create_teslacam_directory

247
setup/pi/setup-teslausb Normal file
View File

@@ -0,0 +1,247 @@
#!/bin/bash -eu
USER_ENABLED_PUSHOVER=false
REPO=${REPO:-cimryan}
BRANCH=${BRANCH:-master}
if ! [ $(id -u) = 0 ]
then
echo "STOP: Run sudo -i."
exit 1
fi
function check_variable () {
local var_name="$1"
if [ -z "${!var_name+x}" ]
then
echo "STOP: Define the variable $var_name like this: export $var_name=value"
exit 1
fi
}
function check_pushover_enabled () {
if [ ! -z "${pushover_enabled+x}" ]
then
if [ ! -n "${pushover_user_key+x}" ] || [ ! -n "${pushover_app_key+x}" ]
then
echo "STOP: You're trying to setup Pushover but didn't provide your User and/or App key."
echo "Define the variables like this:"
echo "export pushover_user_key=put_your_userkey_here"
echo "export pushover_app_key=put_your_appkey_here"
exit 1
elif [ "${pushover_user_key}" = "put_your_userkey_here" ] || [ "${pushover_app_key}" = "put_your_appkey_here" ]
then
echo "STOP: You're trying to setup Pushover, but didn't replace the default User and App key values."
exit 1
else
USER_ENABLED_PUSHOVER=true
echo "export pushover_enabled=true" > /root/.teslaCamPushoverCredentials
echo "export pushover_user_key=$pushover_user_key" >> /root/.teslaCamPushoverCredentials
echo "export pushover_app_key=$pushover_app_key" >> /root/.teslaCamPushoverCredentials
fi
fi
}
function check_available_space () {
echo "Verifying that there is sufficient space available on the MicroSD card..."
local available_space="$( parted -m /dev/mmcblk0 u b print free | tail -1 | cut -d ":" -f 4 | sed 's/B//g' )"
if [ "$available_space" -lt 4294967296 ]
then
echo "STOP: The MicroSD card is too small."
exit 1
fi
echo "There is sufficient space available."
}
function get_script () {
local local_path="$1"
local name="$2"
local remote_path="${3:-}"
wget -O "$local_path/$name" https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/"$remote_path"/"$name"
chmod +x "$local_path/$name"
}
function get_ancillary_setup_scripts () {
get_script /tmp create-backingfiles-partition.sh setup/pi
get_script /tmp create-backingfiles.sh setup/pi
get_script /tmp make-root-fs-readonly.sh setup/pi
}
function fix_cmdline_txt_modules_load ()
{
echo "Fixing the modules-load parameter in /boot/cmdline.txt..."
cp /boot/cmdline.txt ~
cat ~/cmdline.txt | sed 's/ modules-load=dwc2,g_ether/ modules-load=dwc2/' > /boot/cmdline.txt
rm ~/cmdline.txt
echo "Fixed cmdline.txt."
}
BACKINGFILES_MOUNTPOINT=/backingfiles
function create_usb_drive_backing_files () {
if [ ! -e "$BACKINGFILES_MOUNTPOINT" ]
then
mkdir "$BACKINGFILES_MOUNTPOINT"
fi
if [ ! -e /dev/mmcblk0p3 ]
then
/tmp/create-backingfiles-partition.sh "$BACKINGFILES_MOUNTPOINT"
fi
if ! findmnt --mountpoint /backingfiles
then
echo "Mounting the partition for the backing files..."
mount /backingfiles
echo "Mounted the partition for the backing files."
fi
if [ ! -e /backingfiles/*.bin ]
then
/tmp/create-backingfiles.sh "$campercent" "$BACKINGFILES_MOUNTPOINT"
fi
}
function configure_archive_scripts () {
echo "Configuring the archive scripts..."
get_script /root/bin archiveloop run
get_script /root/bin archive-teslacam-clips run
if [ $RSYNC_ENABLE = true ]
then
get_script /root/bin archive-clips.sh run/rsync_archive
get_script /root/bin connect-archive.sh run/rsync_archive
get_script /root/bin disconnect-archive.sh run/rsync_archive
else
get_script /root/bin archive-clips.sh run/cifs_archive
get_script /root/bin connect-archive.sh run/cifs_archive
get_script /root/bin disconnect-archive.sh run/cifs_archive
fi
get_script /root/bin remountfs_rw run
echo "Configured the archive scripts."
}
function configure_pushover_scripts() {
get_script /root/bin send-pushover run
}
function configure_rc_local () {
if grep -q archiveloop /etc/rc.local
then
return
fi
echo "Configuring /etc/rc.local to run the archive scripts at startup..."
echo "#!/bin/bash -eu" > ~/rc.local
echo "archiveserver=\"${archiveserver}\"" >> ~/rc.local
cat << 'EOF' >> ~/rc.local
LOGFILE=/tmp/rc.local.log
function log () {
echo "$( date )" >> "$LOGFILE"
echo "$1" >> "$LOGFILE"
}
log "Launching archival script..."
/root/bin/archiveloop "$archiveserver" &
log "All done"
exit 0
EOF
cat ~/rc.local > /etc/rc.local
rm ~/rc.local
echo "Configured rc.local."
}
function configure_hostname () {
echo "Configuring the hostname..."
local new_host_name="teslausb"
cp /etc/hosts ~
sed "s/raspberrypi/$new_host_name/g" ~/hosts > /etc/hosts
cp /etc/hostname ~
sed "s/raspberrypi/$new_host_name/g" ~/hostname > /etc/hostname
echo "Configured the hostname."
}
function make_root_fs_readonly () {
/tmp/make-root-fs-readonly.sh
}
echo "Verifying environment variables..."
RSYNC_ENABLE="${RSYNC_ENABLE:-false}"
if [ "$RSYNC_ENABLE" = true ]
then
check_variable "RSYNC_USER"
check_variable "RSYNC_SERVER"
export archiveserver="$RSYNC_SERVER"
check_variable "RSYNC_PATH"
else # Else for now, TODO allow both for more redundancy?
check_variable "sharename"
check_variable "shareuser"
check_variable "sharepassword"
export cifs_version="${cifs_version:-3}"
fi
check_variable "archiveserver"
check_variable "campercent"
check_pushover_enabled
if [ ! -e /root/bin ]
then
mkdir /root/bin
fi
if [ "$RSYNC_ENABLE" = true ]
then
get_script /root/bin verify-archive-configuration.sh run/rsync_archive
get_script /root/bin configure-archive.sh run/rsync_archive
else
get_script /root/bin verify-archive-configuration.sh run/cifs_archive
get_script /root/bin configure-archive.sh run/cifs_archive
get_script /root/bin write-archive-credentials-to.sh run/cifs_archive
fi
get_script /root/bin get-archiveserver-ip-address.sh run
/root/bin/verify-archive-configuration.sh
check_available_space
get_ancillary_setup_scripts
pushd ~
configure_archive_scripts
configure_pushover_scripts
fix_cmdline_txt_modules_load
echo "" >> /etc/fstab
create_usb_drive_backing_files
/root/bin/configure-archive.sh
configure_rc_local
configure_hostname
make_root_fs_readonly
echo "All done."

View File

@@ -0,0 +1,91 @@
function Write-Header {
param(
[string]$driveLetter
)
$header=@"
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
"@
Set-WpaSupplicantConfContent "$driveLetter" "$header"
}
function Add-Network {
param(
[string]$driveLetter,
[string]$wifiSSID,
[string]$wifiPSK
)
$network=@"
network={
ssid="$wifiSSID"
psk="$wifiPSK"
}
"@
Add-WpaSupplicantConfContent "$driveLetter" "$network"
}
function Set-WpaSupplicantConfContent {
param(
[string]$driveLetter,
[string]$content
)
$wpaSupplicantConfPath = Get-WpaSupplicantConfPath $driveLetter
$encodedContent = Encode-Content $content
Set-Content -Value $encodedContent -Encoding Byte -Path "$wpaSupplicantConfPath"
}
function Add-WpaSupplicantConfContent {
param(
[string]$driveLetter,
[string]$content
)
$wpaSupplicantConfPath = Get-WpaSupplicantConfPath $driveLetter
$encodedContent = Encode-Content $content
Add-Content -Value $encodedContent -Encoding Byte -Path "$wpaSupplicantConfPath"
}
function Verify-WpaSupplicantConfPath {
param(
[string]$driveLetter
)
$drivePath="${driveLetter}:"
$configPath = "$drivePath\config.txt"
$cmdlinePath = "$drivePath\cmdline.txt"
$sshPath = "$drivePath\ssh"
if ((![System.IO.File]::Exists($configPath) -or
(![System.IO.File]::Exists($cmdlinePath)))) {
Write-Error "Didn't find cmdline.txt and config.txt on drive $drivePath."
exit 1
}
}
function Encode-Content {
param(
[string]$content
)
$utf8 = New-Object System.Text.UTF8Encoding $false
return $utf8.GetBytes($content)
}
function Get-WpaSupplicantConfPath {
param(
[string]$driveLetter
)
Verify-WpaSupplicantConfPath $driveLetter
return "${driveLetter}:\wpa_supplicant.conf"
}
Export-ModuleMember -Function Write-Header
Export-ModuleMember -Function Add-Network

View File

@@ -0,0 +1,18 @@
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$True,Position=1)]
[string]$driveLetter,
[Parameter(Mandatory=$True,Position=2)]
[string]$wifiSSID,
[Parameter(Mandatory=$True,Position=3)]
[string]$wifiPSK
)
Import-Module -Name ".\WpaSupplicantConf.psm1" -Force
Add-Network "$driveLetter" "$wifiSSID" "$wifiPSK"
Write-Verbose "All done."

View File

@@ -11,6 +11,8 @@ Param
[string]$wifiPSK [string]$wifiPSK
) )
Import-Module -Name ".\WpaSupplicantConf.psm1" -Force
$drivePath="${driveLetter}:" $drivePath="${driveLetter}:"
$configPath = "$drivePath\config.txt" $configPath = "$drivePath\config.txt"
$cmdlinePath = "$drivePath\cmdline.txt" $cmdlinePath = "$drivePath\cmdline.txt"
@@ -34,28 +36,9 @@ $cmdlinetxtContent.Replace("rootwait", "rootwait modules-load=dwc2,g_ether").Rep
Write-Verbose "Enabling SSH ..." Write-Verbose "Enabling SSH ..."
[System.IO.File]::CreateText($sshPath).Dispose() [System.IO.File]::CreateText($sshPath).Dispose()
# Sets up wifi credentials so wifi will be
# auto configured on first boot
$wpaSupplicantConfPath="$drivePath\wpa_supplicant.conf"
Write-Verbose "(Re)creating WiFi configuration file $wpaSupplicantConfPath." Write-Verbose "(Re)creating WiFi configuration file $wpaSupplicantConfPath."
if ([System.IO.File]::Exists("$wpaSupplicantConfPath")) {
del "$wpaSupplicantConfPath"
}
$wpaSupplicantConfContent=@" Write-Header "$driveLetter"
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev Add-Network "$driveLetter" "$wifiSSID" "$wifiPSK"
update_config=1
network={
ssid="$wifiSSID"
psk="$wifiPSK"
}
"@
$utf8 = New-Object System.Text.UTF8Encoding $false
Set-Content -Value $utf8.GetBytes($wpaSupplicantConfContent) -Encoding Byte -Path "$wpaSupplicantConfPath"
Write-Verbose "All done." Write-Verbose "All done."

View File

@@ -1,57 +0,0 @@
#!/bin/bash -eu
LOG_FILE=/tmp/archive-teslacam-clips.log
ARCHIVE_MOUNT=/mnt/archive
function log () {
echo "$( date )" >> "$LOG_FILE"
echo "$1" >> "$LOG_FILE"
}
function move_clips_to_archive () {
log "Moving clips to archive..."
local move_count=0
for file_name in "$CAM_MOUNT"/TeslaCam/saved*; do
[ -e "$file_name" ] || continue
log "Moving $file_name ..."
mv -- "$file_name" "$ARCHIVE_MOUNT" >> "$LOG_FILE" 2>&1 || echo ""
log "Moved $file_name."
move_count=$((move_count + 1))
done
log "Moved $move_count file(s)."
if [ -r "/root/.teslaCamPushoverCredentials" ] && [ $move_count > 0 ]
then
log "Sending Pushover message for copied files."
/root/bin/send-pushover $move_count
fi
log "Finished moving clips to archive."
}
function disconnect_usb_drives_from_host () {
log "Disconnecting usb from host..."
modprobe -r g_mass_storage
log "Disconnected usb from host."
}
function ensure_archive_is_mounted () {
log "Ensuring cam archive is mounted..."
ensure_mountpoint_is_mounted_with_retry "$ARCHIVE_MOUNT"
log "Ensured cam archive is mounted."
}
log "Starting..."
ensure_archive_is_mounted
disconnect_usb_drives_from_host
ensure_cam_file_is_mounted
fix_errors_in_cam_file
move_clips_to_archive
unmount_cam_file
connect_usb_drives_to_host

View File

@@ -1,14 +0,0 @@
#!/bin/bash -eu
function log () {
echo "$( date )" >> "$LOG_FILE"
echo "$1" >> "$LOG_FILE"
}
source /root/.teslaCamPushoverCredentials
curl -F "token=$pushover_app_key" \
-F "user=$pushover_user_key" \
-F "title=Dashcam Copy Complete" \
-F "message=$1 file(s) were copied." \
https://api.pushover.net/1/messages

View File

@@ -1,31 +0,0 @@
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$True,Position=1)]
[string]$driveLetter,
[Parameter(Mandatory=$True,Position=2)]
[string]$wifiSSID,
[Parameter(Mandatory=$True,Position=3)]
[string]$wifiPSK
)
$drivePath="${driveLetter}:"
$wpaSupplicantConfPath="$drivePath\wpa_supplicant.conf"
$wpaSupplicantConfContent=@"
network={
ssid="$wifiSSID"
psk="$wifiPSK"
}
"@
$utf8 = New-Object System.Text.UTF8Encoding $false
Add-Content -Value $utf8.GetBytes($wpaSupplicantConfContent) -Encoding Byte -Path "$wpaSupplicantConfPath"
Write-Verbose "All done."

View File

@@ -1,281 +0,0 @@
#!/bin/bash -eu
USER_ENABLED_PUSHOVER=false
REPO=${REPO:-cimryan}
BRANCH=${BRANCH:-master}
if ! [ $(id -u) = 0 ]
then
echo "STOP: Run sudo -i."
exit 1
fi
function check_variable () {
local var_name="$1"
if [ -z "${!var_name+x}" ]
then
echo "STOP: Define the variable $var_name like this: export $var_name=value"
exit 1
fi
}
function check_pushover_enabled () {
if [ ! -z "${pushover_enabled+x}" ]
then
if [ ! -n "${pushover_user_key+x}" ] || [ ! -n "${pushover_app_key+x}" ]
then
echo "STOP: You're trying to setup Pushover but didn't provide your User and/or App key."
echo "Define the variables like this:"
echo "export pushover_user_key=put_your_userkey_here"
echo "export pushover_app_key=put_your_appkey_here"
exit 1
elif [ "${pushover_user_key}" = "put_your_userkey_here" ] || [ "${pushover_app_key}" = "put_your_appkey_here" ]
then
echo "STOP: You're trying to setup Pushover, but didn't replace the default User and App key values."
exit 1
else
USER_ENABLED_PUSHOVER=true
echo "export pushover_enabled=true" > /root/.teslaCamPushoverCredentials
echo "export pushover_user_key=$pushover_user_key" >> /root/.teslaCamPushoverCredentials
echo "export pushover_app_key=$pushover_app_key" >> /root/.teslaCamPushoverCredentials
fi
fi
}
function check_archive_server_reachable () {
echo "Verifying that the archive server $archiveserver is reachable..."
local serverunreachable=false
ping -c 1 -w 1 "$archiveserver" 1>/dev/null 2>&1 || serverunreachable=true
if [ "$serverunreachable" = true ]
then
echo "STOP: The archive server $archiveserver is unreachable. Try specifying its IP address instead."
exit 1
fi
echo "The archive server is reachable."
}
function write_archive_credentials_to () {
local file_path="$1"
echo "username=$shareuser" > "$file_path"
echo "password=$sharepassword" >> "$file_path"
}
function check_archive_mountable () {
local archive_server_ip_address="$1"
local test_mount_location="/tmp/archivetestmount"
if [ ! -e "$test_mount_location" ]
then
mkdir "$test_mount_location"
fi
local tmp_credentials_file_path="/tmp/teslaCamArchiveCredentials"
write_archive_credentials_to "$tmp_credentials_file_path"
local mount_failed=false
mount -t cifs "//$archive_server_ip_address/$sharename" "$test_mount_location" -o "vers=${cifs_version},credentials=${tmp_credentials_file_path},iocharset=utf8,file_mode=0777,dir_mode=0777" || mount_failed=true
if [ "$mount_failed" = true ]
then
echo "STOP: The archive couldn't be mounted with CIFS version ${cifs_version}. Try specifying a lower number for the CIFS version like this: export cifs_version=2"
exit 1
fi
umount "$test_mount_location"
}
function check_available_space () {
echo "Verifying that there is sufficient space available on the MicroSD card..."
local available_space="$( parted -m /dev/mmcblk0 u b print free | tail -1 | cut -d ":" -f 4 | sed 's/B//g' )"
if [ "$available_space" -lt 4294967296 ]
then
echo "STOP: The MicroSD card is too small."
exit 1
fi
echo "There is sufficient space available."
}
function get_ancillary_setup_scripts () {
pushd /tmp
wget https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/windows_archive/create-backingfiles-partition.sh
chmod +x ./create-backingfiles-partition.sh
wget https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/windows_archive/create-backingfiles.sh
chmod +x ./create-backingfiles.sh
wget https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/windows_archive/make-root-fs-readonly.sh
chmod +x ./make-root-fs-readonly.sh
popd
}
function fix_cmdline_txt_modules_load ()
{
echo "Fixing the modules-load parameter in /boot/cmdline.txt..."
cp /boot/cmdline.txt ~
cat ~/cmdline.txt | sed 's/[[:space:]]\+modules-load=[^ [:space:]]\+//' | sed 's/rootwait/rootwait modules-load=dwc2/' > /boot/cmdline.txt
rm ~/cmdline.txt
echo "Fixed cmdline.txt."
}
BACKINGFILES_MOUNTPOINT=/backingfiles
function create_usb_drive_backing_files () {
mkdir "$BACKINGFILES_MOUNTPOINT"
/tmp/create-backingfiles-partition.sh "$BACKINGFILES_MOUNTPOINT"
echo "Mounting the partition for the backing files..."
mount /backingfiles
echo "Mounted the partition for the backing files."
/tmp/create-backingfiles.sh "$campercent" "$BACKINGFILES_MOUNTPOINT"
}
function configure_archive () {
local archive_server_ip_address="$1"
echo "Configuring the archive..."
local archive_path="/mnt/archive"
if [ ! -e "$archive_path" ]
then
mkdir "$archive_path"
fi
local credentials_file_path="/root/.teslaCamArchiveCredentials"
write_archive_credentials_to "$credentials_file_path"
echo "//$archive_server_ip_address/$sharename $archive_path cifs vers=${cifs_version},credentials=${credentials_file_path},iocharset=utf8,file_mode=0777,dir_mode=0777 0" >> /etc/fstab
echo "Configured the archive."
}
function configure_archive_scripts () {
echo "Configuring the archive scripts..."
mkdir /root/bin
pushd ~
wget https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/windows_archive/archiveloop
sed s/ARCHIVE_HOST_NAME=archiveserver/ARCHIVE_HOST_NAME=$archiveserver/ ~/archiveloop > /root/bin/archiveloop
rm ~/archiveloop
chmod +x /root/bin/archiveloop
popd
pushd /root/bin
wget https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/windows_archive/archive-teslacam-clips
chmod +x archive-teslacam-clips
popd
echo "Configured the archive scripts."
pushd /root
wget https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/windows_archive/remountfs_rw
chmod +x remountfs_rw
popd
echo "Downloaded script to remount filesystems read/write if needed (/root/remountfs_rw)."
}
function configure_pushover_scripts() {
if [ ${USER_ENABLED_PUSHOVER} = "true" ]
then
pushd /root/bin
wget https://raw.githubusercontent.com/"$REPO"/teslausb/"$BRANCH"/windows_archive/send-pushover
chmod +x send-pushover
popd
fi
}
function configure_rc_local () {
echo "Configuring /etc/rc.local to run the archive scripts at startup..."
echo "#!/bin/bash -eu" > ~/rc.local
tail -n +2 /etc/rc.local | sed '$d' >> ~/rc.local
cat << 'EOF' >> ~/rc.local
LOGFILE=/tmp/rc.local.log
function log () {
echo "$( date )" >> "$LOGFILE"
echo "$1" >> "$LOGFILE"
}
log "Launching archival script..."
/root/bin/archiveloop &
log "All done"
exit 0
EOF
cat ~/rc.local > /etc/rc.local
rm ~/rc.local
echo "Configured rc.local."
}
function configure_hostname () {
echo "Configuring the hostname..."
local new_host_name="teslausb"
cp /etc/hosts ~
sed "s/raspberrypi/$new_host_name/g" ~/hosts > /etc/hosts
cp /etc/hostname ~
sed "s/raspberrypi/$new_host_name/g" ~/hostname > /etc/hostname
echo "Configured the hostname."
}
function make_root_fs_readonly () {
/tmp/make-root-fs-readonly.sh
}
echo "Verifying environment variables..."
if [ ! -n "${cifs_version+x}" ]
then
cifs_version=3
fi
check_variable "archiveserver"
check_variable "sharename"
check_variable "shareuser"
check_variable "sharepassword"
check_variable "campercent"
check_pushover_enabled
check_archive_server_reachable
ARCHIVE_SERVER_IP_ADDRESS="$(ping -c 1 -w 1 $archiveserver 2>/dev/null | head -n 1 | grep -o -e "(\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\})" | tr -d '()')"
check_archive_mountable "$ARCHIVE_SERVER_IP_ADDRESS"
check_available_space
get_ancillary_setup_scripts
pushd ~
configure_archive_scripts
configure_pushover_scripts
fix_cmdline_txt_modules_load
echo "" >> /etc/fstab
create_usb_drive_backing_files
configure_archive "$ARCHIVE_SERVER_IP_ADDRESS"
configure_rc_local
configure_hostname
make_root_fs_readonly
echo "All done."