Home Automation Treadmill Bike

Diego Condori
15 min readJan 16, 2022

Hello, this is my home automation project, the bicycle treadmill, this bicycle treadmill had a clock and a step counter at the beginning, but as time passed it no longer worked very well, so I decided to use the raspberry pi 3 b+, a rPi screen and a IR sensor obstacle detector, create a simple interface for the end user, in which the end user can change music whenever he wants, also see a cartesian plane where the number of steps taken by the end user is shown. achieved thanks to the IR sensor obstacle detector against time.
Next I will show how I made this project of mine. For this project, a treadmill will be used.

Treadmill Bike

A raspberry pi 3 b+, with a 3.5-inch rPi screen.

Raspberry pi 3 b+ and Rpi Display 3.5 inches

Use the IR sensor obstacle detector to capture every step you take on the treadmill.

IR sensor obstacle detector.

For the case, I had it printed on a 3d printer, the model is on the following page: https://www.thingiverse.com/thing:3473751/files.

3d model of the case.

With adhesive velcro attach it to the treadmill.

Treadmill with velcro.
Treadmill with velcro and Raspberry pi 3 b+.

To attach the IR sensor obstacle detector I did it as follows.

IR sensor obstacle detector Attachment.

The sensor connection is as follows.

Connection

For the programming of the raspberry pi I used html, css, javascript, python, bash and mysql.

For the music section html, css and javascript were used.

music.html:

<!DOCTYPE html>
<html lang="en">
<head>
<title>Simple Music Player</title>
<!-- Load FontAwesome icons -->
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css">

<!-- Load the custom CSS style file -->
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="player">

<!-- Define the section for displaying details -->
<div class="details">
<div class="now-playing">REPRODUCIENDO x DE y</div>
<div class="track-name">Nombre de la cancion</div>
<div class="track-art"></div>
<div class="track-artist">------------------------------------------------------------</div>
</div>

<!-- Define the section for displaying track buttons -->
<div class="buttons">
<div class="prev-track" onclick="prevTrack()">
<i class="fa fa-step-backward fa-2x"></i>
</div>
<div class="playpause-track" onclick="playpauseTrack()">
<i class="fa fa-play-circle fa-5x"></i>
</div>
<div class="next-track" onclick="nextTrack()">
<i class="fa fa-step-forward fa-2x"></i>
</div>
</div>


<div class="slider_container">
<div class="current-time">00:00</div>
<input type="range" min="1" max="100"
value="0" class="seek_slider" onchange="seekTo()">
<div class="total-duration">00:00</div>
</div>


<div class="slider_container">
<i class="fa fa-volume-down"></i>
<input type="range" min="1" max="100"
value="99" class="volume_slider" onchange="setVolume()">
<i class="fa fa-volume-up"></i>
</div>
</div>

<!-- Load the main script for the player -->
<script src="main.js"></script>
</body>
</html>

main.js:

// Select all the elements in the HTML page
// and assign them to a variable
let now_playing = document.querySelector(".now-playing");
let track_art = document.querySelector(".track-art");
let track_name = document.querySelector(".track-name");
let track_artist = document.querySelector(".track-artist");

let playpause_btn = document.querySelector(".playpause-track");
let next_btn = document.querySelector(".next-track");
let prev_btn = document.querySelector(".prev-track");

let seek_slider = document.querySelector(".seek_slider");
let volume_slider = document.querySelector(".volume_slider");
let curr_time = document.querySelector(".current-time");
let total_duration = document.querySelector(".total-duration");

// Specify globally used values
let track_index = 0;
let isPlaying = false;
let updateTimer;

// Create the audio element for the player
let curr_track = document.createElement('audio');

// Define the list of tracks that have to be played
let track_list = [
{
name: "AmoresLejanos",
artist: "------------------------------------------------------------",
image: "Image URL",
path: "AmoresLejanos.mp3"
},

{
name: "Time",
artist: "------------------------------------------------------------",
image: "Image URL",
path: "Time.mp3"
},

];

function loadTrack(track_index) {
// Clear the previous seek timer
clearInterval(updateTimer);
resetValues();

// Load a new track
curr_track.src = track_list[track_index].path;
curr_track.load();

// Update details of the track
track_art.style.backgroundImage =
"url(" + track_list[track_index].image + ")";
track_name.textContent = track_list[track_index].name;
track_artist.textContent = track_list[track_index].artist;
now_playing.textContent =
"PLAYING " + (track_index + 1) + " OF " + track_list.length;

// Set an interval of 1000 milliseconds
// for updating the seek slider
updateTimer = setInterval(seekUpdate, 1000);

// Move to the next track if the current finishes playing
// using the 'ended' event
curr_track.addEventListener("ended", nextTrack);

// Apply a random background color
random_bg_color();
}

function random_bg_color() {
// Get a random number between 64 to 256
// (for getting lighter colors)
let red = Math.floor(Math.random() * 256) + 64;
let green = Math.floor(Math.random() * 256) + 64;
let blue = Math.floor(Math.random() * 256) + 64;

// Construct a color withe the given values
let bgColor = "rgb(" + red + ", " + green + ", " + blue + ")";

// Set the background to the new color
document.body.style.background = bgColor;
}

// Function to reset all values to their default
function resetValues() {
curr_time.textContent = "00:00";
total_duration.textContent = "00:00";
seek_slider.value = 0;
}

function playpauseTrack() {
// Switch between playing and pausing
// depending on the current state
if (!isPlaying) playTrack();
else pauseTrack();
}

function playTrack() {
// Play the loaded track
curr_track.play();
isPlaying = true;

// Replace icon with the pause icon
playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
}

function pauseTrack() {
// Pause the loaded track
curr_track.pause();
isPlaying = false;

// Replace icon with the play icon
playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';
}

function nextTrack() {
// Go back to the first track if the
// current one is the last in the track list
if (track_index < track_list.length - 1)
track_index += 1;
else track_index = 0;

// Load and play the new track
loadTrack(track_index);
playTrack();
}

function prevTrack() {
// Go back to the last track if the
// current one is the first in the track list
if (track_index > 0)
track_index -= 1;
else track_index = track_list.length - 1;

// Load and play the new track
loadTrack(track_index);
playTrack();
}

function seekTo() {
// Calculate the seek position by the
// percentage of the seek slider
// and get the relative duration to the track
seekto = curr_track.duration * (seek_slider.value / 100);

// Set the current track position to the calculated seek position
curr_track.currentTime = seekto;
}

function setVolume() {
// Set the volume according to the
// percentage of the volume slider set
curr_track.volume = volume_slider.value / 100;
}

function seekUpdate() {
let seekPosition = 0;

// Check if the current track duration is a legible number
if (!isNaN(curr_track.duration)) {
seekPosition = curr_track.currentTime * (100 / curr_track.duration);
seek_slider.value = seekPosition;

// Calculate the time left and the total duration
let currentMinutes = Math.floor(curr_track.currentTime / 60);
let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
let durationMinutes = Math.floor(curr_track.duration / 60);
let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);

// Add a zero to the single digit time values
if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; }

// Display the updated duration
curr_time.textContent = currentMinutes + ":" + currentSeconds;
total_duration.textContent = durationMinutes + ":" + durationSeconds;
}
}

style.css:

body {
background-color: lightgreen;
/* Smoothly transition the background color */
transition: background-color .5s;
}

/* Using flex with the column direction to
align items in a vertical direction */
.player {
height: 95vh;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
}

.details {
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
margin-top: 25px;
}

.track-art {
margin: 1px;
height: 1px;
width: 10px;
/*background-image: URL(
"https://source.unsplash.com/Qrspubmx6kE/640x360");*/
background-size: cover;
background-position: center;
border-radius: 15%;
}

/* Changing the font sizes to suitable ones */
.now-playing {
font-size: 1rem;
}

.track-name {
font-size: 3rem;
}

.track-artist {
font-size: 1.5rem;
}

/* Using flex with the row direction to
align items in a horizontal direction */
.buttons {
display: flex;
flex-direction: row;
align-items: center;
}

.playpause-track,
.prev-track,
.next-track {
padding: 25px;
opacity: 0.8;

/* Smoothly transition the opacity */
transition: opacity .2s;
}

/* Change the opacity when mouse is hovered */
.playpause-track:hover,
.prev-track:hover,
.next-track:hover {
opacity: 1.0;
}

/* Define the slider width so that it scales properly */
.slider_container {
width: 75%;
max-width: 400px;
display: flex;
justify-content: center;
align-items: center;
}

/* Modify the appearance of the slider */
.seek_slider, .volume_slider {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
height: 5px;
background: black;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
}

/* Modify the appearance of the slider thumb */
.seek_slider::-webkit-slider-thumb,
.volume_slider::-webkit-slider-thumb {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
width: 15px;
height: 15px;
background: white;
cursor: pointer;
border-radius: 50%;
}

/* Change the opacity when mouse is hovered */
.seek_slider:hover,
.volume_slider:hover {
opacity: 1.0;
}

.seek_slider {
width: 60%;
}

.volume_slider {
width: 30%;
}

.current-time,
.total-duration {
padding: 10px;
}

i.fa-volume-down,
i.fa-volume-up {
padding: 10px;
}

/* Change the mouse cursor to a pointer
when hovered over */
i.fa-play-circle,
i.fa-pause-circle,
i.fa-step-forward,
i.fa-step-backward {
cursor: pointer;
}

Before showing the section of the Cartesian plane, a very simple database was created to create it, which is shown below.

Database for the sensor.

For the creation of the Cartesian plane section, the javascript highcharts library was used.

sensor.php:

<?php
$mysqli = new mysqli("localhost","user_sensor","user_pass_301","sensor");

// Check connection
if ($mysqli -> connect_errno) {
echo "Failed to connect to MySQL: " . $mysqli -> connect_error;
exit();
}
$index = 0;
$dateSensor = array();
// Perform query
if ($result = $mysqli -> query("SELECT datetime, cantidad_pasos FROM tsensor")) {
//echo "Returned rows are: " . $result -> num_rows;
// Free result set
//$result -> free_result();
while($row = $result -> fetch_row())
{
//printf("%s %s %s <br>", $row[0], $row[1], $row[2]);
$dateSensor[$index]=$row;
$index = $index + 1;
}
$result -> free_result();
}
//echo json_encode($dateSensor, JSON_NUMERIC_CHECK);
$mysqli -> close();
?>
<?php
$page = $_SERVER['PHP_SELF'];
$sec = "10";
?>

<!DOCTYPE html>
<html>
<head>
<title>Datos</title>
<meta http-equiv="refresh" content="<?php echo $sec?>;URL='<?php echo $page?>'">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js"></script>

</head>
<body>

<script type="text/javascript">
$(function () {

$('#container').highcharts({
chart: {
type: 'line'
},

time: {
timezone: 'Bolivia/La Paz'
},
title: {
text: 'Cantidad de pasos vs Tiempo'
},

xAxis: {
title: {
text: 'Tiempo'
},
type: 'datetime',
},
yAxis: {
title: {
text: 'Cantidad Pasos'
}
},
series: [{
name: 'Pasos',
data: <?php echo json_encode($dateSensor, JSON_NUMERIC_CHECK);?>
}]
});
});

</script>
<script src="charts/js/highcharts.js"></script>
<script src="charts/js/modules/exporting.js"></script>

<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-body">
<div id="container"></div>
</div>
</div>
</div>
</div>
</div>

</body>
</html>

Now with these two sections, the main page that will be shown below is created.

index.php:

<!DOCTYPE html>
<html>
<head>
<title>Trotadora</title>
<style type="text/css">
@import url('https://fonts.googleapis.com/css?family=Lato:100,100i,300,300i,400,400i,700,700i,900,900i');
*
{
margin: 0;
padding: 0;
}

body
{
font-family: 'Lato', sans-serif;
font-size: 14px;
color: #999999;
word-wrap:break-word;
}

p
{
margin: 0 0 10px;
}

ul
{
list-style: none;
}
button {
border-radius: 50%;
padding: 0.5em;
width: 60px;
height: 60px;
border: 2px solid #A5ADB0;
color: #A5ADB0 ;
position: relative;
}
#button_home_2 {
border-radius: 50%;
padding: 0.5em;
width: 20px;
height: 20px;
border: 2px solid #A5ADB0;
color: #A5ADB0 ;
position: relative;
}
button:hover {
border: 2px solid #A5ADB0;
background-color: #8F9496;
color: #ffffff;
}
.container {
height: 200px;
position: relative;
}
.center {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
}
/*
button::before {
content: " ";
position: absolute;
display: block;
background-color: #727778 ;
width: 2px;
left: 12px;
top: 5px;
bottom: 3px;
transform: rotate(45deg);
}
button::after {
content: " ";
position: absolute;
display: block;
background-color: #727778 ;
height: 2px;
top:12px;
left: 5px;
right: 5px;
transform: rotate(45deg);
}
*/
.container {
width: 100%;
margin: auto;
font-weight: 900;
text-transform: uppercase;
text-align: center;
padding: 0 0 30px;
}

/*.take-input {
margin: 50px 0 0;
}

.take-input input {
width: 400px;
height: 35px;
padding: 0 10px;
border-radius: 5px;
border: 1px solid #ececec;
margin: 0 15px 0 0;
font-size: 15px;
}*/

a, a:link, a:visited {
text-decoration: none;
padding: 9px 15px;
border: 1px solid #A5ADB0;
border-radius: 5px;
color: gray;
}

.animate {
font-size: 100px;
margin: 100px 0 0;
border-bottom: 2px solid #A5ADB0;
font-weight: 90;
}

.animate span {
display: inline-block;
}

a.repeat {
display: inline-block;
font-size: 12px;
text-transform: none;
text-decoration: none;
color: orange;
padding: 5px 12px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-weight: normal;
margin: 0 0 0 50px;
border-radius: 3px;
position: relative;
bottom: 15px;
}

a.repeat:hover {
background: rgba(0, 0, 0, 0.7);
color: white;
}

.animate span:nth-of-type(2) {
animation-delay: .05s;
}
.animate span:nth-of-type(3) {
animation-delay: .1s;
}
.animate span:nth-of-type(4) {
animation-delay: .15s;
}
.animate span:nth-of-type(5) {
animation-delay: .2s;
}
.animate span:nth-of-type(6) {
animation-delay: .25s;
}
.animate span:nth-of-type(7) {
animation-delay: .3s;
}
.animate span:nth-of-type(8) {
animation-delay: .35s;
}
.animate span:nth-of-type(9) {
animation-delay: .4s;
}
.animate span:nth-of-type(10) {
animation-delay: .45s;
}
.animate span:nth-of-type(11) {
animation-delay: .5s;
}
.animate span:nth-of-type(12) {
animation-delay: .55s;
}
.animate span:nth-of-type(13) {
animation-delay: .6s;
}
.animate span:nth-of-type(14) {
animation-delay: .65s;
}
.animate span:nth-of-type(15) {
animation-delay: .7s;
}
.animate span:nth-of-type(16) {
animation-delay: .75s;
}
.animate span:nth-of-type(17) {
animation-delay: .8s;
}
.animate span:nth-of-type(18) {
animation-delay: .85s;
}
.animate span:nth-of-type(19) {
animation-delay: .9s;
}
.animate span:nth-of-type(20) {
animation-delay: .95s;
}

/* Animation Seven */


.seven span {
color: #A5ADB0;
opacity: 0;
transform: translate(-150px, 0) scale(.3);
animation: leftRight .5s forwards;
}


@keyframes leftRight {
40% {
transform: translate(50px, 0) scale(.7);
opacity: 1;
color: #A5ADB0;
}

60% {
color: #A5ADB0;
}

80% {
transform: translate(0) scale(2);
opacity: 0;
}

100% {
transform: translate(0) scale(1);
opacity: 1;
}
}
</style>
</head>

<body>
<div class="container">
<div class="animate seven">
<span>T</span><span>R</span><span>O</span><span>T</span><span>A</span><span>D</span><span>O</span><span>R</span><span>A</span>
</div>
</div>
<div class="container">
<div class="center">
<button type="button" id="button_music">☼</button>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<button type="button" id="button_steps">☼</button>
</div>
</div>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<iframe id="music_section"
title="Seccion de musica"
width="500"
height="400"
src="http://localhost/music.html">
</iframe><button type="button" id="button_home_1">☼</button>
<br><br><br><br>
<iframe id="steps_section"
title="Seccion de la tabla de pasos"
width="700"
height="455"
src="http://localhost/sensor.php">
</iframe><button type="button" id="button_home_2">☼</button>
<script type="text/javascript">
document.getElementById("button_music").onclick = function()
{
location.href = '#music_section';
};
document.getElementById("button_steps").onclick = function()
{
location.href = '#steps_section';
};
document.getElementById("button_home_1").onclick = function()
{
location.href = '#';
};
document.getElementById("button_home_2").onclick = function()
{
location.href = '#';
};
$(function(){
$('.repeat').click(function(){
var classes = $(this).parent().attr('class');
$(this).parent().attr('class', 'animate');
var indicator = $(this);
setTimeout(function(){
$(indicator).parent().addClass(classes);
}, 20);
});
});
</script>

</body>
</html>

Where the songs should be added are in the /var/www/html/ directory after you have to update the main.js, but I automate the adding process with the following script.

add_music.sh:

var1="// Select all the elements in the HTML page
// and assign them to a variable
let now_playing = document.querySelector(\".now-playing\");
let track_art = document.querySelector(\".track-art\");
let track_name = document.querySelector(\".track-name\");
let track_artist = document.querySelector(\".track-artist\");

let playpause_btn = document.querySelector(\".playpause-track\");
let next_btn = document.querySelector(\".next-track\");
let prev_btn = document.querySelector(\".prev-track\");

let seek_slider = document.querySelector(\".seek_slider\");
let volume_slider = document.querySelector(\".volume_slider\");
let curr_time = document.querySelector(\".current-time\");
let total_duration = document.querySelector(\".total-duration\");

// Specify globally used values
let track_index = 0;
let isPlaying = false;
let updateTimer;

// Create the audio element for the player
let curr_track = document.createElement('audio');

// Define the list of tracks that have to be played
let track_list = ["

var2="
];

function loadTrack(track_index) {
// Clear the previous seek timer
clearInterval(updateTimer);
resetValues();

// Load a new track
curr_track.src = track_list[track_index].path;
curr_track.load();

// Update details of the track
track_art.style.backgroundImage =
\"url(\" + track_list[track_index].image + \")\";
track_name.textContent = track_list[track_index].name;
track_artist.textContent = track_list[track_index].artist;
now_playing.textContent =
\"PLAYING \" + (track_index + 1) + \" OF \" + track_list.length;

// Set an interval of 1000 milliseconds
// for updating the seek slider
updateTimer = setInterval(seekUpdate, 1000);

// Move to the next track if the current finishes playing
// using the 'ended' event
curr_track.addEventListener(\"ended\", nextTrack);

// Apply a random background color
random_bg_color();
}

function random_bg_color() {
// Get a random number between 64 to 256
// (for getting lighter colors)
let red = Math.floor(Math.random() * 256) + 64;
let green = Math.floor(Math.random() * 256) + 64;
let blue = Math.floor(Math.random() * 256) + 64;

// Construct a color withe the given values
let bgColor = \"rgb(\" + red + \", \" + green + \", \" + blue + \")\";

// Set the background to the new color
document.body.style.background = bgColor;
}

// Function to reset all values to their default
function resetValues() {
curr_time.textContent = \"00:00\";
total_duration.textContent = \"00:00\";
seek_slider.value = 0;
}

function playpauseTrack() {
// Switch between playing and pausing
// depending on the current state
if (!isPlaying) playTrack();
else pauseTrack();
}

function playTrack() {
// Play the loaded track
curr_track.play();
isPlaying = true;

// Replace icon with the pause icon
playpause_btn.innerHTML = '<i class=\"fa fa-pause-circle fa-5x\"></i>';
}

function pauseTrack() {
// Pause the loaded track
curr_track.pause();
isPlaying = false;

// Replace icon with the play icon
playpause_btn.innerHTML = '<i class=\"fa fa-play-circle fa-5x\"></i>';
}

function nextTrack() {
// Go back to the first track if the
// current one is the last in the track list
if (track_index < track_list.length - 1)
track_index += 1;
else track_index = 0;

// Load and play the new track
loadTrack(track_index);
playTrack();
}

function prevTrack() {
// Go back to the last track if the
// current one is the first in the track list
if (track_index > 0)
track_index -= 1;
else track_index = track_list.length - 1;

// Load and play the new track
loadTrack(track_index);
playTrack();
}

function seekTo() {
// Calculate the seek position by the
// percentage of the seek slider
// and get the relative duration to the track
seekto = curr_track.duration * (seek_slider.value / 100);

// Set the current track position to the calculated seek position
curr_track.currentTime = seekto;
}

function setVolume() {
// Set the volume according to the
// percentage of the volume slider set
curr_track.volume = volume_slider.value / 100;
}

function seekUpdate() {
let seekPosition = 0;

// Check if the current track duration is a legible number
if (!isNaN(curr_track.duration)) {
seekPosition = curr_track.currentTime * (100 / curr_track.duration);
seek_slider.value = seekPosition;

// Calculate the time left and the total duration
let currentMinutes = Math.floor(curr_track.currentTime / 60);
let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
let durationMinutes = Math.floor(curr_track.duration / 60);
let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);

// Add a zero to the single digit time values
if (currentSeconds < 10) { currentSeconds = \"0\" + currentSeconds; }
if (durationSeconds < 10) { durationSeconds = \"0\" + durationSeconds; }
if (currentMinutes < 10) { currentMinutes = \"0\" + currentMinutes; }
if (durationMinutes < 10) { durationMinutes = \"0\" + durationMinutes; }

// Display the updated duration
curr_time.textContent = currentMinutes + \":\" + currentSeconds;
total_duration.textContent = durationMinutes + \":\" + durationSeconds;
}
}"

set=""

for i in $(ls);
do
extension=$(sudo echo $i | tr '.' ' ' | awk '{print $2}')
name=$(sudo echo $i | tr '.' ' ' | awk '{print $1}')
element="
{
name: \"$name\",
artist: \"------------------------------------------------------------\",
image: \"Image URL\",
path: \"$i\"
},
"
if [ $extension = "mp3" ]
then
set+="$element"
fi
done

var="$var1$set$var2"
sudo echo "$var" > main.js

To read the sensor and send it to the database, python was used:

sensor.py

#!/usr/bin/env python

import os
import time
import datetime
import glob
import MySQLdb
from time import strftime
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

# Declaration of the input pin which is connected with the sensor
GPIO_PIN = 12
GPIO.setup(GPIO_PIN, GPIO.IN, pull_up_down = GPIO.PUD_UP)

def dateTime(): #get UNIX time
secs = float(time.time())
secs = secs*1000
return secs
def sensorRead(x):
try:
if not GPIO.input(GPIO_PIN):
return x + 1
except KeyboardInterrupt:
GPIO.cleanup()
return x

db = MySQLdb.connect(host = "localhost", user = "user_sensor", passwd = "user_pass_301", db = "sensor")
cur = db.cursor()

delayTime = 0.2

while(True):
secs = dateTime()
#read = sensorRead(1)

query = "select * from tsensor ORDER BY id DESC LIMIT 1"

cur.execute(query)

myresult = cur.fetchall()

#print(myresult[0][2])

read = sensorRead(myresult[0][2])

sql = ("""INSERT INTO tsensor (datetime, cantidad_pasos) VALUES (%s,%s)""", (secs, read))

try:
#print("Writing to the database...")
cur.execute(*sql)
db.commit()
#print("Write complete")

except:
db.rollback()
#print("We have a problem")
time.sleep(delayTime)
cur.close()
db.close()

Note that this script must be executed every time the main page is initialized in the browser of the raspberry pi 3, when it is in full screen mode.

I have a bash script that every time the raspberry pi 3 is turned on this script is executed, the purpose of this regarding the project is that every time the raspberry pi 3 is turned on it starts in 0 steps and this be recorded in the database.

sudo mysql -uroot -proot sensor -e "DELETE FROM tsensor WHERE datetime >= 0"
sudo mysql -uroot -proot sensor -e "INSERT INTO tsensor(datetime, cantidad_pasos) VALUES($(($(date +%s%N)/1000000)), 0)"

The following article can be of help for the proper functionality of the above script shown: https://www.dexterindustries.com/howto/run-a-program-on-your-raspberry-pi-at-startup/.

Finally I will show the total operation of all these scripts.

All these scripts are in my github: https://github.com/diegojoel301/Bicicleta-Trotadora-Domotizada.

That would be my project which I will work on in a week considering that I have a somewhat busy life, thank you very much for viewing my article.

--

--

Diego Condori

eJPT | eCPPT | Pentester Red Team | Computer Science Student | Programmer