这是SitePoint的IoT周! 我们整周都在发布有关互联网与物理世界交汇点的文章,因此请继续检查IoT标签以获取最新更新。
Tessel 2是关注JavaScript的微控制器,具有一系列预构建模块,您可以将其附加以扩展其功能。 在本文中,我们将探讨将GPS模块连接到Tessel 2时可以做什么。
如果您不熟悉Tessel 2的工作,那么我将在今年初介绍 Tessel 2 的入门基础 。 首先阅读一遍,以掌握在Wi-Fi上设置Tessel并向其推送代码的基础知识。 它还教您如何使Tessel上的LED闪烁得疯狂。 要知道非常有价值的技能!
连接GPS模块
要将GPS功能带到Tessel中,请将其连接到Tessel 2上的端口A上-这是最接近USB电源连接器的端口:
如上所示,您需要将其与大型笨重的矩形钻头和朝上的电气组件连接。 如果看一下引脚连接器,您会看到一个显示GND的引脚,该引脚应该与Tessel 2的端口A上的GND匹配。基本上,如果连接不正确,会有很多迹象表明!
启动我们的GPS Tessel应用程序
为您的Tessel应用程序创建一个名为“ gps”的文件夹(或您想要的任何名称)。 转到“终端/命令提示符”中的该文件夹,然后键入以下内容以初始化新项目:
t2 init
然后,在npm中运行以下命令以安装GPS模块:
npm install gps-a2235h
gps-a2235h
应该与您的GPS模块上的名称匹配(这一点很重要,以防将来的GPS模块稍有不同)。
如果发现错误消息,则如下所示:
> 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
我们的Tessel的JavaScript
我们的Tessel 2 JavaScript代码相对简单,如下所示:
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"),
然后,通过告诉我们Tessel的物理GPS模块位于哪个端口来设置GPS模块。我将我的端口放置在端口A中,该端口的定义如下:
gps = gpsLib.use(tessel.port["A"]),
为了在Tessel和服务器之间来回发送数据,我们将使用WebSockets。 由于Tessel 2运行JavaScript和npm模块这一奇妙的事实,我们可以在Tessel上运行常用的ws
WebSocket模块。 我们添加ws
模块并进行设置以监视我们的服务器位置。 我全部在本地运行,我的Mac运行的Node Server连接到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功能
遵循变量和模块声明之后,我们进入Tessel的实际功能,所有功能都集中在Tessel的gps-a2235h
模块提供的GPS功能上。
首先,我们设置要返回的GPS坐标的格式。您可以尝试多种不同的选项,包括'deg-min-sec'
, 'deg-dec'
, 'deg-min-dec'
和'utm'
。 对于我们的示例,我们将使用'deg-dec'
得出的度数如下所示: [ 31, 46, 5401.2, 'E' ]
。 要设置格式,我们使用以下内容:
gps.setCoordinateFormat({
'format': 'deg-dec'
});
为了对GPS数据通过时做出响应,我们需要首先等待从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) {
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.');
});
如果GPS信号由于任何原因丢失,则将触发'dropped'
事件。 我们这样记录:
gps.on('dropped', function(){
console.log('GPS signal dropped');
});
在'ready'
事件之外,如果GPS发生错误,则模块根本无法搜索卫星,我们使用'error'
事件检测到该'error'
:
gps.on('error', function(err){
console.log('GPS Error: ', err);
});
发送常规的WebSocket更新
我们设置了一个简单的间隔计时器,该间隔每10秒运行一次,而不是不断发送GPS信号(这可能有点太频繁和不必要了)。 一旦我们的WebSocket连接打开并准备就绪,它将开始:
ws.on('open', function() {
setInterval(function() {
// Our functionality will be in here
}, 10000);
});
在setInterval
,我们检查是否在latestCoords
存储了任何坐标。 如果是这样,我们尝试通过WebSocket连接发送那些。 将其放置在try / catch循环中,以避免在发生任何问题时使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);
}
}
我们的Node.js服务器
我们的Node.js服务器是典型的WebSocket服务器,它监视WebSocket消息,然后将这些消息广播到连接到WebSocket服务器的所有客户端。 这会将坐标从我们的Tessel广播到正在等待查找最新坐标的任何Web浏览器中:
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);
});
它还运行Express,这使我们可以通过它投放网页。 我们将静态Web内容添加到Node服务器定义的“ server”文件夹中的“ / public”文件夹中:
app.use(express.static(__dirname + '/public'));
在这里,我们将放置我们的前端代码以显示地图-但是,请务必注意,您可以在任何地方托管此内容。 我将其保留在同一服务器上,只是为了使本教程的所有内容尽可能独立。
添加谷歌地图
为了简单起见,我们的前端将全部放在一个public/index.html
文件中。 我不会介绍使用Google Maps API的绝对基础知识,因为我们已经在SitePoint上介绍了它,然后才以正确的方式利用Google Maps JavaScript API ,甚至还有一整套由Robert Dickerson撰写的在线课程,称为Google简介。 Maps API 。
如果您想继续学习并已经了解Google Maps的工作原理,请继续! 这是我们的基本HTML布局:
<!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>
在body标记的底部,我内联了我的JavaScript-您可以将其放在单独的文件中,也可以根据需要选择放置。 JavaScript开始如下:
var clientWebSocket = new WebSocket('ws://192.168.0.30:5000'),
map,
markers = [],
heatmap,
centered = false;
clientWebSocket
变量是我们存储连接到运行中的Node.js服务器的客户端WebSocket的位置。 map
将是我们的Google地图, markers
将是Tessel返回的坐标数组, heatmap
将是Google Map API热图并centered
仅跟踪地图是否以我们的位置为中心,而不是默认情况下提供的通用经/纬度。
一旦运行Google Maps回调函数,JavaScript中的其他所有内容都会初始化。 我将Google Maps API放入项目中,如下所示:
<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
数组,我们使用Google Maps API将其添加到热图(或将热图重置为更新的数组):
if (heatmap) heatmap.setMap(null);
heatmap = new google.maps.visualization.HeatmapLayer({
data: markers
});
heatmap.setMap(map);
您可能不需要将初始设置设置为null
位(每次更新都会导致闪烁),但是我在其中添加了此信息,以确保出于性能目的该映射是清晰的(不希望在一个位置添加多个数组)。我的GPS热图在运行了一段时间后最终变得非常大!)。 随时删除它,看看它对您的运行情况如何。 我可能最终会在我自己的版本上删除它。
应对任何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
如果我们通过访问http://localhost:5000
来使用Google Maps加载前端Web界面,我们应该会看到一张Google Map,其中包含找到GPS区域的热图。 我在去悉尼中央商务区的火车上跑了,看起来像这样:
结论
这结束了一个相当有趣的项目,即使用Tessel 2和GPS模块提取GPS数据。 使用热图实际上使您可以看到GPS跟踪变得越来越准确,这让我着迷。 整天在家中运行GPS应用程序,首先要跟踪我几扇门,但是随着时间的流逝,我可以看到GPS热图逐渐越来越接近我的实际位置。 挺整洁的!
如果您有Tessel 2并用它构建了一些有趣的东西,我很想听听您的构建! 在下面的评论中让我知道,或者在Twitter上通过@thatpatrickguy与我联系 。
From: https://www.sitepoint.com/tracking-gps-data-with-the-tessel-2/