В наше время обычная вещь, подключённая к интернету, начинает становиться обыденностью. Даже появилось понятие — «интернет вещей» (Internet of Things, IoT). Но как подступиться к этому своеобразному интернету новичку — не всегда понятно, потому что хотя статей по данной теме много, но каждому хочется, чтобы статья была простой для воспроизведения и чтобы в ней разбиралось что-то очень близкое и приятное для читателя.
Поэтому попробуем подключить к интернету самое простое — светодиод, взятый из сломанной оптической мыши. Будем через страницу в интернете включать и выключать светодиод, управлять частотой его мерцаний.
Схема подключения светодиода к интернету будет следующая:

Итак, соберём все детали на столе и спаяем нашу простую схемку. Из мышки достаём светодиод и резистор в 220 Ом. Резистор нужен для ограничения тока, он мелкий и его еле можно разглядеть на конце провода. Для соединения проводов с GPIO использую коннекторы, которые выпросил в сервисе, ремонтирующем компьютеры.

На сервере и «малинке» должен стоять node.js и npm (node package manager). Устанавливаем по данной инструкции.
Для того, чтобы node.js смог работать с GPIO, требуется установить модуль rpi-gpio. А для соединения с сервером RPi потребуется
Следующий код на сервере создаёт сервер на порту 3141 и принимает команду setfps и рассылает её дальше всем браузерам и Raspberry Pi.
Запускаем скрипты следующим образом. На RaspberryPi — с правами рута:
На странице своего сайта включаем код для слайдера jquery-ui и socket.io с нашего сервера. При получении сигнала от node.js-сервера слайдер выставляет текущее значение fps и наоборот — при передвижении слайдера мы на сервер отсылаем новое значение fps, которое сервер затем рассылает всем клиентам в браузеры и на Raspberry Pi.
А вот и видео, описывающее, что получилось:
Вот, собственно, и всё, светодиод подключен к интернету. Теперь с любого устройства с интернетом мы можем управлять его мерцанием. Простор для дальнейшего творчества большой. Можно к выводам подключить модуль-реле и кнопкой на своём сайте включать и выключать любое оборудование. Модулей для Raspberry Pi продаётся очень много, поэтому полёт фантазии почти не ограничен, особенно если в наличии восторженный восьмилетний почитатель электроники.
Документация Socket.io;
Документация Node.js;
Пакет rpi-gpio;
Документация на jquery-ui слайдер;
Распиновка GPIO на Raspberry Pi;
Модуль respawn для автоматического запуска nodejs-приложения (но я выбрал crontab).
Код можете взять из rpi-led на гитхабе.
Поэтому попробуем подключить к интернету самое простое — светодиод, взятый из сломанной оптической мыши. Будем через страницу в интернете включать и выключать светодиод, управлять частотой его мерцаний.
Для нашего эксперимента потребуется
- Интернет через ethernet кабель
- Raspberry Pi
- Сломанная оптическая мышка, провода, паяльник
- Доступ к сайту на vps с правами рута
Собираем схему
Схема подключения светодиода к интернету будет следующая:

Итак, соберём все детали на столе и спаяем нашу простую схемку. Из мышки достаём светодиод и резистор в 220 Ом. Резистор нужен для ограничения тока, он мелкий и его еле можно разглядеть на конце провода. Для соединения проводов с GPIO использую коннекторы, которые выпросил в сервисе, ремонтирующем компьютеры.

Подготавливаем софт
На сервере и «малинке» должен стоять node.js и npm (node package manager). Устанавливаем по данной инструкции.
Для того, чтобы node.js смог работать с GPIO, требуется установить модуль rpi-gpio. А для соединения с сервером RPi потребуется
socket.io-client
. Устанавливаются пакеты командой sudo npm install rpi-gpio
и sudo npm install socket.io-client
. Скрипт для node.js на Raspberry Pi:
var socket = require('socket.io-client')('vpssite.domain:3141');
var gpio = require('rpi-gpio');
var fs = require('fs');
// hack due to error
fs.exists = require('path').exists;
var async = require('async');
// pin GPIO4
var pin = 7;
// current fps
var piFps = 0;
var currentValue = false;
var timemanager;
var set0 = function(err, results) {
if (err)
console.log(err);
console.log('Pin ' + pin + ' closed');
directWrite(pin, false, function() {
clearTimeout(timemanager);
});
};
var blinkexec = function() {
delayedWrite(7, true, function() {
delayedWrite(7, false, blinkexec)
});
};
var blink = function(err, results) {
if (err)
console.log(err);
console.log('Pin ' + pin + ' blinking');
blinkexec();
};
function directWrite(pin, value, callback) {
return gpio.write(pin, value, callback);
}
function delayedWrite(pin, value, callback) {
var delay = Math.round(1000 / piFps / 2);
clearTimeout(timemanager);
timemanager = setTimeout(function() {
directWrite(pin, value, callback);
}, delay);
}
var release = function() {
console.log('Writes complete, pause then unexport pins');
setTimeout(function() {
gpio.destroy(function() {
console.log('Closed pins, now exit');
return process.exit(0);
});
}, 500);
};
socket.on('connect', function() {
console.log('connected');
socket.on('setfps', function(data) {
console.log(data);
if (data.fps > 0) {
piFps = data.fps;
gpio.setup(pin, gpio.DIR_OUT, blink);
} else {
gpio.setup(pin, gpio.DIR_OUT, set0);
}
});
socket.on('disconnect', function() {
console.log('disconnect');
release();
});
});
Следующий код на сервере создаёт сервер на порту 3141 и принимает команду setfps и рассылает её дальше всем браузерам и Raspberry Pi.
Скрипт для node.js на vps
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var allClients = [];
var count = 0;
var fpsPi = 0;
server.listen(3141);
server.on('error', function(e) {
if (e.code == 'EADDRINUSE') {
console.log('Address in use, exit...');
process.exit();
}
});
app.get('/', function (req, res) {
res.send('Fps is ' + fpsPi);
console.log('requested / - show ' + fpsPi);
});
function getDate() {
var datas = new Date();
return datas.getHours() + ':' + datas.getMinutes() + ':' + datas.getSeconds() + '.' + datas.getMilliseconds()
}
function consolelog(msg) {
console.log(getDate() + ' ' + msg);
}
io.on('connection', function (socket) {
io.emit('setfps', {fps: fpsPi});
// browser subscribes to listen to the station
socket.on('subscribe', function(data) {
socket.json.emit('subscribed', {fps: fpsPi});
io.emit('setfps', {fps: fpsPi});
});
// disconnect on error. Browser will reconnect
socket.on('error', function() {
socket.disconnect();
});
// client disconnects
socket.on('disconnect', function() {
consolelog('Client disconnected.');
});
// save to RPi and browsers new fps
socket.on('setfps', function(fps){
fpsPi = fps;
consolelog('setfps ' + fpsPi);
io.emit('setfps', {fps: fpsPi});
});
});
Запуск работы
Запускаем скрипты следующим образом. На RaspberryPi — с правами рута:
sudo nodejs led.js
, а на сервере — просто добавляем в кронтаб * * * * * cd /var/www/apps; node server.js >> cron_rpi.log
, это не так красиво, зато всегда сервер будет запущен и можем о нём забыть. На странице своего сайта включаем код для слайдера jquery-ui и socket.io с нашего сервера. При получении сигнала от node.js-сервера слайдер выставляет текущее значение fps и наоборот — при передвижении слайдера мы на сервер отсылаем новое значение fps, которое сервер затем рассылает всем клиентам в браузеры и на Raspberry Pi.
Код, размещаемый на странице сайта
<script src="http://vpssite.domain:3141/socket.io/socket.io.js"></script>
<script>
function setSlided(val) {
if (val == 0) {
$('#freq').html('Выключен');
$('#freq2').hide();
}
else {
$('#freq').html(val);
$('#freq2').show();
}
}
$(function() {
// соединяемся с nodejs на сервере
var socket = io.connect('http://bk-it.ru:3141');
socket.emit('subscribe');
// при ответе сервера выставляем текущую fps
socket.on('subscribed', function(data) {
if (!data.error) {
setSlided(data.fps);
$("#loading").hide();
$("#slider").slider({
min: 0,
max: 20,
value: data.fps,
slide: function(event, ui) {
$("#slider").slider({ disabled: true });
socket.emit('setfps', ui.value);
//setSlided(ui.value);
}
});
}
});
socket.on('setfps', function(data) {
if (!data.error) {
setSlided(data.fps);
$("#slider").slider({value: data.fps});
$("#slider").slider({ disabled: false});
}
});
});
</script>
<h1>Светодиод, подключённый к интернету</h1>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script>
<div class="panel panel-info">
<div class="panel-heading">Управляйте светодиодом через сайт</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
<div style="height:40px;position:relative;top:12px;">
<div id="slider"><div id="loading" style="position:relative;top:-4px;">Соединяемся <img src="/img/loading.gif" alt=""></div></div>
</div>
</div>
<div class="col-md-6">
<div class="well-sm">Частота мерцания <b id="freq">Выключен</b> <span id="freq2" style="display:none;">раз/сек</span></div>
</div>
</div>
</div>
<div class="panel-footer">
Не так часто встречаете светодиод, подключённый к интернету?
</div>
</div>
Результаты работы
А вот и видео, описывающее, что получилось:
Вот, собственно, и всё, светодиод подключен к интернету. Теперь с любого устройства с интернетом мы можем управлять его мерцанием. Простор для дальнейшего творчества большой. Можно к выводам подключить модуль-реле и кнопкой на своём сайте включать и выключать любое оборудование. Модулей для Raspberry Pi продаётся очень много, поэтому полёт фантазии почти не ограничен, особенно если в наличии восторженный восьмилетний почитатель электроники.
Полезные ссылки, помогшие эксперименту
Документация Socket.io;
Документация Node.js;
Пакет rpi-gpio;
Документация на jquery-ui слайдер;
Распиновка GPIO на Raspberry Pi;
Модуль respawn для автоматического запуска nodejs-приложения (но я выбрал crontab).
Код можете взять из rpi-led на гитхабе.