-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathpestdetector.sh
executable file
·643 lines (573 loc) · 27.8 KB
/
pestdetector.sh
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
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
#!/bin/bash
#
# title: pestdetector.sh
# description: This script creates images and detects rats and other forms of
# pest like cockroaches
# author: Dr. Christian Baun
# url: https://github.com/christianbaun/pestdetector
# license: GPLv3
# date: February 7th 2022
# version: 1.4
# bash_version: tested with 5.1.4(1)-release
# requires: The functions in functionlibrary.sh
# libcamera-still command line tool that uses the libcamera open
# source camera stack.
# Tested with the libcamera-apps packet version 2a38ae93f143
# As alternative, the raspistill command line tool can be used.
# curl command line tool for interaction with the Telegram Bot
# Tested with curl 7.74.0
# hostname command line tool. Tested with 3.21
# ping command line tool. Tested with iputils-s20180629
# python3 for the LCD driver when using the LCD 4x20 displays
# optional: none
# notes: This script has been developed to run on a Raspberry Pi 4
# (4 GB RAM). Two LCD 4x20 displays with HD44780 controllers,
# connected via the I2C interface are used to inform about the
# work of the pest detector.
# example: ./pestdetector.sh
# ----------------------------------------------------------------------------
# Function library with thse functions:
# clear_lcd_displays()
# make_a_picture()
# detect_objects()
# check_if_objects_have_been_deteted()
# print_result_on_LCD()
# print_no_object_detected_on_LCD()
# inform_telegram_bot()
# prevent_directory_overflow()
. functionlibrary.sh
function usage
{
echo "$SCRIPT [-h] [-m <modelname>] [-l <labelmap>] [-i <directory>] [-s <size>] [-j <directory>] [-t] [-o <time>] [-d <number>] [-c] [-r]
Arguments:
-h : show this message on screen
-m : the name of the model used for object detection. The name must match the
directory name in the home directory
-l : the file name of the labelmap used for object detection
-i : the directory to store the images that contain detected objects
-s : the maximum size [kB] of the directory to store the images with detected
objects. The minimum value is 10000 (= 10 MB)
-j : the directory to store the log files of pest detector
-t : use telegram bot notifications. If this flag is set, telegram notifications
are send when the pest detector starts and when objects are detected.
The bot token url and the chat ID must be specified as variables
\$TELEGRAM_TOKEN and \$TELEGRAM_CHAT_ID in the file
/home/pi/pest_detect_telegram_credentials.sh
-o : slow motion operation mode for obervation, debugging and documentation
purposes. Inserts a pause of <time> seconds between the single steps of the
pest detector. The minimum value is 1 and the maximum value is 20
-d : use 0, 1 or 2 LCD displays (4x20)
-c : use Coral Accelerator TPU coprocessor
-r : rotate the camera image 180 degrees
"
exit 0
}
# Script name
SCRIPT=${0##*/}
# This is the detault model that is used when no model name is
# specified with the command line parameter -m <modelname>
STANDARDMODELL=model_2021_07_08_rat_bug_hedgehog
STANDARDLABELMAP=labelmap.txt
MODELLNAME_PARAMETER=0
LABELMAP_PARAMETER=0
# Path of the directory for the most recent picture
DIRECTORY_MOST_RECENT_IMAGE="/dev/shm/most_recent_image"
DIRECTORY_IMAGES_PARAMETER=0
# Path of the directory for the picture
DIRECTORY_IMAGES=""
STANDARD_DIRECTORY_IMAGES="images"
DIRECTORY_IMAGES_MAX_SIZE_PARAMETER=0
DIRECTORY_IMAGES_MAX_SIZE=""
STANDARD_DIRECTORY_IMAGES_MAX_SIZE="50000" # 50 MB max for testing purposes
DIRECTORY_LOGS_PARAMETER=0
DIRECTORY_LOGS=""
STANDARD_DIRECTORY_LOGS="logs"
DIRECTORY_LOGS_MAX_SIZE="100000" # 100 MB max
SLOW_MOTION_MODE_PARAMETER=0
SLOW_MOTION_MODE_TIME=0
# Do not use the telegram bot notification per default
USE_TELEGRAM_BOT=0
# Do not use LCDdisplays 4x20 per default
NUM_LCD_DISPLAYS=0
USE_CORAL_TPU_COPROCESSOR=0
ROTATE_CAMERA_IMAGE=0
LCD_LINE_1_1=""
LCD_LINE_1_2=""
LCD_LINE_1_3=""
LCD_LINE_1_4=""
LCD_LINE_2_1=""
LCD_LINE_2_2=""
LCD_LINE_2_3=""
LCD_LINE_2_4=""
CLEAR_LCD_DRIVER1="lcd_display1_clear.py"
CLEAR_LCD_DRIVER2="lcd_display2_clear.py"
LCD_DRIVER1="lcd_output_display1.py"
LCD_DRIVER2="lcd_output_display2.py"
RED='\033[0;31m' # Red color
NC='\033[0m' # No color
GREEN='\033[0;32m' # Green color
YELLOW='\033[0;33m' # Yellow color
BLUE='\033[0;34m' # Blue color
WHITE='\033[0;37m' # White color
# At the very beginning, no objects have been detected
HIT=0
DETECTED_OBJECTS_OF_LAST_RUN=""
while getopts "hm:l:i:s:j:o:td:cr" ARG ; do
case $ARG in
h) usage ;;
m) MODELLNAME_PARAMETER=1
MODELLNAME=${OPTARG} ;;
l) LABELMAP_PARAMETER=1
LABELMAP=${OPTARG} ;;
i) DIRECTORY_IMAGES_PARAMETER=1
DIRECTORY_IMAGES=${OPTARG} ;;
s) DIRECTORY_IMAGES_MAX_SIZE_PARAMETER=1
DIRECTORY_IMAGES_MAX_SIZE=${OPTARG} ;;
j) DIRECTORY_LOGS_PARAMETER=1
DIRECTORY_LOGS=${OPTARG} ;;
o) SLOW_MOTION_MODE_PARAMETER=1
SLOW_MOTION_MODE_TIME=${OPTARG} ;;
t) USE_TELEGRAM_BOT=1 ;;
d) NUM_LCD_DISPLAYS=${OPTARG} ;;
c) USE_CORAL_TPU_COPROCESSOR=1 ;;
r) ROTATE_CAMERA_IMAGE=1 ;;
*) echo -e "${RED}[ERROR] Invalid option! ${OPTARG} ${NC}"
exit 1
;;
esac
done
# If the user did not want to specify the model name name with the parameter -m <modelname>,
# the pest detector will use the default model name
if [ "$MODELLNAME_PARAMETER" -eq 0 ] ; then
# No model provided as parameter => default model: $STANDARDMODELL
MODELLNAME=${STANDARDMODELL}
fi
# If the user did not want to specify the file name of the labelmap with the parameter -l <labelmap>,
# the pest detector will use the default labelmap file name
if [ "$LABELMAP_PARAMETER" -eq 0 ] ; then
# No labelmap file name provided as parameter => label map file name: $STANDARDLABELMAP
LABELMAP=${STANDARDLABELMAP}
fi
MODEL="/home/pi/${MODELLNAME}"
LABELS="/home/pi/${MODELLNAME}/${LABELMAP}"
# If the user did not want to specify the directory for the image files with detected objects
# with the parameter -i <directory>, the pest detector will use the default image files directory
if [ "$DIRECTORY_IMAGES_PARAMETER" -eq 0 ] ; then
# No image directory provided as parameter => default image directory: $STANDARD_DIRECTORY_IMAGES
DIRECTORY_IMAGES=${STANDARD_DIRECTORY_IMAGES}
fi
# If the user did not want to specify the maximum size of the directory that stores the image files
# with detected objects with the parameter -s <size>, the pest detector will use the default size
if [ "$DIRECTORY_IMAGES_MAX_SIZE_PARAMETER" -eq 0 ] ; then
# No maximum size for the directory provided as parameter => default size: $STANDARD_DIRECTORY_IMAGES_MAX_SIZE
DIRECTORY_IMAGES_MAX_SIZE=${STANDARD_DIRECTORY_IMAGES_MAX_SIZE}
fi
# It makes no sense to specify a maximum size of less than 10 MB for the
# directory that stores the image files with detected objects
if [ "$DIRECTORY_IMAGES_MAX_SIZE" -lt 10000 ] ; then
echo -e "${RED}[ERROR] It makes no sense to specify a maximum size of less than 10 MB for the directory that stores the image files with detected objects.${NC}"
usage
exit 1
fi
# It makes no sense to specify a slow motion waiting time that is less than 1 second
# and more than 20 seconds
if [ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ] ; then
if [[ "$SLOW_MOTION_MODE_TIME" -lt 1 || "$SLOW_MOTION_MODE_TIME" -gt 20 ]] ; then
echo -e "${RED}[ERROR] It makes no sense to specify a slow motion waiting time of less than 1 second and more than 20 seconds.${NC}"
usage
exit 1
fi
fi
# If the user did not want to specify the directory for the log files
# with the parameter -j <directory>, the pest detector will use the default log files directory
if [ "$DIRECTORY_LOGS_PARAMETER" -eq 0 ] ; then
# No image directory provided as parameter => default image directory: $STANDARD_DIRECTORY_LOGS
DIRECTORY_LOGS=${STANDARD_DIRECTORY_LOGS}
fi
# Check if the required command line tools are available
if ! [ -x "$(command -v hostname)" ]; then
echo -e "${RED}[ERROR] The command line tool hostname is missing.${NC}"
exit 1
else
HOSTNAME=$(hostname)
fi
# Store timestamp of the date in a variable
DATE_TIME_STAMP=$(date +%Y-%m-%d)
CLOCK_TIME_STAMP=$(date +%H-%M-%S)
echo -e "${DATE_TIME_STAMP} ${CLOCK_TIME_STAMP} Welcome to pestdetector on host ${HOSTNAME}"
# Check if the logs directory already exists
if [ -e ${DIRECTORY_LOGS} ] ; then
# If the directory for the logs already exists
echo -e "${GREEN}[OK] The directory ${DIRECTORY_LOGS} already exists in the local directory.${NC}"
else
# If the directory for the logs does not already exist => create it
if mkdir ${DIRECTORY_LOGS} ; then
echo -e "${GREEN}[OK] The directory ${DIRECTORY_LOGS} has been created.${NC}"
else
echo -e "${RED}[ERROR] Unable to create the local directory ${DIRECTORY_LOGS}.${NC}"
exit 1
fi
fi
# Definition of the logfile specification.
# This can be attached with a pipe to echo commands
TEE_PROGRAM_LOG=" tee -a ${DIRECTORY_LOGS}/${DATE_TIME_STAMP}-pestdetector_log.txt"
LOGFILE_OBJECTS_DETECTED="${DIRECTORY_LOGS}/${DATE_TIME_STAMP}-detected_objects.txt"
# Only if the command line parameter -t is set, the Telegram Bot notifications
# shall be send when the pest detector is started and when objects are detected
# and only in this case, the curl command line tool is required.
if [ "$USE_TELEGRAM_BOT" -eq 1 ] ; then
if ! [ -x "$(command -v curl)" ]; then
echo -e "${RED}[ERROR] The command line tool curl is missing.${NC}" | ${TEE_PROGRAM_LOG}
exit 1
fi
fi
# Validate that the number of 4x20 LCD displays used is 0, 1 or 2
if [ "$NUM_LCD_DISPLAYS" -eq 0 ] ; then
echo -e "${GREEN}[OK] ${NUM_LCD_DISPLAYS} 4x20 LCD display are used.${NC}"
elif [ "$NUM_LCD_DISPLAYS" -eq 1 ] ; then
echo -e "${GREEN}[OK] ${NUM_LCD_DISPLAYS} 4x20 LCD display is used.${NC}"
elif [ "$NUM_LCD_DISPLAYS" -eq 2 ] ; then
echo -e "${GREEN}[OK] ${NUM_LCD_DISPLAYS} 4x20 LCD displays are used.${NC}"
else
echo -e "${RED}[ERROR] The number of 4x20 LCD displays used must be 0, 1 or 2.${NC}"
usage
exit 1
fi
# It a slow motion waiting time was specified with the command-line parameter
# -o <seconds>, an information about this is print out.
if [ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ] ; then
echo -e "${GREEN}[OK] A slow motion waiting time of ${SLOW_MOTION_MODE_TIME} seconds is used.${NC}"
fi
# ------------------------------
# | Check the operating system |
# ------------------------------
if [[ "$OSTYPE" == "linux-gnu" || "$OSTYPE" == "linux-gnueabihf" ]]; then
# Linux
echo -e "${YELLOW}[INFO] The operating system is Linux: ${OSTYPE}${NC}" | ${TEE_PROGRAM_LOG}
elif [[ "$OSTYPE" == "freebsd"* ]]; then
# FreeBSD
echo -e "${YELLOW}[INFO] The operating system is FreeBSD: ${OSTYPE}${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Using the pest detector in FreeBSD was never tested.${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Please report to the developer if it worked or not.${NC}" | ${TEE_PROGRAM_LOG}
elif [[ "$OSTYPE" == "darwin"* ]]; then
# Mac OS X
echo -e "${YELLOW}[INFO] The operating system is Mac OS X: ${OSTYPE}${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Using the pest detector in Mac OS X was never tested.${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Please report to the developer if it worked or not.${NC}" | ${TEE_PROGRAM_LOG}
elif [[ "$OSTYPE" == "msys" ]]; then
# Windows
echo -e "${YELLOW}[INFO] The operating system is Windows: ${OSTYPE}${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Using the pest detector in Windows was never tested.${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Please report to the developer if it worked or not.${NC}" | ${TEE_PROGRAM_LOG}
elif [[ "$OSTYPE" == "cygwin" ]]; then
# POSIX compatibility layer for Windows
echo -e "${YELLOW}[INFO] POSIX compatibility layer for Windows detected: ${OSTYPE}${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Using the pest detector in Windows was never tested.${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Please report to the developer if it worked or not.${NC}" | ${TEE_PROGRAM_LOG}
else
# Unknown
echo -e "${YELLOW}[INFO] The operating system is unknown: ${OSTYPE}${NC}" | ${TEE_PROGRAM_LOG}
fi
# ----------------------------------------------------
# | Check that we have a working internet connection |
# ----------------------------------------------------
# We shall check at least 5 times
LOOP_VARIABLE=5
#until LOOP_VARIABLE is greater than 0
while [ $LOOP_VARIABLE -gt "0" ]; do
# Check if we have a working network connection by sending a ping to 8.8.8.8
if ping -q -c 1 -W 1 8.8.8.8 >/dev/null ; then
echo -e "${GREEN}[OK] This computer has a working internet connection.${NC}" | ${TEE_PROGRAM_LOG}
# Skip entire rest of loop.
break
else
echo -e "${YELLOW}[INFO] The internet connection is not working now. Will check again.${NC}" | ${TEE_PROGRAM_LOG}
# Decrement variable
LOOP_VARIABLE=$((LOOP_VARIABLE-1))
if [ "$LOOP_VARIABLE" -eq 0 ] ; then
echo -e "${RED}[INFO] This computer has no working internet connection.${NC}" | ${TEE_PROGRAM_LOG}
fi
# Wait a moment.
sleep 1
fi
done
# ----------------------------------------------------------
# | Check if the required command line tools are available |
# ----------------------------------------------------------
# If libcamera-still will not work, we will try raspistill later, but for the moment we hope it will work
TRY_LEGACY_RASPISTILL=0
# Check if the command line tool libcamera-still is available
if [ -x "$(command -v libcamera-still)" ]; then
echo -e "${GREEN}[OK] The tool libcamera-still has been found on this system.${NC}" | ${TEE_PROGRAM_LOG}
libcamera-still &> /dev/null
if [ $? -eq 0 ] ; then
echo -e "${GREEN}[OK] The tool libcamera-still appears to work well.${NC}" | ${TEE_PROGRAM_LOG}
else
echo -e "${YELLOW}[INFO] The tool libcamera-still fails. I try the legacy raspistill instead.${NC}" | ${TEE_PROGRAM_LOG}
# We need to try raspistill...
TRY_LEGACY_RASPISTILL=1
fi
fi
# If libcamera-still is not present or does not work properly, we need to try legacy raspistill as fallback solution
if [[ ${TRY_LEGACY_RASPISTILL} -eq 1 ]]; then
# Check if the legacy command line tool raspistill is available
if [ -x "$(command -v raspistill)" ] ; then
echo -e "${GREEN}[OK] The tool raspistill has been found on this system.${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] But it is a good idea to install libcamera-still from the libcamera tools because the legacy raspistill tool will stop working in the future.${NC}" | ${TEE_PROGRAM_LOG}
else
echo -e "${RED}[ERROR] pestdetector requires either the command line tool libcamera-still or raspistill.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
# This is only required if we use 1 or 2 LCD displays.
if [[ "$NUM_LCD_DISPLAYS" -eq 1 || "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
# Check if the LCD "driver" for LCD display 1 (just a command line tool tool to print lines on the LCD) is available
if ! [ -f "${LCD_DRIVER1}" ] ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER1} is missing.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
else
if ! python3 ${CLEAR_LCD_DRIVER1} ; then
echo -e "${RED}[ERROR] The LCD command line tool ${CLEAR_LCD_DRIVER1} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
# No matter if we have 1 or 2 LCD displays, the first one will show a welcome message
if ! python3 ${LCD_DRIVER1} "Welcome to" "pestdetector" "on host" "${HOSTNAME}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER1} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
fi
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
# This is only required if we use 2 LCD displays.
if [[ "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
# Check if the LCD "driver" for LCD display 2 (just a command line tool tool to print lines on the LCD) is available
if ! [ -f "${LCD_DRIVER1}" ]; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER2} is missing.${NC}" && exit 1
else
if ! python3 ${CLEAR_LCD_DRIVER2} ; then
echo -e "${RED}[ERROR] The LCD command line tool ${CLEAR_LCD_DRIVER2} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
if ! python3 ${LCD_DRIVER2} "This display informs" "about the state of" "the pestdetector" "software" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER2} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
fi
# ------------------------------------------------------
# | Check if the Telegram Bot notification is possible |
# ------------------------------------------------------
# Only if the command line parameter -t is set, the Telegram Bot notifications
# are send when the pest detector is started and when objects are detected
if [ "$USE_TELEGRAM_BOT" -eq 1 ] ; then
# If the file with the Telegram Bot url token und the chat ID exist, import the
# variables $TELEGRAM_TOKEN and $TELEGRAM_CHAT_ID
PEST_DETECT_TELEGRAM_CONFIG_FILE="/home/pi/pest_detect_telegram_credentials.sh"
if [ -f $PEST_DETECT_TELEGRAM_CONFIG_FILE ] ; then
. $PEST_DETECT_TELEGRAM_CONFIG_FILE
echo -e "${GREEN}[OK] The file with the Telegram Bot information is present.${NC}" | ${TEE_PROGRAM_LOG}
else
echo -e "${YELLOW}[INFO] The file with the Telegram Bot information is not present.${NC}" | ${TEE_PROGRAM_LOG}
fi
# Check if all variables that are required for the Telegram Bot notification
# do exist and are not empty
if [ -z "$TELEGRAM_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ] ; then
echo -e "${YELLOW}[INFO] One or more variables that are reqiored for the Telegram Bot notifications are undefined.${NC}" | ${TEE_PROGRAM_LOG}
echo -e "${YELLOW}[INFO] Please set the variables \$TELEGRAM_TOKEN and \$TELEGRAM_CHAT_ID if you want using Telegram Bot notifications.${NC}" | ${TEE_PROGRAM_LOG}
TELEGRAM_NOTIFICATIONS=0
else
TELEGRAM_NOTIFICATIONS=1
fi
if [[ ${TELEGRAM_NOTIFICATIONS} -eq 1 ]]; then
curl -s -X POST ${TELEGRAM_TOKEN}/sendMessage --data text="Pest Detector has been started." --data chat_id=${TELEGRAM_CHAT_ID} > /dev/null
fi
fi
# --------------------------------------------------
# | Check if the required directories/folders exit |
# --------------------------------------------------
# Check if the images directory already exists
if [ -e ${DIRECTORY_IMAGES} ] ; then
# If the directory for the images already exists
echo -e "${GREEN}[OK] The directory ${DIRECTORY_IMAGES} already exists in the directory.${NC}" | ${TEE_PROGRAM_LOG}
else
# If the directory for the images does not already exist => create it
if mkdir ${DIRECTORY_IMAGES} ; then
echo -e "${GREEN}[OK] The directory ${DIRECTORY_IMAGES} has been created.${NC}" | ${TEE_PROGRAM_LOG}
else
echo -e "${RED}[ERROR] Unable to create the directory ${DIRECTORY_IMAGES}.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
# Check if the most_recent_image directory already exists
if [ -e ${DIRECTORY_MOST_RECENT_IMAGE} ] ; then
# If the directory for the most_recent_image already exists
echo -e "${GREEN}[OK] The directory ${DIRECTORY_MOST_RECENT_IMAGE} already exists in the directory.${NC}" | ${TEE_PROGRAM_LOG}
else
# If the directory for the most_recent_image does not already exist => create it
if mkdir ${DIRECTORY_MOST_RECENT_IMAGE} ; then
echo -e "${GREEN}[OK] The directory ${DIRECTORY_MOST_RECENT_IMAGE} has been created.${NC}" | ${TEE_PROGRAM_LOG}
else
echo -e "${RED}[ERROR] Unable to create the directory ${DIRECTORY_MOST_RECENT_IMAGE}.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
# Check if the most_recent_image directory is empty. If it is not, erase all content
if [[ -z "$(ls -A ${DIRECTORY_MOST_RECENT_IMAGE})" ]] ; then
# -z string => True (0) if the string is null (an empty string).
# In other words, it is Talse (1) if there are files in most_recent_image
# -A means list all except . and ..
echo -e "${GREEN}[OK] The directory ${DIRECTORY_MOST_RECENT_IMAGE} is empty.${NC}" | ${TEE_PROGRAM_LOG}
else
# Erase the content of the directory most_recent_image.
# It sould be empty at the very beginning of the script.
# If it was not empty, maybe something went wrong with the inite loop during the last run.
if rm ${DIRECTORY_MOST_RECENT_IMAGE}/* ; then
echo -e "${GREEN}[OK] The directory ${DIRECTORY_MOST_RECENT_IMAGE} is now empty.${NC}" | ${TEE_PROGRAM_LOG}
else
echo -e "${RED}[ERROR] Unable to erase the content of the directory ${DIRECTORY_MOST_RECENT_IMAGE}.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
# Clear the LCD display(s)
clear_lcd_displays
NUMBER_OF_RUNS=0
# Inifinite loop
while true ; do
# Increment the number of program runs + 1 by using the command line tool bc
NUMBER_OF_RUNS=$(echo "${NUMBER_OF_RUNS} + 1" | bc)
TIMESTAMP_OUTPUT_STYLE=$(date +%Y-%m-%d\ %H:%M:%S)
echo -e "${GREEN}[OK] ${TIMESTAMP_OUTPUT_STYLE} ==> Start of program run ${NUMBER_OF_RUNS} <=== ${NC}" | ${TEE_PROGRAM_LOG}
# -----------------------------------------
# | Try to make a picture with the camera |
# -----------------------------------------
# This is only required if we use 2 LCD displays
if [[ "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
# Print some information on LCD display 2
LCD_LINE_2_1="Make a picture "
LCD_LINE_2_2=" "
LCD_LINE_2_3=" "
LCD_LINE_2_4=" "
if ! python3 ${LCD_DRIVER2} "${LCD_LINE_2_1}" "${LCD_LINE_2_2}" "${LCD_LINE_2_3}" "${LCD_LINE_2_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER2} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
# If we just have 1 LCD display, print some status information on LCD display 1
elif [[ "$NUM_LCD_DISPLAYS" -eq 1 ]] ; then
LCD_LINE_1_1="Make a picture "
if ! python3 ${LCD_DRIVER1} "${LCD_LINE_1_1}" "${LCD_LINE_1_2}" "${LCD_LINE_1_3}" "${LCD_LINE_1_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER1} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
make_a_picture
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
# -----------------------------------------
# | Object detection and logfile creation |
# -----------------------------------------
# This is only required if we use 2 LCD displays
if [[ "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
# Print some information on LCD display 2
LCD_LINE_2_1=" "
LCD_LINE_2_2="Detect objects "
LCD_LINE_2_3=" "
LCD_LINE_2_4=" "
if ! python3 ${LCD_DRIVER2} "${LCD_LINE_2_1}" "${LCD_LINE_2_2}" "${LCD_LINE_2_3}" "${LCD_LINE_2_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER2} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
# If we just have 1 LCD display, print some status information on LCD display 1
elif [[ "$NUM_LCD_DISPLAYS" -eq 1 ]] ; then
LCD_LINE_1_1="Detect objects "
if ! python3 ${LCD_DRIVER1} "${LCD_LINE_1_1}" "${LCD_LINE_1_2}" "${LCD_LINE_1_3}" "${LCD_LINE_1_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER1} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
detect_objects
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
# ----------------------------------------------------
# | Check if one or more objects have been detected. |
# | If there have been objects detected, move the |
# | picture and the log file to the images directory |
# ----------------------------------------------------
# This is only required if we use 2 LCD displays
if [[ "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
# Print some information on LCD display 2
LCD_LINE_2_1=" "
LCD_LINE_2_2=" "
LCD_LINE_2_3="Analyze results "
LCD_LINE_2_4=" "
if ! python3 ${LCD_DRIVER2} "${LCD_LINE_2_1}" "${LCD_LINE_2_2}" "${LCD_LINE_2_3}" "${LCD_LINE_2_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER2} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
# If we just have 1 LCD display, print some status information on LCD display 1
elif [[ "$NUM_LCD_DISPLAYS" -eq 1 ]] ; then
LCD_LINE_1_1="Analyze results "
if ! python3 ${LCD_DRIVER1} "${LCD_LINE_1_1}" "${LCD_LINE_1_2}" "${LCD_LINE_1_3}" "${LCD_LINE_1_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER1} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
check_if_objects_have_been_deteted
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
# ----------------------------------------------------------
# | If one or more objects have been detected, print |
# | the results on the LCD screen => print_result_on_LCD() |
# | |
# | If no objects have been detected, print the result on |
# | the LCD screen => print_no_object_detected_on_LCD() |
# ----------------------------------------------------------
if [ "$HIT" -eq 1 ] ; then
# If one or more objects have been detected...
# This is only required if we use 1 or 2 LCD displays
if [[ "$NUM_LCD_DISPLAYS" -eq 1 || "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
print_result_on_LCD
fi
# Write information about deteceted objects into log file
write_detected_objects_message_into_logfile
# Telegram Bot notification about detected objects will only be send if the
# user wants to do this by providing command line argument -t and if the
# required variables $TELEGRAM_TOKEN and $TELEGRAM_CHAT_ID are present
if [[ ${USE_TELEGRAM_BOT} -eq 1 && ${TELEGRAM_NOTIFICATIONS} -eq 1 ]]; then
# Inform the Telegram Bot about the detected objects
inform_telegram_bot
fi
else
# If no object has been detected...
# This is only required if we use 1 or 2 LCD displays.
if [[ "$NUM_LCD_DISPLAYS" -eq 1 || "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
print_no_object_detected_on_LCD
fi
fi
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
# ----------------------------------------------
# | Prevent the images directory from overflow |
# ----------------------------------------------
# This is only required if we use 2 LCD displays
if [[ "$NUM_LCD_DISPLAYS" -eq 2 ]] ; then
# Print some information on LCD display 2
LCD_LINE_2_1=" "
LCD_LINE_2_2=" "
LCD_LINE_2_3=" "
LCD_LINE_2_4="Organize folders "
if ! python3 ${LCD_DRIVER2} "${LCD_LINE_2_1}" "${LCD_LINE_2_2}" "${LCD_LINE_2_3}" "${LCD_LINE_2_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER2} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
# If we just have 1 LCD display, print some status information on LCD display 1
elif [[ "$NUM_LCD_DISPLAYS" -eq 1 ]] ; then
LCD_LINE_1_1="Organize folders "
if ! python3 ${LCD_DRIVER1} "${LCD_LINE_1_1}" "${LCD_LINE_1_2}" "${LCD_LINE_1_3}" "${LCD_LINE_1_4}" ; then
echo -e "${RED}[ERROR] The LCD command line tool ${LCD_DRIVER1} does not operate properly.${NC}" | ${TEE_PROGRAM_LOG} && exit 1
fi
fi
if [[ "$SLOW_MOTION_MODE_PARAMETER" -eq 1 ]] ; then
sleep "${SLOW_MOTION_MODE_TIME}"
fi
prevent_directory_overflow
done
exit 0