В этом разделе мы подключим приемник GPS к серверу jCjS. Это устройство доступно и широко распространено, и поэтому оно было выбрано для начала описания концепций взаимодействия jCjS c реальным оборудованием. Данный материал относится к операционной системе Linux, реализация этого приложения jCjS в Windows не должно составлять проблемы.

Подключение устройства в терминале Linux

...

Транслируем строки NMEA через интернет

Мы увидели строки вываливающиеся из приемника GPS как из рога изобилия, которые содержат информацию о положении, скорости, направления (курса), точного времени, количества и положения спутников. Стоит отдать должное разработчикам приемников GPS, которые выбрали такой простой текстовый формат данных NMEA, так как он понятен человеку, у которого в длинном путешествии может слететь все сложное лицензионное программное обеспечение (так как закончился ключ лицензии :) и остался один терминал, и он тем самым, поставлен на грань выживания. А мы сейчас устроим трансляцию последней полученной строки NMEA в интернет с помощью jCjS.

Начнем с файла инициализации.

var ansDev = 0;
post.serial = new SerialPort();
if(!post.serial.open('/dev/rfcomm0')) {
   post.log('ошибка открытия порта /dev/rfcomm0', -1);
   ansDev = -1;
}
post.log('порт /dev/rfcomm0 открыт', 1);

var ansCnt = 0;
post.serial.readyRead.connect(readyRead);
function readyRead() {
   while(post.serial.canReadLine()) {
      var str = post.serial.readLine();
      if(str.slice(0, 6) != '$GPRMC') { continue; }
      ansDev = str;
      if(ansCnt < 10) {
          post.log(ansDev, 1);
       }
       ansCnt++;
   }
}

В этом скрипте мы видим две новых функции. Первая - это функция встроенного глобального конструктора new SerialPort(), по синтаксису и применению она очень похожа на функцию создания таймера new Timer(). В строке 3 мы открываем наш виртуальный порт /dev/rfcomm0 и выдаем лог, через также встроенную в post функцию log(). Первый аргумент log() - текст сообщения, второй аргумент уровень важности лога. Если он выше или равен текущего установленного порога важности логов, а он у нас по умолчанию равен 1 (см. лог запуска сервера 2013-06-29-10:48:53.858 v0 obj=server jcjshttpserver.cpp:340 init() порог логирования 1). Если уровень важности лога отрицателен, то он всегда выдается и означает ошибку.

Мы используем виртуальный последовательный порт и его параметры: скорость, количество бит, проверка четности - не используются, точнее они не влияют на работу Bluetooth порта. Счастливые обладатели GPS приемника работающего по "настоящему" последовательному порту могут не мучится настройкой Bluetooth, но им будет необходимо выставить параметры порта до (или после его) успешного открытия, примерно так:

post.serial.baudRate = 9600;
post.serial.parity = 0;
post.serial.stopBits = 2;
post.serial.dataBits = 8;

Подробное описание свойств и функций класса последовательного порта смотрим в ...

При поступлении новых данных в буфер объекта последовательного порта он генерирует сигнал readyRead(), который мы перехватываем в нативной функции JavaScript readyRead(). В ней мы проверяем, что поступила целая строка (или пакет строк), далее мы изымаем данные построчно в цикле while с помощью функций объекта последовательного порта canReadLine() и readLine(). Также мы выдаем 10 прочитанных строк в лог, уведомляя журнал, что процесс чтения данных NMEA GPS приемника запущен нормально. Строка 14 фильтрует строки с записью GPRMC, так как только этот тип строк содержит информацию о местоположении и времени.

Пока совершенно тривиальный командный скрипт:

http.respPlainText(ansDev);

Все, первый результат достигнут. С помощью открыто распространяемого jCjS и пары скриптов за Вашим путешествием будет следить весь мир, и не оставит в трудный час стихийных бедствий. Ну это, конечно, если у Вас имеется спутниковый канал интернета.

$GPRMC,092618.000,A,5505.3114,N,03847.1453,E,0.13,131.12,290613,,*03

Сообщаем географические координаты: 55° 5 минут северной широты; 38° 47 минут восточной долготы, время по Гринвичу: 9 часов 26 минут 18 секунд. Полет нормальный.

Парсин строк NMEA

Создадим файл создания объекта парсинга строк NMEA nmea.js с таким содержанием и согласно стандарту NMEA:

NmeaParser = function() {}
NmeaParser.prototype.time = new Date();
NmeaParser.prototype.lat = 45;
NmeaParser.prototype.lng = 0;

NmeaParser.prototype.setNmeaStr = function(str) {
    if(str.slice(0, 6) != '$GPRMC') { return; }
    var listData = str.split(",");

    //устанавливаем текущее время
    this.time.setHours(listData[1].slice(0, 2));
    this.time.setMinutes(listData[1].slice(2, 4));
    this.time.setSeconds(listData[1].slice(4, 6));

   //широта
   var latGrad = listData[3].slice(0, 2);
   var latMin = listData[3].slice(2);
   var latSign = listData[4] == "N" ? +1 : -1;
   this.lat = latSign * (latGrad + latMin / 60);

    //долгота
    var lngGrad = listData[5].slice(0, 3);
   var lngMin = listData[5].slice(3);
   var lngSign = listData[6] == "E" ? +1 : -1;
   this.lng = lngSign * (lngGrad + lngMin / 60);
}

Нам пока не нужны все параметры - только широта, долгота и время. Впоследствии этот скрипт будет дополнен. Также видоизменим файл инициализации так, чтобы полученная строка от приемника передавалась объекту nmea, а командный скрипт выдавал распарсенную строку в виде литерала объекта. Также в командный скрипт введем ведение файла "бортового журнала" в виде текстового файла, а для этого создадим объект поста файл.

Отображаем координаты на карте

http://ru.wikipedia.org/wiki/NMEA
http://habrahabr.ru/post/110460/
https://developers.google.com/maps/documentation/javascript/reference?hl=ru
https://developers.google.com/maps/documentation/javascript/?hl=ru

Далее