Perishable goods are a huge hassle to transport over long distances, especially on cargo ships. The service and maintenance team always has to keep a close eye on the temperature in the refrigerator room. During the daytime there is a high probability that the temperature of the refrigerator goes beyond the desired threshold, thereby spoiling the perishable goods. A notification system must be put in place in order to alert the service and maintenance team.
SolutionOftentimes, logistical companies responsible for transporting perishable goods (eg: Fish, meat, fruits, and vegetables), find themselves setting up complex systems to detect anomalies in the temperature, and the job becomes harder as they are on a ship with limited access to electricity and power. Temperature monitoring systems cannot consume power since that would require a compromise on the power required by the refrigerator to preserve the perishable goods. IoT eliminates this hassle and makes it easier for ships' crew and personnel to monitor temperature and receive alerts when the temperature is not within the required range. This mechanism is helpful for people working in the Operations and Maintenance teams aboard the ship. They get notified if there are slight temperature changes, and the alert system (LED & buzzer) is engaged simultaneously. The LED and Buzzer are placed in the office of the service personnel, aboard the ship.
This project focuses on creating a dynamic threshold for temperature changes using machine learning algorithms (Z-score analysis) and deploying alerts such as the buzzer and LED. The project is made using the Bolt IoT wifi module and a VPS (in this case it is ubuntu).
WorkflowThe code for this project is written in such a way that both static and dynamic thresholds are used:
- The static threshold is needed in order to make sure that the temperature change is still within the required threshold.
- The dynamic threshold is needed to detect sudden changes in temperature. The alert system (LED & buzzer) is engaged and an SMS is sent to the phone number if sudden temperature anomalies are detected.
- If the sudden change in temperature is within the limits of the static threshold, the alert system disengages, since the temperature change is not harmful, but the maintenance and operations employees are still notified.
- If the sudden change in temperature is not within the limits of the static threshold, the alert system continues to stay engaged until the temperature reaches the static threshold.
This project makes use of the Z-score algorithm for anomaly detection.
Definition: A Z-score is a numerical measurement that describes a value's relationship to the mean of a group of values. The Z-score is measured in terms of standard deviations from the mean.
Formulae and Calculations: The Z-score can be calculated by a handful of easy formulae. The machine learning code written in order to calculate the Z-score is iterative in nature, i.e., the Z-score is calculated every time the temperature is measured by the LM35 sensor.
The formulae required to calculate Z-score is shown below:
In the above picture, the variables are as follows:
1. Mn- Mean.
2. r = frame size.
3. I = iteration flag.
4. Vi = value of temperature at I (current value).
5. Zn = Z-score.
6. C = multiplication factor.
7. Tn = Threshold value.
Creating & Setting up an account on TwilioIntroduction:
Twilio is a 3rd party PaaS (Platform as a Software) company that provides cloud communication. It uses web APIs to make calls and send and receive messages to registered mobile numbers. The following gives step-by-step instructions to create a Twilio account.
1. URL-Go to https://www.twilio.com/ .
2. Sign up- You will find the welcome page. Here click on the "Sign up for free option"
3. Details- Enter your details, as shown, and click on the "Start your free trial" option. Twilio shows the services that are made available for your free trial account, on the right.
4. Verification- Twilio sends an email to your registered email ID. Open your email and check your inbox for the verification message from Twilio, and click on the link.
5. Mobile no. verification- After clicking on the "Confirm Your Email" link, you will be redirected to the Twilio page to finish creating the account by providing your mobile number.
6. Completing Verification- A verification code is sent to your mobile number, enter it, and click on "Submit".
7. Project creation- Twilio then proceeds to ask questions about the project that you are creating using the platform. Choose the most appropriate description of yourself and the project.
8. Language- Since the project is written in Python, select the Python option.
9. Usage of Twilio- Twilio cloud communication services are used for a project in this case, hence choose the "Use Twilio in a project" option.
10. SMS- In this Temperature monitoring project, we'll be using Twilio to send and receive SMS, hence, select that option.
11. Dashboard- We have now created a new project, the dashboard looks like this-
Account credentials such as SID (string identifier) and Auth Token (also called security token) are provided as soon as the project is created. We need to generate a number in order to receive messages. Hence choose the "Get a Trial Number" option. (NOTE- no payment is required, Twilio provides a trial balance).
12. Number generated- Twilio then generates a trial number in order to be able to send SMS from the trial account.
13. Programmable SMS- After the number is generated, click on the 3 horizontal line icon as shown in the image, this opens a side menu. Here choose the option "Programmable SMS".
This option allows you to send SMS from your Twilio account, the configuration of the same is given as follows.
14. SMS Configuration- Once the Programmable SMS option is chosen, select the "Try it out" option in the side menu in order to check if your registered mobile number is able to receive messages from Twilio at your given geographical location.
15. Try SMS- In the try SMS option, there is an option to send a trial message to your account, with a body of your own choice. After writing the body, select the "Make Request" option in order to send a trial SMS.
The status of the message is shown in the right bottom corner, as marked in the image.
The above screenshot is a message from the Twilio account. The request made was hence successful.
16. Creating new projects- New projects can be created for different requirements under the same account.
Click the arrow next to your current project and choose the "Create new Project" option.
And voila, a new project is created and you can name it as per your requirements.
17. Viewing all projects- All projects created by the user can be viewed for future usage or reference.
Under the same arrow next to the project name, "View all Projects" option is chosen to view all projects created by the user.
This panel appears where you can view all projects.
UbuntuUbuntu serves as a VPS- Virtual Private Server.
Before writing the code, we need to make sure the following packages are installed in Ubuntu:
1. Updating packages on Ubuntu-
sudo apt-get -y update
2. Installing python3 pip3-
sudo apt install python3-pip
3. Installing Boltiot library using pip
sudo pip3 install boltiot
CODE EXPLANATION:The code is explained here in detail.
Configurationfile- conf.py:
The conf.py file consists of all device credentials and the FRAME_SIZE and MUL_FACTOR. It also has max and min values stated as static thresholds.
1. Importing
import json,time,math,statistics
from boltiot import Bolt,Sms
import conf
We are importing the modules required for the Temperature monitoring. The json module is used to fetch data from online APIs and Bolt cloud. The time module is used for pausing the LED and buzzer. Modules like math, statistics are imported in order to calculate the Z-score. The public objects (Bolt, Sms) defined in the "boltiot" module are imported. Lastly the configuration file with all device and web API credentials in imported.
2. Dynamic Threshold:
def compute_threshold(history_data,frame_size,factor):
if len(history_data)<frame_size:
return None
if len(history_data)>frame_size:
del history_data[0:len(history_data)-frame_size]
In the above code, we define a function- compute_threshold
which takes in the parameters- history_data
(datatype-list/array), frame_size
(10), and factor
(C=6). If the number of elements in the array history_data
exceeds the frame_size
, then 10 values from history_data
are deleted.
3. Z-score calculation:
Mn=statistics.mean(history_data)
Variance=0
for data in history_data:
Variance=Variance+math.pow((data-Mn),2)
Zn=conf.MUL_FACTOR*(Variance/frame_size)
high_bound=history_data[frame_size-1]+Zn
low_bound=history_data[frame_size-1]-Zn
return(high_bound,low_bound)
The z-score is calculated using the formulae shown before. The mean of all the history_data is calculated, followed by the calculation of variance using the for loop. The variance is calculated in an iterative manner. The z-score (Zn) is calculated according to the formulae. Then the high_bound
is calculated, which is the higher threshold value and the low_bound
which is the lower threshold value.
4. Buzzer:
def buzzer():
response=mybolt.digitalWrite("0","HIGH")
data_b=json.loads(response)
if data_b['success']!=1:
print('An error has occurred while sending sound alert',data_b['value'])
else:
print("Buzzer ON")
A function buzzer
is defined for the working of the buzzer. It is connected to the GPIO pin 0. If the "success
" key in the list of data_b is not equal to 1, an error message is printed. Otherwise the buzzer is made to switch on.
5. LED:
def led():
response=mybolt.digitalWrite("1","HIGH")
data_c=json.loads(response)
if data_c['success']!=1:
print("An error has occured while switching on the LED")
else:
print("LED ON")
This function is similar to the Buzzer function.
6. Sending SMS:
mybolt=Bolt(conf.API_KEY,conf.DEVICE_ID)
sms=Sms(conf.SID,conf.AUTH_TOKEN,conf.TO_NUMBER,conf.FROM_NUMBER)
history_data=[]
In this part of the code, all device credentials are imported from the conf file. Here Bolt
and Sms
are public objects in the boltiot
module and hence can be accessed directed without specifying the name of the parent module (eg: boltiot.Bolt
). Again, mybolt
simply calls the Bolt function from boltiot
, it is the same with sms
.
7. Declaring an Infinite loop:
while True:
response=mybolt.analogRead("A0") #taking input from the analog-digital pin
data=json.loads(response) #converting the input to json script format
if data['success']!=1:
print("There was an error while retrieving the data")
print("This is the error",data['value'])
time.sleep(10)
print("This is the value",data['value'])
The infinite loop is declared to run the program till the while
condition becomes False
. Here we read the sensor value (from LM35) which is connected to the analog pin A0. The data from the sensor is loaded into the json script form so we can access the keys such as 'success
' and 'value
'. If the 'success
' is not equal to 1, an error message is printed. The time
module is then called for checking the condition again after 10 seconds. If the Bolt iot wifi module was successful in retrieving the data, the value under key 'value' in the data object is printed.
8. sensor_value:
sensor_value=0
try:
sensor_value=int(data['value'])
except Exception as e:
print("There was an error while parsing the response")
continue
Now the sensor value is declared. A try and except block follows this.
The try and except block is used to handle exceptions. If the code in the try
block throws an exception, it is handled by the except
block. So hence, in the code, the try
block assigns sensor_value
(type-int), a value from the data object obtained in the infinite while loop.
In case there was a failure in the assignment of the value, the except block is executed, which prints the error.
9. Comparing sensor_value
to static threshold:
try:
if sensor_value>conf.max or sensor_value<conf.min:
print("The sensor value has crossed threshold")
led()
buzzer()
response=sms.send_sms("The temperature of the refrigerator has gone out of threshol d")
print("The response received from Twilio is: "+ str(response))
print("The status of the SMS at Twilio is: " + str(response.status))
if sensor_value<conf.max or sensor_value>conf.min:
time.sleep(10)
response=mybolt.digitalWrite("0","LOW")
response=mybolt.digitalWrite("1","LOW")
except Exception as e:
print("There was an error while sending the SMS:", e)
Here we make use of the try and except block yet again. In the try
block, we compare the sensor_value
to the static thresholds defined in the conf file. If the sensor_value has crossed the static threshold, the led()
and buzzer()
functions are called, and at the same time, an SMS is sent. If the sensor_value
falls below the static threshold, the led and buzzer are required to switch off (GPIO pins 1 and 0 respectively).
The except block is written to handle any exceptions that arise while sending an SMS.
10. Data for Dynamic Threshold:
bound=compute_threshold(history_data,conf.FRAME_SIZE,conf.MUL_FACTOR)
if not bound:
required_data_count=conf.FRAME_SIZE-len(history_data)
print("There is no sufficient data, the no. of data points required is:",required_data_count)
history_data.append(int(data['value']))
time.sleep(10)
continue
The function compute_threshold
takes in the parameters- history_data, frame size and multiplication factor specified in conf file. The function returns a Boolean value (which is False
) and stored in bound
. The if
condition now checks the condition (not bound= True
) and calculates the required data count. If sufficient data is not available, it appends the latest sensor value to the the history_data
list.
11. Comparing sensor_value
to bound
:
try:
if sensor_value>bound[0]:
print("The temperature has increased, sending SMS")
response=sms.send_sms("The temperature has increased")
led()
buzzer()
print("This is the response",response)
history_data.append(sensor_value);
Here we use the try
block again. If the sensor_value
is greater than the value in bound at index 0, an SMS is sent and the LED and the buzzer are switched on.
We need to note that this code is written to detect sudden changes in temperature which is not favourable for perishable goods.
12. Temperature anomaly:
if sensor_value<bound[0]:
time.sleep(10)
response=mybolt.digitalWrite("0","LOW")
response=mybolt.digitalWrite("1","LOW")
except Exception as e:
print("error",e)
time.sleep(10)
If the temperature anomaly (sudden change in temperature) is below the static threshold, the led and buzzer switches off after 10 seconds. However, if the temperature anomaly is above the static threshold, the LED and buzzer continue alarming the service and maintenance team.
OutputIn the above image, it is seen that there are 2 messages sent by Twilio. The first message "The temperature has increased" is sent when there is an anomaly detected (sudden change), and the second message is sent when the temperature crossed the static threshold. For a better understanding, I would suggest you to watch the video.
Comments