During the last summer, I started studying about neural networks and machine learning. The topic interested me quite a lot and after I had spent a few weeks understanding the subject, I decided to put my new-found skills to a test by creating a project that increases the resolution of MRI images of the brain.
However, I did not have a GPU (Graphical Processing Unit) which is actually quite necessary for training a neural network (training the AI in simpler terms). So I had to resort to connect to GPUs on the cloud using Google Colab.
Since the training goes on for hours, I would start the training in the morning, go to my college and analyse the results when I came back home in the evening. All this seems wonderful but there is a catch. Many days I would return home only to find out that the entire days' training was lost and no progress would be made that day. Now, why did this happen? Training the network on GPUs on the cloud requires a stable internet connection. If the signal is lost or becomes too weak for a few minutes, the GPU gets disconnected all the training that was done for hours during that day would be lost.
So, I had to develop some way to keep a track of my internet connection so that in case the signal is lost or becomes too weak, someone in my house could connect my device to a different network or troubleshoot the WiFi router right away. That is when I remembered the Bolt IoT WiFi Module that was lying in my house. So, I started developing a device that could send me or someone in my house an alert when the internet signal became too weak. I also included two LEDs whose brightness would indicate the internet strength so that even if the alert is not acknowledged, the sight of a dim LED in the hall could inform the person in my house that the internet has become slow.
1. Introduction:The project has 3 output devices- 2 LEDs and a buzzer. The first LED indicates the download speed, the second LED indicates the upload speed and the buzzer buzzes whenever there is a sudden increase or decrease in the internet speed and a telegram message is also sent. The buzzer produces different sounds for sudden increase or decrease of upload speed and download speed. Z-score analysis is used to determine if there is a sudden change in internet speed. The speedtest module in python is used to collect the upload and download speeds at any instant of time.
2. Hardware Configuration:The longer terminal (+ve terminal) of the buzzer is connected to pin 0 of the Bolt WiFi Module and the shorter terminal to the ground pin using male/female jumper wires. The longer terminal of the first LED is connected to pin 1 of the Bolt WiFi Module while the shorter terminal is connected to pin 2. The longer terminal of the second LED is connected to pin 3 of the Bolt WiFi Module while the shorter terminal is connected to pin 4.
To control the bolt device remotely, the Device ID and API Key are required. Go to https://cloud.boltiot.com/ and login by entering your credentials. The following page is shown which contains the Device ID (highlighted in blue).
To find your API Key, navigate to the API page. Here, you can obtain the API key by either clicking on the show API Key button or by copying it to the clipboard and pasting it somewhere else.
- Sign-up for/sign-in to Telegram: Go to the Playstore on your phone, and download and install Telegram. Create a new account or sign-in to your account if it already exists. Telegram will give you a call or send you an SMS to verify your mobile number. Get your account verified and approve any permissions if required.
- Creating a channel: Go to Telegram and click on the hamburger button (the button with 3 dashes) on the top left corner of the screen to reveal the menu. Select New Channel. Enter a suitable name and description for your channel. In the next screen, set the channel as public. Also, enter a permanent link for your channel which can have lower case letters and numbers 0-9. This link will be later required to send messages to the channel.
- Creating a bot: Bots are required to send messages on a channel. The BotFather bot can be used to create bots. Click on the search icon on the top right corner of the screen and type "BotFather". Click on BotFather and this will open up a chat window. Type "/start" (without the quotes) and this will show you a list of commands. Type "/newbot" to create a new bot. Give your bot a name and a unique username. It will display a message containing the bot token. The telegram bot id is "bot" followed by the bot token. This telegram bot id will be later used to send messages. For example, if bot token is "894346529:AAhuJ2XJQy5dlEtLYF0sc0Z_qu", the telegram bot id is "bot894346529:AAhuJ2XJQy5dlEtLYF0sc0Z_qu". The message will also have the permanent link of the bot. Click on the link. This will take you to the chat window with the bot. Click on start at the bottom of the screen. You have now successfully activated your bot.
- Adding the bot to your channel: Go to your channel and click on the channel name at the top. Click on Administrators button. Click on Add Admin. Search for the name of the bot and select it. Click on the tick mark on the top right corner to add the bot to your channel. This completes everything that is required to receive messages through Telegram.
5.1ConfigurationFile:
File name: config.py
bolt_api_key = "XXXX" # Bolt Cloud API Key
device_id = "BOLTXXXX" # Device ID of the Bolt Module
telegram_chat_id = "@XXXX" # Telegram channel ID. Paste after @
telegram_bot_id = "botXXXX" # Telegram bot ID.
FRAME_SIZE = 5 # Frame Size for Z score analysis
MUL_FACTOR = 15 # Multiplication Factor for Z score analysis
The configuration file will be imported into the main code. We keep a separate configuration file so that any user can use the same code by only modifying the configuration file.
5.2Imports:
import math
import statistics
import speedtest # To find the internet speed
import requests
import json
import time
from boltiot import Bolt # To control the bolt module
import config # importing configuration file
Creating bolt object:
mybolt = Bolt(config.bolt_api_key, config.device_id)
5.3Finding Internet Speed:
def find_speed():
"""Returns the download and upload speed in Mbps"""
try:
st = speedtest.Speedtest()
down = st.download()/1e6
up = st.upload()/1e6
except:
print("Please check your internet connection")
return 0, 0
return down, up
5.4Sending Messages Via Telegram:
def send_telegram_message(message):
"""Sends message via Telegram
Returns true if message was successfully delivered"""
url = "https://api.telegram.org/" + config.telegram_bot_id + "/sendMessage"
data = {
"chat_id": config.telegram_chat_id,
"text": message
}
try:
response = requests.request(
"POST",
url,
params=data
)
print("This is the Telegram URL")
print(url)
print("This is the Telegram response")
print(response.text)
telegram_data = json.loads(response.text)
return telegram_data["ok"]
except Exception as e:
print("An error occurred in sending the alert message via Telegram")
print(e)
return False
5.5 Writing Analog Output To Bolt WiFi Module Pins:
def write_pin_value(pin, val):
"""Writes analog output to the given pin
Returns True if the value was successfully written"""
try:
response = mybolt.analogWrite(pin, val)
data = json.loads(response)
if data["success"] != 1:
print("Request not successfull")
print("This is the response->", data)
time.sleep(15)
except Exception as e:
print("Something went wrong when writing pin value")
print(e)
time.sleep(15)
return False
return True
5.6 Converting Internet Speed Into Suitable Value For Analog Write Function:
def translate(value, left_min=0, left_max=150, right_min=0, right_max=255):
"""Converts the value of internet signal into appropriate
voltage/analog output for bolt WiFi module"""
if value > 150:
return 255
left_span = left_max - left_min
right_span = right_max - right_min
scale = right_span/left_span
value_scaled = (value - left_min)*scale+right_min
return int(value_scaled)
The Bolt WiFi Module pins accept values between 0 and 255 (0 = no voltage, 255 = maximum voltage). So we need to convert the internet speed into the required range. This is just a basic conversion from one range to another, maintaining the same ratio, which is performed by the translate() function. To do this, we find the ratio between input and output ranges. Then we multiply the input value by the ratio (scale) to get the result. (Since the minimum value of both input and output ranges are 0, the explanation provided here is accurate. However, the code written here is robust and works even if the minimum values for the ranges are not 0).
The input range is from 0 to 150 and the output range is from 0 to 255. If the internet speed is greater than 150 Mbps, the output becomes 255.
5.7 Computing Bounds Using Z-Score Analysis:
Z-Score analysis is used for anomaly detection (to detect if there is a sudden change in the internet speed). The compute_bound() function computes the upper and lower bounds using Z-Score analysis. If the data point is not located inside the bounds, it is considered as an anomaly.
The function takes 3 variables :
- history_data: Contains the data on which bounds have to be calculated.
- frame_size: It is the number of data points that has to be taken into account for computing the bounds.
- factor: It is the multiplication factor which defines the size of the bound. Greater the factor, bigger the bound i.e. greater tolerance to variation in data.
def compute_bounds(history_data, frame_size, factor):
"""Used to compute bounds for Z-score analysis
Returns the upper and lower bounds"""
if len(history_data)<frame_size :
return None
if len(history_data)>frame_size :
del history_data[0:len(history_data)-frame_size]
Mn = statistics.mean(history_data)
Variance = 0
for data in history_data :
Variance += math.pow((data-Mn),2)
Zn = factor * math.sqrt(Variance / frame_size)
High_bound = history_data[frame_size-1]+Zn
Low_bound = history_data[frame_size-1]-Zn
return [High_bound, Low_bound]
Here, r is Frame Size and C is Multiplication Factor.
Mn is mean of the data for the last 'r' data points.
Zn is Z-Score which is the product of multiplication factor and standard deviation of the last 'r' data points.
Tn is the bounds. It is obtained by adding and subtracting Z-Score with the data point under observation.
5.8 Body of the Program:
# Make sure that all pins are in OFF state
write_pin_value('0', 0)
write_pin_value('1', 0)
write_pin_value('2', 0)
write_pin_value('3', 0)
write_pin_value('4', 0)
pin1 = '1' # First LED pin (Download speed)
pin2 = '3' # Second LED pin (Upload speed)
pin3 = '0' # Buzzer pin
download_history = []
upload_history = []
while True:
# Obtain the download and upload speed
download, upload = find_speed()
# Switching OFF the buzzer in case it was ON
write_pin_value(pin3, 0)
if write_pin_value(pin1, translate(download)):
print("Download Speed is:", download, "Mbps")
bound = compute_bounds(download_history, config.FRAME_SIZE, config.MUL_FACTOR)
if not bound:
req_data_count = config.FRAME_SIZE - len(download_history)
print("Not enough data to compute Z-score. Need ",
req_data_count, " more data points")
else:
if download > bound[0]:
message = "Enjoy the moment.Your download speed is a blazing " \
+ str(download) + " Mbps"
send_telegram_message(message)
write_pin_value(pin3, 255)
time.sleep(5)
elif download < bound[1]:
message = "Check your net connection.Your download speed is " \
+ str(download) + " Mbps"
send_telegram_message(message)
write_pin_value(pin3, 200)
time.sleep(5)
download_history.append(download)
if write_pin_value(pin2, translate(upload)):
print("Upload Speed is:", upload, "Mbps")
bound = compute_bounds(upload_history, config.FRAME_SIZE, config.MUL_FACTOR)
if not bound:
req_data_count = config.FRAME_SIZE - len(upload_history)
print("Not enough data to compute Z-score. Need ", req_data_count,
" more data points")
else:
if upload > bound[0]:
message = "Enjoy the moment.Your upload speed is a blazing " \
+ str(upload) + " Mbps"
send_telegram_message(message)
write_pin_value(pin3, 100)
time.sleep(5)
elif upload < bound[1]:
message = "Check your internet connection.Your upload speed is "\
+ str(upload) + " Mbps"
send_telegram_message(message)
write_pin_value(pin3, 50)
time.sleep(5)
upload_history.append(upload)
The program obtains the download and upload speed using the speedtest module. The values are then converted between 0 and 255 by using the translate() function, and are written on the corresponding Bolt WiFi Module pins which causes the LEDs to glow. The brightness depends on the value written. In case of sudden changes in internet speed, the buzzer buzzes with a sound that indicates the type of change that has occurred and an alert is also sent via telegram. The buzzer stops buzzing after a few seconds.
Comments
Please log in or sign up to comment.