From d1ffe404b13fd70ee53e1dbe9aa2bee3ca06dffc Mon Sep 17 00:00:00 2001 From: zephyrus9MA <67062520+zephyrus9MA@users.noreply.github.com> Date: Sat, 4 Jul 2020 20:52:09 -0700 Subject: [PATCH 1/7] Add files via upload --- lib/NotifyLib/Mail.go | 59 ++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/lib/NotifyLib/Mail.go b/lib/NotifyLib/Mail.go index ec35bee..194cea6 100644 --- a/lib/NotifyLib/Mail.go +++ b/lib/NotifyLib/Mail.go @@ -1,29 +1,30 @@ -package NotifyLib - -import ( - "fmt" - "log" - "net/smtp" - "strconv" -) - -// SendMail ... -func SendMail(logger *log.Logger, mailServer string, mailServerPort int, mailServerLogin string, mailServerPassword string, fromAddress string, toAddress string, subj string, body string) error { - // Set up authentication information. - var auth smtp.Auth - if len(mailServerLogin) > 0 { - auth = smtp.PlainAuth("", mailServerLogin, mailServerPassword, mailServer) - } - - // Connect to the server, authenticate, set the sender and recipient, and send the email in one step. - to := []string{toAddress} - msg := []byte("To: " + toAddress + "\r\nSubject: " + subj + "\r\n\r\n" + body + "\r\n") - serverPort := mailServer + ":" + strconv.Itoa(mailServerPort) - logger.Printf("Sending mail via server %s\n", serverPort) - err := smtp.SendMail(serverPort, auth, fromAddress, to, msg) - if err != nil { - return fmt.Errorf("sendMail error: %s", err) - } - - return nil -} +package NotifyLib +// Add second to address. Most mail servers require a FROM: address. This was added to the message by Lee Elson on 6/29/20 + +import ( + "fmt" + "log" + "net/smtp" + "strconv" +) + +// SendMail ... +func SendMail(logger *log.Logger, mailServer string, mailServerPort int, mailServerLogin string, mailServerPassword string, fromAddress string, toAddress1 string, toAddress2 string, subj string, body string) error { + // Set up authentication information. + var auth smtp.Auth + if len(mailServerLogin) > 0 { + auth = smtp.PlainAuth("", mailServerLogin, mailServerPassword, mailServer) + } + + // Connect to the server, authenticate, set the sender and recipient, and send the email in one step. + //LSE set up second To email address + to := []string{toAddress1, toAddress2} + msg := []byte("To: " + toAddress1 + "\r\nFrom: " + fromAddress + "\r\nSubject: " + subj + "\r\n" + body + "\r\n") + serverPort := mailServer + ":" + strconv.Itoa(mailServerPort) + err := smtp.SendMail(serverPort, auth, fromAddress, to, msg) + if err != nil { + return fmt.Errorf("sendMail error: %s", err) + } + + return nil +} From 1d068c92754faa4e0411a2434a28c9ced2b1e269 Mon Sep 17 00:00:00 2001 From: zephyrus9MA <67062520+zephyrus9MA@users.noreply.github.com> Date: Sat, 4 Jul 2020 20:52:41 -0700 Subject: [PATCH 2/7] Add files via upload --- TeslaCommand.go | 388 ++++++++++++++++++++++++++---------------------- readme.md | 74 +++++---- 2 files changed, 255 insertions(+), 207 deletions(-) diff --git a/TeslaCommand.go b/TeslaCommand.go index 9903f92..d96fb5b 100644 --- a/TeslaCommand.go +++ b/TeslaCommand.go @@ -1,179 +1,209 @@ -// -// Brett Morrison, Februrary 2016 -// -// A program to alert if Tesla is not plugged in at a specified GeoFence -// -package main - -import ( - "TeslaCommand/lib/HaversinFormula" - "TeslaCommand/lib/NotifyLib" - "flag" - "fmt" - "io" - "log" - "os" - "time" - - tesla "github.com/jsgoecke/tesla" -) - -// Magic clientid and clientsecret available here: http://pastebin.com/fX6ejAHd -const clientid = "e4a9949fcfa04068f59abb5a658f2bac0a3428e4652315490b659d5ab3f35a9e" -const clientsecret = "c75f14bbadc8bee3a7594412c31416f8300256d7668ea7e6e7f06727bfb9d220" - -var teslaLoginEmail string -var teslaLoginPassword string -var vehicleIndex int -var geoFenceLatitude float64 -var geoFenceLongitude float64 -var mailServer string -var mailServerPort int -var mailServerLogin string -var mailServerPassword string -var fromAddress string -var toAddress string -var twilioSID string -var twilioToken string -var senderPhoneNumber string -var recipientPhoneNumber string -var radius int -var checkInterval int -var alertThreshold int - -func init() { - flag.StringVar(&teslaLoginEmail, "teslaLoginEmail", "", "Email for teslamotors.com account") - flag.StringVar(&teslaLoginPassword, "teslaLoginPassword", "", "Password for teslamotors.com account") - flag.IntVar(&vehicleIndex, "vehicleIndex", 0, "Index of vehicles in your account - If just 1 vehicle, use 0") - flag.Float64Var(&geoFenceLatitude, "geoFenceLatitude", 0.0, "Latitude of GeoFence Center") - flag.Float64Var(&geoFenceLongitude, "geoFenceLongitude", 0.0, "Longitude of GeoFence Center") - flag.StringVar(&mailServer, "mailServer", "", "SMTP Server hostname") - flag.IntVar(&mailServerPort, "mailServerPort", 25, "SMTP Server port number") - flag.StringVar(&mailServerLogin, "mailServerLogin", "", "SMTP Server login username") - flag.StringVar(&mailServerPassword, "mailServerPassword", "", "SMTP Server password") - flag.StringVar(&fromAddress, "fromAddress", "", "Alert send from email") - flag.StringVar(&toAddress, "toAddress", "", "Alert send to email") - flag.StringVar(&twilioSID, "twilioSID", "", "Twilio SID") - flag.StringVar(&twilioToken, "twilioToken", "", "Twilio Token") - flag.StringVar(&senderPhoneNumber, "senderPhoneNumber", "", "Sender Phone Number") - flag.StringVar(&recipientPhoneNumber, "recipientPhoneNumber", "", "Recipient Phone Number") - flag.IntVar(&radius, "radius", 0, "Radius in meters from center geoFence - Typically use 200") - flag.IntVar(&checkInterval, "checkInterval", 300, "Time in seconds between checks for geoFence") - flag.IntVar(&alertThreshold, "alertThreshold", 50, "Percentage charged threshold to send alert. If charge level is above threshold, alert won't be sent") -} - -func main() { - // Setup Logging - logFileName := fmt.Sprintf("TeslaCommand-%v.log", time.Now().Unix()) - logf, err := os.OpenFile(logFileName, os.O_WRONLY|os.O_CREATE, 0640) - if err != nil { - log.Fatalln(err) - } - defer logf.Close() - - log.SetOutput(logf) - logger := log.New(io.MultiWriter(logf, os.Stdout), "TeslaCommand: ", log.Lshortfile|log.LstdFlags) - - logger.Printf("Num Args %d\n", len(os.Args)) - flag.Parse() - if len(os.Args) != 19 { - flag.Usage() - os.Exit(1) - } - - client, err := tesla.NewClient(&tesla.Auth{ClientID: clientid, ClientSecret: clientsecret, Email: teslaLoginEmail, Password: teslaLoginPassword}) - if err != nil { - logger.Println(err) - os.Exit(1) - } - //logger.Println("token: " + li.Token) - - vehicles, err := client.Vehicles() - if err != nil { - logger.Println(err) - os.Exit(1) - } - - vehicle := vehicles[vehicleIndex] - - vehicleState, err := vehicle.VehicleState() - if err != nil { - logger.Println(err) - os.Exit(1) - } - - // Need to set this flag for every time vehicle exits and enters GeoFence (so we don't send repeated alerts) - ingeofenceandstopped := false - waitmessage := fmt.Sprintf("Waiting to check vehicle %v location for %v seconds...\n", vehicleState.VehicleName, checkInterval) - - // Loop every N seconds. - logger.Printf(waitmessage) - for _ = range time.Tick(time.Duration(checkInterval) * time.Second) { - logger.Printf("Checking vehicle %v location after waiting %v seconds.\n", vehicleState.VehicleName, checkInterval) - - driveState, err := vehicle.DriveState() - if err != nil { - logger.Println(err) - logger.Printf(waitmessage) - continue - } - - distance := HaversinFormula.Distance(geoFenceLatitude, geoFenceLongitude, driveState.Latitude, driveState.Longitude) - - logger.Printf("Distance: %v\n\n", distance) - - // If the distance is outside the radius, that means vehicle is outside the GeoFence. Ok to get out - if distance > float64(radius) { - ingeofenceandstopped = false - logger.Printf(waitmessage) - continue - } - - // This is to prevent the below logic, if it's already executed, no need to keep doing it - if ingeofenceandstopped == true { - logger.Printf(waitmessage) - continue - } - - // Check if the vehicle is stopped. - if (driveState.ShiftState == nil || driveState.ShiftState == "P") && driveState.Speed == 0 { - ingeofenceandstopped = true - - // In the GeoFence and stopped. Get the vehicle charge state. - chargeState, err := vehicle.ChargeState() - if err != nil { - logger.Println(err) - logger.Printf(waitmessage) - continue - } - - // Check if the vehicle is plugged in. - logger.Printf("Vehicle %v is within %v meters of GeoFence with a battery level of %v percent and charging state of %v.", vehicleState.VehicleName, int(distance), chargeState.BatteryLevel, chargeState.ChargingState) - if chargeState.ChargingState == "Disconnected" { - // Disconnected, stopped, and within the radius - send alert - if chargeState.BatteryLevel >= alertThreshold { - logger.Printf("Battery level is above %v alert threshold. Not sending alert.", chargeState.BatteryLevel) - logger.Printf(waitmessage) - continue - } - - subject := "Tesla Command - " + vehicleState.VehicleName - body := fmt.Sprintf("Vehicle %v is within %v meters of GeoFence with a battery level of %v percent. Please plug in.", vehicleState.VehicleName, int(distance), chargeState.BatteryLevel) - logger.Println(body) - - // Send mail - err = NotifyLib.SendMail(logger, mailServer, mailServerPort, mailServerLogin, mailServerPassword, fromAddress, toAddress, subject, body) - if err != nil { - logger.Println(err) - } - - // Send text - err = NotifyLib.SendText(logger, twilioSID, twilioToken, senderPhoneNumber, recipientPhoneNumber, body) - if err != nil { - logger.Println(err) - } - } - } - logger.Printf(waitmessage) - } -} +// +// Brett Morrison, Februrary 2016 +// Lee Elson. June 2020 Modified to add Tesla wake up call with sleep time and to have a complete TO:, FROM:, SUBJECT:,MSG +// in the message portion of the sendmail. This is necessary for some SMPT servers. Also commented out texting portion +// due to subscription cost. A second to: email address has been added allowing email-to-text if desired. +// Also modified the loop so that the program ends if it finds the charge port door open. The program has +// been changed to loop only if the door is closed and is designed to be run at a time when the vehicle **should** be home and attached. +// +// A program to alert if Tesla is not plugged in at a specified GeoFence +// +package main + +import ( + "TeslaCommand/lib/HaversinFormula" + "TeslaCommand/lib/NotifyLib" + "flag" + "fmt" + "io" + "log" + "os" + "time" + + tesla "github.com/jsgoecke/tesla" +) + +// Magic clientid and clientsecret available here: http://pastebin.com/fX6ejAHd +const clientid = "e4a9949fcfa04068f59abb5a658f2bac0a3428e4652315490b659d5ab3f35a9e" +const clientsecret = "c75f14bbadc8bee3a7594412c31416f8300256d7668ea7e6e7f06727bfb9d220" + +var teslaLoginEmail string +var teslaLoginPassword string +var vehicleIndex int +var geoFenceLatitude float64 +var geoFenceLongitude float64 +var mailServer string +var mailServerPort int +var mailServerLogin string +var mailServerPassword string +var fromAddress string +var toAddress1 string +var toAddress2 string +var twilioSID string +var twilioToken string +var senderPhoneNumber string +var recipientPhoneNumber string +var radius int +var checkInterval int +var alertThreshold int + +func init() { + flag.StringVar(&teslaLoginEmail, "teslaLoginEmail", "", "Email for teslamotors.com account") + flag.StringVar(&teslaLoginPassword, "teslaLoginPassword", "", "Password for teslamotors.com account") + flag.IntVar(&vehicleIndex, "vehicleIndex", 0, "Index of vehicles in your account - If just 1 vehicle, use 0") + flag.Float64Var(&geoFenceLatitude, "geoFenceLatitude", 0.0, "Latitude of GeoFence Center") + flag.Float64Var(&geoFenceLongitude, "geoFenceLongitude", 0.0, "Longitude of GeoFence Center") + flag.StringVar(&mailServer, "mailServer", "", "SMTP Server hostname") + flag.IntVar(&mailServerPort, "mailServerPort", 25, "SMTP Server port number") + flag.StringVar(&mailServerLogin, "mailServerLogin", "", "SMTP Server login username") + flag.StringVar(&mailServerPassword, "mailServerPassword", "", "SMTP Server password") + flag.StringVar(&fromAddress, "fromAddress", "", "Alert send from email") + flag.StringVar(&toAddress1, "toAddress1", "", "Alert send to email1") //LSE mod to add second email address + flag.StringVar(&toAddress2, "toAddress2", "", "Alert send to email2") //LSE mod to add second email address + flag.StringVar(&twilioSID, "twilioSID", "", "Twilio SID") + flag.StringVar(&twilioToken, "twilioToken", "", "Twilio Token") + flag.StringVar(&senderPhoneNumber, "senderPhoneNumber", "", "Sender Phone Number") + flag.StringVar(&recipientPhoneNumber, "recipientPhoneNumber", "", "Recipient Phone Number") + flag.IntVar(&radius, "radius", 0, "Radius in meters from center geoFence - Typically use 200") + flag.IntVar(&checkInterval, "checkInterval", 300, "Time in seconds between checks for geoFence") + flag.IntVar(&alertThreshold, "alertThreshold", 50, "Percentage charged threshold to send alert. If charge level is above threshold, alert won't be sent") +} + +func main() { + // Setup Logging + logFileName := fmt.Sprintf("TeslaCommand-%v.log", time.Now().Unix()) + logf, err := os.OpenFile(logFileName, os.O_WRONLY|os.O_CREATE, 0640) + if err != nil { + log.Fatalln(err) + } + defer logf.Close() + + log.SetOutput(logf) + logger := log.New(io.MultiWriter(logf, os.Stdout), "TeslaCommand: ", log.Lshortfile|log.LstdFlags) + + logger.Printf("Num Args %d\n", len(os.Args)) + flag.Parse() + if len(os.Args) != 20 { + flag.Usage() + os.Exit(1) + } + + + client, err := tesla.NewClient(&tesla.Auth{ClientID: clientid, ClientSecret: clientsecret, Email: teslaLoginEmail, Password: teslaLoginPassword}) + if err != nil { + logger.Println(err) + os.Exit(1) + } + //logger.Println("token: " + li.Token) + + vehicles, err := client.Vehicles() + if err != nil { + logger.Println(err) + os.Exit(1) + } + vehicle := vehicles[vehicleIndex] + //LSE. Add vehicle wakeup call + _, err = vehicle.Wakeup() + if err != nil { + logger.Println(err) + os.Exit(1) + } + time.Sleep(60 * time.Second) //Give it a chance to wake up LSE + // LSE + + + vehicleState, err := vehicle.VehicleState() + if err != nil { + logger.Println(err) + os.Exit(1) + } + + // Need to set this flag for every time vehicle exits and enters GeoFence (so we don't send repeated alerts) + // LSEingeofenceandstopped := false + waitmessage := fmt.Sprintf("Waiting to check vehicle %v location for %v seconds...\n", vehicleState.VehicleName, checkInterval) + + // Loop every N seconds. + logger.Printf(waitmessage) + for _ = range time.Tick(time.Duration(checkInterval) * time.Second) { + + //LSE. Add vehicle wakeup call + _, err = vehicle.Wakeup() + if err != nil { + logger.Println(err) + os.Exit(1) + } + time.Sleep(60 * time.Second) //Give it a chance to wake up LSE + // LSE + + logger.Printf("Checking vehicle %v location after waiting %v seconds.\n", vehicleState.VehicleName, checkInterval) + + driveState, err := vehicle.DriveState() + if err != nil { + logger.Println(err) + logger.Printf(waitmessage) + continue + } + + distance := HaversinFormula.Distance(geoFenceLatitude, geoFenceLongitude, driveState.Latitude, driveState.Longitude) + + logger.Printf("Distance: %v\n\n", distance) + + // If the distance is outside the radius, that means vehicle is outside the GeoFence. Ok to get out + if distance > float64(radius) { + // LSEingeofenceandstopped = false + logger.Printf(waitmessage) + continue + } + + // The following code was removed in order to make loop do the whole test each time, including sending email if disconnected LSE + // This is to prevent the below logic, if it's already executed, no need to keep doing it + // LSEif ingeofenceandstopped == true { + // LSElogger.Printf(waitmessage) + // LSEcontinue + // LSE} + + // Check if the vehicle is stopped. + if (driveState.ShiftState == nil || driveState.ShiftState == "P") && driveState.Speed == 0 { + // LSEingeofenceandstopped = true + + // In the GeoFence and stopped. Get the vehicle charge state. + chargeState, err := vehicle.ChargeState() + if err != nil { + logger.Println(err) + logger.Printf(waitmessage) + continue + } + + // Check if the vehicle is plugged in. + logger.Printf("Vehicle %v is within %v meters of GeoFence with a battery level of %v percent and charging state of %v.", vehicleState.VehicleName, int(distance), chargeState.BatteryLevel, chargeState.ChargingState) + if chargeState.ChargingState != "Disconnected" { + logger.Printf("Charge state is %v. Exit", chargeState.ChargingState) + os.Exit(1) + } + // Disconnected, stopped, and within the radius - send alert + if chargeState.BatteryLevel >= alertThreshold { + logger.Printf("Battery level is above %v alert threshold. Not sending alert.", chargeState.BatteryLevel) + logger.Printf(waitmessage) + continue + } + + subject := "Tesla Command - " + vehicleState.VehicleName + body := fmt.Sprintf("Vehicle %v is within %v meters of GeoFence with a battery level of %v percent. Please plug in.", vehicleState.VehicleName, int(distance), chargeState.BatteryLevel) + logger.Println(body) + + // Send mail + err = NotifyLib.SendMail(logger, mailServer, mailServerPort, mailServerLogin, mailServerPassword, fromAddress, toAddress1, toAddress2, subject, body) + if err != nil { + logger.Println(err) + } + +//LSE // Send text +//LSE err = NotifyLib.SendText(logger, twilioSID, twilioToken, senderPhoneNumber, recipientPhoneNumber, body) +//LSE if err != nil { +//LSE logger.Println(err) +//LSE } + + } + logger.Printf(waitmessage) + } +} diff --git a/readme.md b/readme.md index 588618b..52ad35d 100644 --- a/readme.md +++ b/readme.md @@ -1,28 +1,46 @@ -# TeslaCommand - -### Overview -A Golang program to connect to a Tesla vehicle, determine if it's within a GeoFence, and once it enters, if it's not plugged in, send an email alert. - -Given a teslamotors.com account, interval, coordinates, and radius, it connects to the Tesla RESTful API, and determines the vehicles location and charging state. - -The command line args are specified via minus sign, argname, equal sign, value. - -You must first go on [Google Maps][1] or [LatLong][2] and get the Longitude and Latitude of the center point of your charging destination. - -### Installation -Install [Go][3] and [Git][4] if you don't have them. Go can be tricky with paths. Type `$ go env` and then `$ cd` into directory in `$GOROOT/src`. Clone this repository from within the `src` directory. - -`$ git clone https://github.com/morrisonbrett/TeslaCommand.git` - -`$ cd TeslaCommand` - -Below is an example run. The long/lat is for the Tesla Hawthorne, CA Supercharger (replace with your own values): - -`$ go run TeslaCommand.go -checkInterval=300 -fromAddress="user@gmail.com" -geoFenceLatitude=33.921063 -geoFenceLongitude=-118.33015434 -mailServer="smtp.gmail.com" -mailServerLogin="user@gmail.com" -mailServerPassword="the-gmail-password" -mailServerPort=587 -radius=200 -teslaLoginEmail="user@gmail.com" -teslaLoginPassword="the-teslamotors-password" -toAddress="user@gmail.com" -vehicleIndex=0` - -Please see the "Issues" link for a list of "TO DO" items. It's a work in progress... :-) - -[1]: https://support.google.com/maps/answer/18539?hl=en -[2]: http://www.latlong.net/ -[3]: https://golang.org/ -[4]: http://git-scm.com/download/ +# TeslaCommand + +### Overview +A Golang program to connect to a Tesla vehicle, determine if it's within a GeoFence, and once it enters, if it's not plugged in, send an email alert. + +Given a teslamotors.com account, interval, coordinates, and radius, it connects to the Tesla RESTful API, and determines the vehicles location and charging state. + +The command line args are specified via minus sign, argname, equal sign, value. + +You must first go on [Google Maps][1] or [LatLong][2] and get the Longitude and Latitude of the center point of your charging destination. + +### Installation +Install [Go][3] and [Git][4] if you don't have them. Go can be tricky with paths. Type `$ go env` and then `$ cd` into directory in `$GOROOT/src`. Clone this repository from within the `src` directory. + +`$ git clone https://github.com/morrisonbrett/TeslaCommand.git` + +`$ cd TeslaCommand` + +Below is an example run. The long/lat is for the Tesla Hawthorne, CA Supercharger (replace with your own values): + +`$ go run TeslaCommand.go -checkInterval=300 -fromAddress="user@gmail.com" -geoFenceLatitude=33.921063 -geoFenceLongitude=-118.33015434 -mailServer="smtp.gmail.com" -mailServerLogin="user@gmail.com" -mailServerPassword="the-gmail-password" -mailServerPort=587 -radius=200 -teslaLoginEmail="user@gmail.com" -teslaLoginPassword="the-teslamotors-password" -toAddress="user@gmail.com" -vehicleIndex=0` + +Please see the "Issues" link for a list of "TO DO" items. It's a work in progress... :-) + +[1]: https://support.google.com/maps/answer/18539?hl=en +[2]: http://www.latlong.net/ +[3]: https://golang.org/ +[4]: http://git-scm.com/download/ + +################Modifications and fixes +Vehicles will "sleep" after a certain period. When asleep, vehicle data is unavailable so a wake command has been added. +A hard coded wait time of 60 seconds is used to allow the vehicle to wake. Note that repeated waking of the vehicle drains the battery. + +The original used a fee-for-service provider (twilio) to send texts. This code has been commented out, but input parameters remain, are required and +are unused. A second toaddress has been added to allow free email-to-text transmissions. + +Changes were made to email transmission. Most SMTP servers require the message to contain TO:, FROM: and SUBJECT: since FROM is often checked for +validity. Also, port 25 seems to be the only one that works (Gmail, Charter). + +The original was designed to loop if the vehicle is found outside the fence. Here we assume that the norm is for the vehicle to be inside the fence when checking occurs +so the primary check is for charging door open. If true, the program quits. If false, it loops. Suggested loop interval 3600 seconds. Program is +designed to be started with a scheduler (e.g.cron or Window Task Manager) at a time when vehicle **should** be charging. + +Note that the example command above is **out of date, even for the original**. Here is a sample command for the current version: +go run TeslaCommand.go -alertThreshold=100 -checkInterval=3600 -fromAddress="user@gmail.com" -geoFenceLatitude=33.921063 -geoFenceLongitude=-118.33015434 -mailServer="mobile.charter.net" -mailServerLogin="user@charter.net" -mailServerPassword="the-password" -mailServerPort=25 -radius=200 -recipientPhoneNumber="7775551212" -senderPhoneNumber="7775551212" -teslaLoginEmail"user@gmail.com" -teslaLoginPassword="the-teslamotors-password" -toAddress1="user@gmail.com" -toAddress2="user@gmail.com" -twilioSID="3334445555" -twilioToken="2223334444" -vehicleIndex=0 + From 00f66f12b0e64f58033f49a4423fd3965d85f211 Mon Sep 17 00:00:00 2001 From: zephyrus9MA <67062520+zephyrus9MA@users.noreply.github.com> Date: Tue, 7 Jul 2020 14:01:41 -0700 Subject: [PATCH 3/7] Update readme.md --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 52ad35d..3dbe24b 100644 --- a/readme.md +++ b/readme.md @@ -27,7 +27,7 @@ Please see the "Issues" link for a list of "TO DO" items. It's a work in progre [3]: https://golang.org/ [4]: http://git-scm.com/download/ -################Modifications and fixes +### Modifications and fixes Vehicles will "sleep" after a certain period. When asleep, vehicle data is unavailable so a wake command has been added. A hard coded wait time of 60 seconds is used to allow the vehicle to wake. Note that repeated waking of the vehicle drains the battery. @@ -42,5 +42,5 @@ so the primary check is for charging door open. If true, the program quits. If f designed to be started with a scheduler (e.g.cron or Window Task Manager) at a time when vehicle **should** be charging. Note that the example command above is **out of date, even for the original**. Here is a sample command for the current version: -go run TeslaCommand.go -alertThreshold=100 -checkInterval=3600 -fromAddress="user@gmail.com" -geoFenceLatitude=33.921063 -geoFenceLongitude=-118.33015434 -mailServer="mobile.charter.net" -mailServerLogin="user@charter.net" -mailServerPassword="the-password" -mailServerPort=25 -radius=200 -recipientPhoneNumber="7775551212" -senderPhoneNumber="7775551212" -teslaLoginEmail"user@gmail.com" -teslaLoginPassword="the-teslamotors-password" -toAddress1="user@gmail.com" -toAddress2="user@gmail.com" -twilioSID="3334445555" -twilioToken="2223334444" -vehicleIndex=0 +`go run TeslaCommand.go -alertThreshold=100 -checkInterval=3600 -fromAddress="user@gmail.com" -geoFenceLatitude=33.921063 -geoFenceLongitude=-118.33015434 -mailServer="mobile.charter.net" -mailServerLogin="user@charter.net" -mailServerPassword="the-password" -mailServerPort=25 -radius=200 -recipientPhoneNumber="7775551212" -senderPhoneNumber="7775551212" -teslaLoginEmail"user@gmail.com" -teslaLoginPassword="the-teslamotors-password" -toAddress1="user@gmail.com" -toAddress2="user@gmail.com" -twilioSID="3334445555" -twilioToken="2223334444" -vehicleIndex=0` From fbef264872bb8c8a12e014a17e9b2dbc372f6a0e Mon Sep 17 00:00:00 2001 From: zephyrus9MA <67062520+zephyrus9MA@users.noreply.github.com> Date: Tue, 7 Jul 2020 14:03:00 -0700 Subject: [PATCH 4/7] Update readme.md --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 3dbe24b..97cf177 100644 --- a/readme.md +++ b/readme.md @@ -42,5 +42,6 @@ so the primary check is for charging door open. If true, the program quits. If f designed to be started with a scheduler (e.g.cron or Window Task Manager) at a time when vehicle **should** be charging. Note that the example command above is **out of date, even for the original**. Here is a sample command for the current version: + `go run TeslaCommand.go -alertThreshold=100 -checkInterval=3600 -fromAddress="user@gmail.com" -geoFenceLatitude=33.921063 -geoFenceLongitude=-118.33015434 -mailServer="mobile.charter.net" -mailServerLogin="user@charter.net" -mailServerPassword="the-password" -mailServerPort=25 -radius=200 -recipientPhoneNumber="7775551212" -senderPhoneNumber="7775551212" -teslaLoginEmail"user@gmail.com" -teslaLoginPassword="the-teslamotors-password" -toAddress1="user@gmail.com" -toAddress2="user@gmail.com" -twilioSID="3334445555" -twilioToken="2223334444" -vehicleIndex=0` From 1cd69bcd5912715dcfe3f10fa9266d19047a1c0e Mon Sep 17 00:00:00 2001 From: zephyrus9MA <67062520+zephyrus9MA@users.noreply.github.com> Date: Wed, 8 Jul 2020 09:22:20 -0700 Subject: [PATCH 5/7] Update TeslaCommand.go --- TeslaCommand.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/TeslaCommand.go b/TeslaCommand.go index d96fb5b..e935681 100644 --- a/TeslaCommand.go +++ b/TeslaCommand.go @@ -1,7 +1,8 @@ // // Brett Morrison, Februrary 2016 -// Lee Elson. June 2020 Modified to add Tesla wake up call with sleep time and to have a complete TO:, FROM:, SUBJECT:,MSG -// in the message portion of the sendmail. This is necessary for some SMPT servers. Also commented out texting portion +// Lee Elson. June 2020 +// Modified to add Tesla wake up call with sleep time and to have a complete TO:, FROM:, SUBJECT:,MSG +// in the message portion of the sendmail. This is necessary for some SMTP servers. Also commented out texting portion // due to subscription cost. A second to: email address has been added allowing email-to-text if desired. // Also modified the loop so that the program ends if it finds the charge port door open. The program has // been changed to loop only if the door is closed and is designed to be run at a time when the vehicle **should** be home and attached. @@ -102,16 +103,15 @@ func main() { os.Exit(1) } vehicle := vehicles[vehicleIndex] - //LSE. Add vehicle wakeup call + //Add vehicle wakeup call _, err = vehicle.Wakeup() if err != nil { logger.Println(err) os.Exit(1) } - time.Sleep(60 * time.Second) //Give it a chance to wake up LSE - // LSE + //Give it a chance to wake up + time.Sleep(60 * time.Second) - vehicleState, err := vehicle.VehicleState() if err != nil { logger.Println(err) @@ -119,21 +119,21 @@ func main() { } // Need to set this flag for every time vehicle exits and enters GeoFence (so we don't send repeated alerts) - // LSEingeofenceandstopped := false + ingeofenceandstopped := false waitmessage := fmt.Sprintf("Waiting to check vehicle %v location for %v seconds...\n", vehicleState.VehicleName, checkInterval) // Loop every N seconds. logger.Printf(waitmessage) for _ = range time.Tick(time.Duration(checkInterval) * time.Second) { - //LSE. Add vehicle wakeup call - _, err = vehicle.Wakeup() - if err != nil { - logger.Println(err) - os.Exit(1) - } - time.Sleep(60 * time.Second) //Give it a chance to wake up LSE - // LSE + //Add vehicle wakeup call + _, err = vehicle.Wakeup() + if err != nil { + logger.Println(err) + os.Exit(1) + } + //Give it a chance to wake up + time.Sleep(60 * time.Second) logger.Printf("Checking vehicle %v location after waiting %v seconds.\n", vehicleState.VehicleName, checkInterval) @@ -150,7 +150,7 @@ func main() { // If the distance is outside the radius, that means vehicle is outside the GeoFence. Ok to get out if distance > float64(radius) { - // LSEingeofenceandstopped = false + ingeofenceandstopped = false logger.Printf(waitmessage) continue } @@ -197,7 +197,7 @@ func main() { logger.Println(err) } -//LSE // Send text + // Send text //LSE err = NotifyLib.SendText(logger, twilioSID, twilioToken, senderPhoneNumber, recipientPhoneNumber, body) //LSE if err != nil { //LSE logger.Println(err) From 5ffd688620d3ab4e550bed98cf29b562d798e333 Mon Sep 17 00:00:00 2001 From: zephyrus9MA <67062520+zephyrus9MA@users.noreply.github.com> Date: Wed, 8 Jul 2020 10:15:51 -0700 Subject: [PATCH 6/7] Update Mail.go --- lib/NotifyLib/Mail.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/NotifyLib/Mail.go b/lib/NotifyLib/Mail.go index 194cea6..2396ef6 100644 --- a/lib/NotifyLib/Mail.go +++ b/lib/NotifyLib/Mail.go @@ -1,5 +1,5 @@ package NotifyLib -// Add second to address. Most mail servers require a FROM: address. This was added to the message by Lee Elson on 6/29/20 +// Most mail servers require a FROM: address. import ( "fmt" @@ -16,9 +16,9 @@ func SendMail(logger *log.Logger, mailServer string, mailServerPort int, mailSer auth = smtp.PlainAuth("", mailServerLogin, mailServerPassword, mailServer) } - // Connect to the server, authenticate, set the sender and recipient, and send the email in one step. - //LSE set up second To email address + //set up 2 email addresses to := []string{toAddress1, toAddress2} + // Connect to the server, authenticate, set the sender and recipient, and send the email in one step. msg := []byte("To: " + toAddress1 + "\r\nFrom: " + fromAddress + "\r\nSubject: " + subj + "\r\n" + body + "\r\n") serverPort := mailServer + ":" + strconv.Itoa(mailServerPort) err := smtp.SendMail(serverPort, auth, fromAddress, to, msg) From e3ef82801da9a05247ba335ab99c161ad0681c9f Mon Sep 17 00:00:00 2001 From: zephyrus9MA <67062520+zephyrus9MA@users.noreply.github.com> Date: Wed, 8 Jul 2020 10:20:28 -0700 Subject: [PATCH 7/7] Update Mail.go --- lib/NotifyLib/Mail.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/NotifyLib/Mail.go b/lib/NotifyLib/Mail.go index 2396ef6..658fa05 100644 --- a/lib/NotifyLib/Mail.go +++ b/lib/NotifyLib/Mail.go @@ -21,6 +21,7 @@ func SendMail(logger *log.Logger, mailServer string, mailServerPort int, mailSer // Connect to the server, authenticate, set the sender and recipient, and send the email in one step. msg := []byte("To: " + toAddress1 + "\r\nFrom: " + fromAddress + "\r\nSubject: " + subj + "\r\n" + body + "\r\n") serverPort := mailServer + ":" + strconv.Itoa(mailServerPort) + logger.Printf("Sending mail via server %s\n", serverPort) err := smtp.SendMail(serverPort, auth, fromAddress, to, msg) if err != nil { return fmt.Errorf("sendMail error: %s", err)