Это неделя Интернета вещей в SitePoint! Всю неделю мы публикуем статьи, ориентированные на пересечение интернета и физического мира, поэтому следите за последними обновлениями в теге IoT .
Tessel 2 — это ориентированный на JavaScript микроконтроллер, который имеет ряд предварительно собранных модулей, которые можно подключать для расширения его функциональности. В этой статье мы рассмотрим, что мы можем сделать при подключении модуля GPS к Tessel 2.
Если вы новичок в работе с Tessel 2, я рассмотрел основы начала работы с Tessel 2 в начале этого года. Прочтите это в первую очередь, чтобы получить представление об основах настройки Tessel на своем Wi-Fi и вставке кода в него. Он также учит вас, как заставить светодиоды на вашем Tessel мигать, как сумасшедшие. Очень ценные навыки, чтобы знать!
Подключение модуля GPS
Чтобы добавить некоторые функции GPS в ваш Tessel, подключите его к порту A на Tessel 2 — это ближайший к разъему питания USB:
Как вы можете видеть выше, вы захотите соединить его с большим громоздким прямоугольным битом и электрическими компонентами вверх. Если вы посмотрите на штыревые разъемы, вы увидите тот, который говорит GND — который должен совпадать с GND на порте A. Tessel 2. В основном, есть множество контрольных признаков, если вы подключаете его неправильно!
Запуск нашего приложения GPS Tessel
Создайте папку для своего приложения Tessel под названием «gps» (или любое другое имя, которое вы предпочитаете). Перейдите в эту папку в терминале / командной строке и введите следующую команду для инициализации нового проекта:
t2 init
Затем выполните следующую команду в npm, чтобы установить модуль GPS:
npm install gps-a2235h
gps-a2235h
Если вы обнаружите, что получаете сообщение об ошибке, подобное этому:
> cd examples ; pakmanager build || echo 'Could not build pakmanager package. Please make sure pakmanager is globally installed'
sh: pakmanager: command not found
Could not build pakmanager package. Please make sure pakmanager is globally installed
Сначала вы захотите установить это глобально, вот так (а затем снова попытаться установить модуль gps):
npm install pakmanager -g
JavaScript нашего Тесселя
Наш JavaScript-код Tessel 2 относительно прост и выглядит так:
var tessel = require("tessel"),
gpsLib = require("gps-a2235h"),
gps = gpsLib.use(tessel.port["A"]),
WebSocket = require('ws'),
ws = new WebSocket('ws://192.168.0.30:5000'),
latestCoords;
gps.setCoordinateFormat({
'format': 'deg-dec'
});
gps.on('ready', function() {
console.log('GPS module now searching for satellites...');
gps.on('coordinates', function(coords) {
console.log('Lat:', coords.lat, '\tLon:', coords.lon, '\tTimestamp:', coords.timestamp);
latestCoords = coords.lat + ',' + coords.lon;
});
gps.on('fix', function(data) {
console.log(data.numSat, 'fixed.');
});
gps.on('dropped', function(){
console.log('GPS signal dropped');
});
});
gps.on('error', function(err){
console.log('GPS Error: ', err);
});
ws.on('open', function() {
setInterval(function() {
if (latestCoords !== undefined) {
console.log('Trying to send coords of ' + latestCoords);
try {
ws.send(latestCoords, function ack(error) {
console.log('Error detected while sending: ' + error);
});
} catch (e) {
console.log('Error caught while sending: ' + error);
}
} else {
console.log('No coords coming through');
}
}, 10000);
});
Давайте рассмотрим, что на самом деле здесь происходит. Мы начинаем с требования модуля Tessel и нашего модуля GPS:
var tessel = require("tessel"),
gpsLib = require("gps-a2235h"),
Затем мы настраиваем модуль GPS, сообщая ему, в каком порту находится физический модуль GPS нашего Тесселя. Я поместил свой порт в порт A, который я определил следующим образом:
gps = gpsLib.use(tessel.port["A"]),
Для передачи данных между нашим Tessel и нашим сервером мы будем использовать WebSockets. В связи с тем, что в Tessel 2 работают модули JavaScript и npm, мы можем запустить на Tessel часто используемый модуль ws
Мы добавляем модуль ws
Я запустил все это локально: мой Mac работал на сервере Node, подключенном к маршрутизатору 4G, и мой Tessel также подключился к тому же маршрутизатору 4G. Это позволило мне напрямую использовать IP-адрес для ссылки на сервер.
WebSocket = require('ws'),
ws = new WebSocket('ws://192.168.0.30:5000'),
Если вы хотите, чтобы это выполнялось через Интернет, вы можете разместить его на общедоступном сервере и изменить настройку WebSocket на:
ws = new WebSocket('ws://www.myfancynodeserver.com'),
Наконец, мы устанавливаем переменную с именем latestCoords
GPS-функции Tessel
Следуя нашим объявлениям переменных и модулей, мы переходим к фактической функциональности нашего Tessel, которая сосредоточена на функциях GPS, предоставляемых модулем gps-a2235h
Для начала, мы устанавливаем формат для наших координат GPS, которые будут возвращаться. Есть ряд различных опций, которые вы можете попробовать, в том числе 'deg-min-sec'
'deg-dec'
'deg-min-dec'
'utm'
В нашем примере мы будем использовать 'deg-dec'
[ 31, 46, 5401.2, 'E' ]
Чтобы установить формат, мы используем следующее:
gps.setCoordinateFormat({
'format': 'deg-dec'
});
Чтобы реагировать на данные GPS, когда они поступают, нам нужно сначала подождать, чтобы получить событие "ready"
Как и многие другие JavaScript-фреймворки, мы используем для этого функцию on()
Все наше обнаружение событий GPS происходит в пределах этого:
gps.on('ready', function() {
console.log('GPS module now searching for satellites...');
// Further functionality will be here.
});
Самым полезным из событий GPS, за которыми мы будем следить, является событие 'coordinates'
Когда происходит это событие, наш модуль GPS возвратил серию координат своего местоположения. В нашем примере он предоставляет их в переменной с именем coords
coords.lon
Мы объединяем оба этих значения в строку и сохраняем их внутри coords.lat
latestCoords
Еще одно событие, за которым вы можете наблюдать, это событие gps.on('coordinates', function(coords) {
Это возвращает количество спутников GPS, которые наш модуль смог зафиксировать для определения местоположения. В моей демонстрации, как правило, пять или шесть в Сиднее, так что вы можете использовать это в качестве основы для того, каким будет обычное число. Я регистрирую эти значения, когда они приходят с помощью:
console.log('Lat:', coords.lat, '\tLon:', coords.lon, '\tTimestamp:', coords.timestamp);
latestCoords = coords.lat + ',' + coords.lon;
});
'fix'
Если сигнал GPS будет потерян по какой-либо причине, сработает событие gps.on('fix', function(data) {
Мы записываем это так:
console.log(data.numSat, 'fixed.');
});
'dropped'
Вне события gps.on('dropped', function(){
console.log('GPS signal dropped');
});'ready'
'error'
Отправка регулярных обновлений WebSocket
Вместо постоянной отправки сигналов GPS, что может быть слишком частым и ненужным, мы настроили простой интервальный таймер, который запускается каждые 10 секунд. Это начинается, когда наше соединение WebSocket открыто и готово к работе:
gps.on('error', function(err){
console.log('GPS Error: ', err);
});
В нашем ws.on('open', function() {
setInterval(function() {
// Our functionality will be in here
}, 10000);
});setInterval
Если это так, мы пытаемся отправить их через наше соединение WebSocket. Это помещено в цикл try / catch, чтобы избежать сбоя нашего Tessel, если что-то пойдет не так:
latestCoords
Наш сервер Node.js
Наш сервер Node.js является типичным сервером WebSocket, который отслеживает сообщения WebSocket, а затем передает эти сообщения всем клиентам, подключенным к серверу WebSocket. Это передаст координаты от нашего Tessel на любой веб-браузер, который ждет, чтобы узнать последние координаты:
if (latestCoords !== undefined) {
console.log('Trying to send coords of ' + latestCoords);
try {
ws.send(latestCoords, function ack(error) {
console.log('Error detected while sending: ' + error);
});
} catch (e) {
console.log('Error caught while sending: ' + error);
}
}
Он также работает с Express, что позволяет нам обслуживать веб-страницы через него. Мы добавляем наш статический веб-контент в папку «/ public» в нашей папке «server», как определено нашим Node-сервером:
var http = require('http'),
url = require('url'),
express = require('express'),
app = express(),
bodyParser = require('body-parser'),
server = require('http').Server(app),
WebSocketServer = require('ws').Server,
wss = new WebSocketServer({server: server}),
port = process.env.PORT || 5000,
latestCoords;
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
if (message) {
latestCoords = message;
broadcast(latestCoords);
}
});
});
function broadcast(message) {
if (message) {
wss.clients.forEach(function each(client) {
client.send(message);
});
}
}
server.listen(port, function() {
console.log('Listening on ' + port);
});
Здесь мы разместим наш код переднего плана для отображения карты — однако важно отметить, что вы можете разместить этот контент абсолютно где угодно. Я держал его на том же сервере, чтобы в этом уроке все было максимально автономно.
Добавление карт Google
Наш интерфейс будет все в одном файле app.use(express.static(__dirname + '/public'));
Я не буду рассказывать об основах использования API Карт Google, так как мы уже рассказывали об этом здесь, в SitePoint, о том, как правильно использовать API JavaScript Карт Google, и даже проведем целый онлайн-курс Роберта Дикерсона под названием « Введение в Google». API Карт .
Если вы хотите следовать и уже знаете, как работает Google Maps, продолжайте! Вот наш основной макет HTML:
public/index.html
Внизу тега body я указал свой JavaScript — вы можете поместить его в отдельный файл или по своему усмотрению. JavaScript начинается так:
<!DOCTYPE html>
<html>
<head>
<title>MAPS!</title>
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
}
#map {
height: 100%;
}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>
Переменная var clientWebSocket = new WebSocket('ws://192.168.0.30:5000'),
map,
markers = [],
heatmap,
centered = false;clientWebSocket
map
markers
heatmap
centered
Все остальное в нашем JavaScript инициализируется после запуска функции обратного вызова Google Maps. Я добавил API Карт Google в свой проект так:
<script src="https://maps.googleapis.com/maps/api/js?key=YOURKEY&libraries=visualization&callback=initMap"
async defer></script>
Затем все выполняется внутри функции initMap()
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: -34.397, lng: 150.644},
zoom: 12
});
// The rest of our WebSocket functionality will be here
}
После этого мы настраиваем проверку любых сообщений WebSocket. Если мы получим их, мы отфильтруем их в формат {lat: -34.397, lng: 150.644}
clientWebSocket.onmessage = function(e) {
var latLngRaw = e.data.replace(/ /g, ''),
latLngSplit = latLngRaw.split(','),
lat = latLngSplit[0] * (latLngSplit[1] === 'S' ? -1 : 1),
lng = latLngSplit[2] * (latLngSplit[3] === 'W' ? -1 : 1),
pos = {lat: lat, lng: lng};
console.log(pos);
// Google Map marker functionality will go here
}
После этого мы добавляем его в наш массив markers
Если у нас есть значения широты и долготы, то мы готовы сделать это. Мы также центрируем карту в этом начальном местоположении:
if (!isNaN(pos.lat) && !isNaN(pos.lng)) {
marker = new google.maps.LatLng(lat, lng);
markers.push(marker);
if (!centered) {
map.setCenter(marker);
centered = true;
}
}
// Heatmap functionality will go here
Наконец, с нашим обновленным массивом markers
if (heatmap) heatmap.setMap(null);
heatmap = new google.maps.visualization.HeatmapLayer({
data: markers
});
heatmap.setMap(map);
Возможно, вам не нужно делать начальную настройку на null
Не стесняйтесь удалить его и посмотрите, насколько хорошо он работает для вас. Я мог бы закончить тем, что удалил это на своей собственной версии слишком позже.
Хорошей практикой также является способ реагирования на любые ошибки WebSocket:
clientWebSocket.onerror = function(error) {
console.log('Error with WebSocket: ' + error);
};
В бою
Если мы сначала запустим наш сервер, запустив:
node index.js
Затем запустите наш код Tessel GPS, выполнив:
t2 run index.js
Изначально на терминале для приложения Tessel мы увидим:
0 'fixed.'
0 'fixed.'
0 'fixed.'
0 'fixed.'
0 'fixed.'
Это показывает, что спутники пока не найдены. Постарайтесь, чтобы он был на линии прямой видимости с небом — это увеличит ваши шансы! Как только он найдет несколько спутников, вы увидите:
3 'fixed.'
Lat: [ 33.8666, 'S' ] Lon: [ 151.08533333333332, 'E' ] Timestamp: 75903.769
Lat: [ 33.8666, 'S' ] Lon: [ 151.08533333333332, 'E' ] Timestamp: 75903.769
3 'fixed.'
Lat: [ 33.866595, 'S' ] Lon: [ 151.085355, 'E' ] Timestamp: 75904.765
Lat: [ 33.866595, 'S' ] Lon: [ 151.085355, 'E' ] Timestamp: 75904.765
На сервере Node.js, как только начнут поступать координаты, в терминале вы увидите следующее:
received: 34.27340792375617,S,146.02321379585192,E
received: 33.786892811069265,S,147.00557255884632,E
received: 32.00388987502083,S,145.91804205672815,E
received: 34.48931397567503,S,148.91048887046054,E
received: 34.59769207518548,S,145.09519725223072,E
received: 33.53758704382926,S,145.1981749490369,E
received: 33.66241379012354,S,149.52391665312462,E
Если мы загрузим наш интерфейсный веб-интерфейс с помощью Карт Google, перейдя по http://localhost:5000
Я управлял этим, когда ехал на поезде в КБР Сиднея, и это выглядело так:
Вывод
На этом завершается довольно увлекательный проект по извлечению данных GPS с использованием модуля Tessel 2 и GPS. Использование тепловой карты фактически позволяет вам видеть GPS-отслеживание все более и более точным, что мне показалось увлекательным. Запуская приложение GPS в течение дня из дома, оно началось с отслеживания нескольких дверей от меня, но затем я увидел, что тепловая карта GPS постепенно приближалась к моему фактическому местоположению с течением дня. Довольно аккуратно!
Если у вас есть Tessel 2 и вы создали что-то интересное, я хотел бы услышать, что вы создали! Дайте мне знать в комментариях ниже или свяжитесь со мной в Твиттере по адресу @thatpatrickguy .