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

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

На сервере и «малинке» должен стоять node.js и npm (node package manager). Устанавливаем по данной инструкции [2].
Для того, чтобы node.js смог работать с GPIO, требуется установить модуль rpi-gpio. А для соединения с сервером RPi потребуется socket.io-client. Устанавливаются пакеты командой sudo npm install rpi-gpio и sudo npm install socket.io-client.
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.
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>
А вот и видео, описывающее, что получилось:
Вот, собственно, и всё, светодиод подключен к интернету. Теперь с любого устройства с интернетом мы можем управлять его мерцанием. Простор для дальнейшего творчества большой. Можно к выводам подключить модуль-реле [3] и кнопкой на своём сайте включать и выключать любое оборудование. Модулей для Raspberry Pi продаётся очень много, поэтому полёт фантазии почти не ограничен, особенно если в наличии восторженный восьмилетний почитатель электроники.
Документация Socket.io [4];
Документация Node.js [5];
Пакет rpi-gpio [6];
Документация на jquery-ui слайдер [7];
Распиновка GPIO на Raspberry Pi [8];
Модуль respawn для автоматического запуска nodejs-приложения (но я выбрал crontab) [9].
Код можете взять из rpi-led [10] на гитхабе.
Автор: shukshinivan
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/raspberry-pi/73637
Ссылки в тексте:
[1] vps: https://www.reg.ru/?rlink=reflink-717
[2] по данной инструкции: https://github.com/joyent/node/wiki/backports.debian.org
[3] модуль-реле: https://www.modmypi.com/shop/nwazet-pecan-pi-relay-kit
[4] Документация Socket.io: http://socket.io/docs/
[5] Документация Node.js: http://nodejs.org/api/
[6] Пакет rpi-gpio: https://www.npmjs.org/package/rpi-gpio
[7] Документация на jquery-ui слайдер: http://api.jqueryui.com/slider/
[8] Распиновка GPIO на Raspberry Pi: https://www.modmypi.com/image/data/tutorials/gpio-en-francais/le-raspberry-pi-3.jpg
[9] Модуль respawn для автоматического запуска nodejs-приложения (но я выбрал crontab): https://github.com/mafintosh/respawn
[10] rpi-led: https://github.com/shukshin-ivan/rpi-led
[11] Источник: http://habrahabr.ru/post/242409/
Нажмите здесь для печати.