-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.py
317 lines (236 loc) · 10.7 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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
#!/usr/bin/env python
#import pdb # python debugger
import os
import time
import pycom
#PYBYTES
from _pybytes import Pybytes
from _pybytes_config import PybytesConfig
from machine import RTC, unique_id
from machine import SD, Pin, reset
import network # Used to disable WiFi
from initialisation import initialisation #initialise_time # TODO: clunky refactor
from helper import blink_led
import loggingpycom
from LoggerFactory import LoggerFactory
from UserButton import UserButton
from Constants import *
from machine import Timer
from SensorLogger import SensorLogger
from EventScheduler import EventScheduler
from helper import blink_led, get_sensors, led_lock
from averages import get_sensor_averages
from TempSHT35 import TempSHT35
import GpsSIM28
import _thread
#from initialisation import initialise_pm_sensor, initialise_file_system, remove_residual_files, get_logging_level
from LoRaWAN import LoRaWAN
from machine import RTC, unique_id
#from initialisation import initialise_time
from ubinascii import hexlify
import Configuration
from new_config import new_config
from software_update import software_update
import strings as s
import ujson
#===================Disable default wifi===================
try:
wlan = network.WLAN()
wlan.deinit()
except Exception as e:
print("Unable to disable WiFi")
#===============LED
pycom.heartbeat(False) # disable the heartbeat LED
pycom.rgbled(0x552000) # flash orange to indicate startup
#=========================Mount SD card=======
try:
sd = SD()
os.mount(sd, '/sd')
#TODO: Error catch , set led for no SD card
except Exception as e:
print("SD did not mount")
#===================Get a logger up and running asap!
logger_factory = LoggerFactory()
#TODO: Set log level to level in config file
status_logger = logger_factory.create_status_logger(DEFAULT_LOG_NAME, level=loggingpycom.DEBUG, terminal_out=True,
filename=LOG_FILENAME)
status_logger.warning("Rebooted")
#=============Global config
config = Configuration.Configuration(status_logger)
status_logger.info("Config loaded")
#=============iNIT functions
init = initialisation(config, status_logger)
#=========================Get time sorted
# Get current time
rtc = RTC()
no_time, update_time_later = init.initialise_time(rtc, False) #Dont use GPS , yet - just read RTC
update_time_later = True #Force a gps fix
status_logger.info("RTC read")
#======================== Setup user interupt button
user_button = UserButton(status_logger)
pin_14 = Pin("P14", mode=Pin.IN, pull=Pin.PULL_DOWN)
pin_14.callback(Pin.IRQ_RISING | Pin.IRQ_FALLING, user_button.button_handler)
user_button.set_config_enabled(True)
status_logger.warning("User button enabled")
#TODO: provision if key on sd card
#set connect to false in config file?
#========Pybytes
pycom.nvs_set('pybytes_debug',99 ) #0 warning - 99 all
conf = PybytesConfig().read_config()
pybytes = Pybytes(conf)
#backup config
#naw.... pybytes.write_config([file=’/flash/pybytes_config.json’, silent=False])
pybytes.update_config('pybytes_autostart', False, permanent=True, silent=False, reconnect=False)
status_logger.warning("Update")
#pdb.set_trace()
pycom.pybytes_on_boot(False)
conf = PybytesConfig().read_config()
pybytes = Pybytes(conf)
#TIME
# Get current time
#rtc = RTC()
#no_time, update_time_later = initialise_time(rtc, True, status_logger) #TODO: True is use gps
pybytes.start(autoconnect=False)
pybytes.send_signal(1, 0) # Sort of similar to uptime, sent to note reboot
status_logger.warning("Pybytes config done")
#==========================
# Try to mount SD card, if this fails, keep blinking red and do not proceed
#try:
#from loggingpycom import DEBUG
#from LoggerFactory import LoggerFactory
#from UserButton import UserButton#
# Initialise LoggerFactory and status logger
#logger_factory = LoggerFactory()
#status_logger = logger_factory.create_status_logger(DEFAULT_LOG_NAME, level=loggingpycom.DEBUG, terminal_out=True,
# filename=LOG_FILENAME)
# Initialise button interrupt on pin 14 for user interaction
#user_button = UserButton(status_logger)
#pin_14 = Pin("P14", mode=Pin.IN, pull=Pin.PULL_DOWN)
#pin_14.callback(Pin.IRQ_RISING | Pin.IRQ_FALLING, user_button.button_handler)
# Mount SD card
#sd = SD()
#os.mount(sd, '/sd')
# except Exception as e:
# print(str(e))
# reboot_counter = 0
# while True:
# blink_led((0x550000, 0.5, True)) # blink red LED
# time.sleep(0.5)
# reboot_counter += 1
# if reboot_counter >= 180:
# reset()
try:
# Read configuration file to get preferences
#config = Configuration.Configuration(status_logger)
#config.read_configuration() #Now removed from init
"""SET CODE VERSION NUMBER - if new tag is added on git, update code version number accordingly"""
# ToDo: Update OTA.py so if version is 0.0.0, it backs up all existing files, and adds all files as new.
# ToDo: Set code_version to '0.0.0' in default config, and remove the line below
config.save_config({"code_version": "0.2.6"})
"""SET FORMAT VERSION NUMBER - version number is used to indicate the data format used to decode LoRa messages in
the back end. If the structure of the LoRa message is changed during update, increment the version number and
add a corresponding decoder to the back-end."""
config.save_config({"fmt_version": 1})
#TODO: Repair overrride later
# Override Preferences - DEVELOPER USE ONLY - keep all overwrites here
# if 'debug_config.json' in os.listdir('/flash'):
# status_logger.warning("Overriding configuration with the content of debug_config.json")
# with open('/flash/debug_config.json', 'r') as f:
# config.set_config(ujson.loads(f.read()))
# status_logger.warning("Configuration changed to: " + str(config.get_config()))
# Check if GPS is enabled in configurations
if config.get_config("GPS") == "OFF":
gps_on = False
else:
gps_on = True
#=======REmove this config stuff === warn this devide id may be used -- check
# Check if device is configured, or SD card has been moved to another device
# device_id = hexlify(unique_id()).upper().decode("utf-8")
# if not config.is_complete(status_logger) or config.get_config("device_id") != device_id:
# config.reset_configuration(status_logger)
# # Force user to configure device, then reboot
# new_config(status_logger, arg=0)
#=======REmove this config stuff
# User button will enter configurations page from this point on
# If initialise time failed to acquire exact time, halt initialisation
if no_time:
raise Exception("Could not acquire UTC timestamp")
# Check if updating was triggered over LoRa
if config.get_config("update"):
software_update(status_logger)
except Exception as e:
status_logger.exception(str(e))
reboot_counter = 0
try:
while user_button.get_reboot():
blink_led((0x555500, 0.5, True)) # blink yellow LED
time.sleep(0.5)
reboot_counter += 1
if reboot_counter >= 180:
status_logger.info("rebooting...")
reset()
new_config(status_logger, arg=0) #TODO remove this
except Exception:
reset()
pycom.rgbled(0x552000) # flash orange until its loaded
# If sd, time, logger and configurations were set, continue with initialisation
try:
status_logger.info("Filesystem.......")
# Configurations are entered parallel to main execution upon button press for 2.5 secs
user_button.set_config_blocking(False)
# Set debug level - has to be set after logger was initialised and device was configured
logger_factory.set_level(DEFAULT_LOG_NAME, config.get_config(LOG_LEVEL_KEY) ) # initialisation(config, status_logger).get_logging_level())
# Initialise file system
init.initialise_file_system()
# Remove residual files from the previous run (removes all files in the current and processing dir)
init.remove_residual_files()
# Get a dictionary of sensors and their status
sensors = get_sensors(status_logger)
# Join the LoRa network
lora = False
if (True in sensors.values() or gps_on) and config.get_config("LORA") == "ON":
lora = LoRaWAN(status_logger)
# Initialise temperature and humidity sensor thread with id: TEMP
status_logger.info("Starting Temp logger...")
if sensors[s.TEMP]:
TEMP_logger = SensorLogger(sensor_name=s.TEMP, terminal_out=True)
if config.get_config(s.TEMP) == "SHT35":
temp_sensor = TempSHT35(config, TEMP_logger, status_logger)
status_logger.info("Temperature and humidity sensor initialised")
# Initialise PM power circuitry
PM_transistor = Pin('P20', mode=Pin.OUT)
if config.get_config(s.PM1) == "OFF" and config.get_config(s.PM2) == "OFF": #Turn on sensors (power)
PM_transistor.value(0) #TODO: Somehow make this clear that it disables BOTH???
else:
#FIX PM_transistor.value(1)
status_logger.info("Power ON both PM sensors")
# Initialise PM sensor threads
if False: #sensors[s.PM1]:
init.initialise_pm_sensor(sensor_name=s.PM1, pins=('P3', 'P17'), serial_id=1, status_logger=status_logger)
if False: #sensors[s.PM2]:
init.initialise_pm_sensor(sensor_name=s.PM2, pins=('P11', 'P18'), serial_id=2, status_logger=status_logger)
# Start scheduling lora messages if any of the sensors are defined
if True in sensors.values():
PM_Events = EventScheduler(logger=status_logger, data_type="sensors", lora=lora)
if gps_on:
GPS_Events = EventScheduler(logger=status_logger, data_type="gps", lora=lora)
status_logger.info("Initialisation finished")
# Blink green three times to identify that the device has been initialised
for val in range(3):
blink_led((0x005500, 0.5, True))
time.sleep(0.5)
# Initialise custom yellow heartbeat that triggers every 5 seconds
heartbeat = Timer.Alarm(blink_led, s=5, arg=(0x005500, 0.1, True), periodic=True)
# Try to update RTC module with accurate UTC datetime if GPS is enabled and has not yet synchronized
if gps_on and update_time_later:
# Start a new thread to update time from gps if available
# https://docs.pycom.io/firmwareapi/micropython/_thread/
status_logger.info("Starting GPS thread...")
_thread.start_new_thread(GpsSIM28.SetRTCtime, (rtc, status_logger))
#TODO: delete init object?
except Exception as e:
status_logger.exception("Exception in the main")
led_lock.acquire()
pycom.rgbled(0x550000)
while True:
time.sleep(5)