-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
123 lines (115 loc) · 3.85 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"""starts the main program loop"""
import sys
import time
import config
import gps
import requests
import serial
API_URL = "https://api.thingspeak.com/update.json?api_key={write_key}&latitude={lat}&longitude={lon}"
READ_TIMEOUT = 2#seconds
DELAY_TIME = 3#seconds
def update_thingspeak(cfg, lat, lon):
"""updates thingspeak channel with lat lon"""
print("\nupdating ThingSpeak...")
url = API_URL.replace("{write_key}", cfg["write_key"]).replace("{lat}", str(lat)).replace("{lon}", str(lon))
success = False
try:
req = requests.get(url)
if req.status_code == 200:
print("SUCCESS")
success = True
elif req.status_code == 404:
print("ERROR: unable to update ThingSpeak - please verify write key")
else:
print(req.content)
except requests.exceptions.ConnectionError:
print("ERROR: check internet connection")
print()
return success
def configure():
"""loads, configures, and saves runtime configuration"""
cfg = config.load_config()
config.set_port(cfg)
config.set_baud(cfg)
config.set_update_rate(cfg)
#config.set_channel(cfg)
config.set_write_key(cfg)
config.save_config(cfg)
def delay():
"""delays any following functions by the DELAY_TIME amount"""
print("please wait...")
last_time = time.time()
while True:
if time.time() - last_time >= DELAY_TIME:
print()
return
def run():
"""opens the serial port, reads and parses data, updates ThingSpeak"""
print("\n***** RUN *****")
print("press Ctrl-C to show menu")
delay()
cfg = config.load_config()
last_update = time.time()
update_rate_seconds = int(cfg["update_rate"])*60
ser = serial.Serial()
ser.port = cfg["port"]
ser.baudrate = cfg["baud"]
ser.timeout = READ_TIMEOUT
try:
print("opening serial port: %s"%cfg["port"])
ser.open()
except:
print("ERROR: unable to open serial port")
raise KeyboardInterrupt#raise to go to menu instead of exiting
print()
while True:
try:
data = ser.readline()
time_delta = time.time() - last_update
if data:
gps_string = data.decode("utf-8")
print(gps_string.strip("\n"))
if time_delta > update_rate_seconds:
lat, lng = gps.extract_lat_lng(gps_string)
if lat and lng:
updated = update_thingspeak(cfg, lat, lng)
if updated:
last_update = time.time()
else:
print("failed to update ThingSpeak - trying again in 10 seconds\n")
#set last_update so that an update will be attempted in 10 seconds
last_update = time.time() - update_rate_seconds + 10
else:
print("input timeout")
except KeyboardInterrupt:
if ser.is_open:
print("\nclosing serial port: %s"%cfg["port"])
ser.close()
#bubble the exception out of the run() function to for menu to be shown
raise KeyboardInterrupt
def menu():
"""provides a menu for the user to choose to run, confiure, or quit the application"""
choice = None
while not choice:
print("\n***** MENU *****")
print("r) RUN")
print("c) CONFIGURE")
print("q) QUIT")
choice = input(">> ").lower()
if choice == "r":
return
elif choice == "c":
configure()
elif choice == "q":
sys.exit()
else:
print("invalid option")
choice = None
def main():
"""application entry point"""
while True:
try:
run()
except KeyboardInterrupt:
menu()
main()