Summary of the links used in this document:
- Get started, fast
- Manual
- Note on WebSocket
- Demos
- Examples
- Case Study. Comparison with Node-RED
- Extract custom data
Scripts:
The scripts you will need to run the Multiplexer are tomux.sh
, and mux.sh
. You might need to tweak them to fit your context.
Some pre-built examples are given in the RESTNavServer
module, which is itself based on this Multiplexer.
Do also see the section Build, package, run, in this document.
Note: This project was tested and used at sea, in the real world.
The main
method is in nmea.mux.GenericNMEAMultiplexer
.
For the impatient: Get started, fast.
- At the center of the picture, we have the NMEA-Multiplexer
- This is also hosting an optional HTTP server, implementing REST and Web interfaces to the data.
- Then you have Consumers (aka channels), bringing in NMEA Data
- File channel (to replay logged data)
- Serial channel, to read a Serial port
- TCP, REST, MQTT, WebSockets, etc..., whatever can provide NMEA sentences
- etc...
- Then you possibly have Computers, calculating extra data, re-injected into the NMEA-multiplexer
- Current and True Wind calculated with GPS data (SOG, COG)
- Custom ones
- etc...
- Then you have Forwarders, spitting out NMEA data (and others, sometimes)
- File Forwarder, to log data
- Character-mode console
- REST Forwarder, to feed other servers
- TCP and others to feed other soft programs (like OpenCPN, SeaWi, etc)
- etc...
NMEA channels management, in and out.
This is - obviously - a software multiplexer (no hardware required), that can read data from multiple sources, compute extra data (like current) if needed, and broadcast them onto (possibly) several output destinations.
For example:
- Read one or more serial ports (GPS, boat data), write them into a log file
- Read a serial port, read a
BME280
sensor (air temperature, atmospheric pressure, relative humidity), and broadcast everything on a TCP port, forOpenCPN
. - Read a file of logged data, and send them over
TCP
toOpenCPN
, for replay. - etc...
- NMEA (National Marine Electronics Association) is one of the oldest IT standards, defining how sensor data should be conveyed.
- Another Good Resource, by the author of GPSd.
Note: here is an opened question:
Some software products are using more "modern" technologies to shape the data (like
GPSd
,SignalK
, ..., they use JSON over REST/HTTP), but what is the point?text/plain
has always been a supported mime-type, suitable for NMEA Sentences...The conveyed data are NMEA data, and to be able to communicate with other softs, their (proprietary?) format will eventually have to be converted back to NMEA... Here we chose not to convert anything. NMEA remains NMEA, which everyone understands. And everyone's happy.
NMEA Parsers are available in OpenSource, in several languages. In this project, you'll find at least one in Java, and for ES6. Plus one in Python (WiP), in the
Java-TCP-Python
module, calledNMEASerialTest.py
.This being said... You will see in this project that there is a data-cache that can be used, at least, in the case of the REST Server (also part of this project, and heavily used in the
RESTNavServer
). This cache can be pinged and used from REST requests; as such, it supports a JSON format..., the requirements sound a lot like the ones SignalK is addressing.The remaining point would be to agree on the JSON Schema to use, but there is no standard about that yet.
This NMEAMultiplexer will deal with NMEA Data, in input, as well as for output, in order to preserve - as much as possible -
compatibility with other programs. Everyone understands NMEA.
The "only" exception to this rule will be the structure of the data cache, which brings us back to the note above...
This NMEAMultiplexer can
- use many input protocols (File, Serial, TCP, UDP, WebSockets, Sensors, Computations, ...)
- produce many outputs (File, Serial, TCP, UDP, WebSockets...)
- and use a REST API on top of that.
At the heart of this lies a small http server (part of this project), designed to run on very small boards, like a Raspberry Pi Zero, and with possibly no Internet access.
Warning
⚠️ : It is not designed to scale as an enterprise server!
The operations on the Serial port(s) require libRxTx
. This is included in the gradle dependencies.
To be able to use it outside gradle, run (on Linux/Debian/Raspberry Pi):
sudo apt-get install librxtx-java
See how this is used and referred to in mux.sh
(the launching script).
For the impatient: go here to get started now. The others will keep reading.
- NMEA Strings Parser
- AIS Strings Parser (WiP)
- NMEA Strings generator
- Serial port Reader / Writer
- TCP Reader / Writer
- REST Reader / Writer
- UDP Reader / Writer
- WebSockets client (read/write)
- ... and more.
- A tiny (but amazing) HTTP REST server, for admin and external access (through REST services) purpose.
Javadoc can be generated by using
../../gradlew javadoc
The generated files will be in build/docs/javadoc
. Open the index.html
in your browser.
At the center of the picture, there is the Multiplexer (aka MUX).
The MUX reads from channels
and writes to forwarders
.
A channel is an NMEA data provider, a forwarder is an NMEA data producer, it can be used as input from another Multiplexer.
Just to insist: A channel is an NMEA data provider. This means that it produces (pure) NMEA Sentences!! This is pure NMEA. Nothing fancy like a JSON Object or whatever object representing the same data in another format. NMEA is already a well known and defined format. |
In addition, we can have sensors. A sensor is reading data from a transducer, and produces NMEA sentences read by the Mux. In other words, a sensor is talking to the Multiplexer, and can be seen as a channel.
Also, a computer is using NMEA data collected by the Multiplexer to produce other NMEA data that will be broadcasted by the forwarders. For example, True Wind computed with Apparent Wind data and the GPS data.
Note: to compute the required data, we have a cache, where the data required by the computers are pushed. This cache is initialized before starting the computers, with parameters contained in the properties file used at startup.
This cache is necessary to perform damping and smoothing operations - among others.
Finally, we have transformers, that transform NMEA data into another (proprietary) format, and then behave like a a regular forwarder to provide them to whoever is interested.
A transformer is also a forwarder. See below examples of transformers
.
Channels (aka Consumers):
- Serial reads NMEA data from a Serial Port
- TCP reads NMEA data from a TCP server
- WebSocket reads NMEA data from a WebSocket server (this is a WebSocket client)
- File reads NMEA data from a log file
- etc
Forwarders:
- Serial writes NMEA data to a Serial Port (not implemented yet)
- TCP writes NMEA data to a TCP port
- WebSocket writes NMEA data to a WebSocket server (this is also a WebSocket client)
- File write NMEA data to a log file
- Small Screens, oled, eInk, etc (WiP)
- etc
Sensors:
- BME280 reads raw data from a BME280 sensor (Temperature, Pressure, Humidity), and produces
XDR
andMDA
NMEA Sentences. - BMP180 reads raw data from a BMP180 sensor (Temperature, Pressure), and produces
XDR
andMDA
NMEA Sentences. - HTU21D-F reads raw data from a HTU21D-F sensor (Temperature, Humidity), and produces
XDR
NMEA Sentences. - LSM303 reads raw data from a LSM303 sensor (3D magnetometer and accelerometer), and produces
XDR
NMEA Sentences for pitch and roll,HDM
for heading. - HMC5883L reads raw data from a HMC5883L sensor (3D magnetometer), and produces
XDR
NMEA Sentences for pitch and roll,HDM
for heading. - ... and the list is not closed.
Note about Sensors: As opposed to what it used to be in the previous version, we kept the code that reads the sensors' data in Python. The values will be reached through the
TCP
channel. This was done to avoid dependencies on Java frameworks likePI4J
ordiozero
. We've experienced some frustration recently, when PI4J-v1 was deprecated (after WiringPi's deprecation). Its V2 - anddiozero
as well) have restrictions on the Java SDK. It requires JDK 11, that cannot run on a Raspberry Pi Zero. This may be fixed later, but leaving the sensor code in Python (usually written by the sensors' providers) cuts us some slack, as those already working drivers do not need to be re-written in Java. This presented some redundant aspect...
Computers:
- True Wind computer (produces
MDA
,MWD
data) - Current computer (produces
VDR
data).
Also look into nmea.computers.ExtraDataComputer
, instantiated when tw-current
is mentioned in the computers
list of the mux definition.
Important: Computers require the cache to be initialized. This is set in the properties file:
init.cache=true
Transformers:
A Transformer
is specific kind of Forwarder
.
- GPSD data, like
nmea.forwarders.GPSdServer
(See this) - Custom data (like
nmea.forwarders.CharacterConsoleWriter
)
A basic approach to compute the current would be to do it by instant triangulation, figuring the Course Made Good (CMG) and comparing it with the GPS Data (Course and Speed Over Ground). A better approach turned out to compute the current over a given period of time. For example, you can perform this calculation by comparing the position you should be at with the CMG only (i.e. as if there was no current) and the one given by the GPS, over periods like 30 seconds, 1 minute, 10 minutes, etc, using a smoothing of the Boat Speed (BSP) and the CMG. The cache is designed to manage several such computations in parallel, they are discriminated by the length of their time-buffer (30 seconds, 5 minutes, etc). The accuracy of such a computations is much higher than the instant triangulation. See this article for details.
Note: There is no Transformer on the picture above
There is an rmi forwarder. This is a work in progress, but it works.
It is feeding an RMI server that can then be accessed by an RMI client.
See an example of such a client in samples.rmi.client.SampleRMIClient
.
See the class nmea.mux.GenericNMEAMultiplexer
, it uses the file nmea.mux.properties
to define what to read, and what to re-broadcast it to.
See it to understand its content (should be clear enough).
The properties file used by the nmea.mux.GenericNMEAMultiplexer
can be overridden by the System property named mux.properties
, like in
-Dmux.properties=nmea.mux.gps.log.small.properties
Those settings can be modified once the mux is started, through the REST API.
To compile and build:
$> ../../gradlew shadowJar
To run it, modify mux.sh
to fit your environment, and run
$> ./mux.sh
The script above can take the name of the properties
(or yaml
) file as a parameter,
like in $> ./mux.sh nmea.mux.gps.log.properties
. The default name for the
configuration file is nmea.mux.properties
, as seen in nmea.mux.GenericNMEAMultiplexer.java
, where it is the default value for the
system variable named mux.properties
.
See the Manual for more technical details.
The build is done as said above, with a
$> ../../gradlew shadowJar
This produces a fat jar (in the build/libs
folder), that can be used to run the Multiplexer.
In the modules implementing the NMEA-multiplexer, you can also package for production, using the script to.prod.sh
from a terminal (you will be prompted for input).
This will produce a tar.gz
file, containing everything needed to run smoothly (jar-files, scripts, sample config files).
This archive can be exported to wherever it is needed, and it will not require any source file, nor git repository.
To start the Multiplexer, you need to eventually run the script mux.sh
. This script will
refer to the right jar-file, and use the right java command to start the Multiplexer. It can also take the
name of the properties
(or yaml
) file as a parameter. The script to.mux.sh
can help you as well, as it can take
care of some cleanup before running mux.sh
. Those two scripts can be run in batch mode,
like with nohup ./mux.sh &
. If you do so, then you will need to kill
the Multiplexer process to stop it. This can be achieved by running killmx.sh
.
Note: During the packaging step above (
to.prod.sh
), the script is also archiving some web resources. The Multiplexer this page is about can be exposed through a small REST/HTTP server.
This way to expose the Multiplexer's features is indeed part of the Multiplexer, hence those Web examples. But those pages do not mean to be seen as anything but examples !!
The Channels - aka Consumers - support sentence filtering. Filtering can be applied on NMEA Device ID, and on NMEA Sentence ID. Filters can be positive (inclusive) or negative (exclusive).
Positive filters are linked with an or, Negative ones with an and.
A (sentence) filter like "HDM", "GLL", "~RMC", "~XDR"
would mean
(HDM or GLL) and (not RMC and not XDR)
Note: the filter above is meaningless, this is just an example. If the sentence has to start with
HDM
orGLL
, there is no point in excludingRMC
orXDR
... 🙄. They are already implicitly excluded.
"HDM", "GLL"
would mean "Only HDM or GLL""~RMC", "~XDR"
would mean "Everything, but RMC and XDR"
It is the user's responsibility not to have contradiction in the filters, like [ "GLL", "~GLL" ]
,
no verification is done in this area. Such a filter would just return nothing.
Note: This is just providing the possibility to negate an expression. Convenient, but limited. The best would probably be to use regular expressions (RegExp). Big drawback though: for the majority of the users, the RegExp syntax could be complex, too complex, or even scary...
There is an example of a transformer
in WebSocketProcessor.java
. As you would see, it is just implementing the Forwarder
interface,
and this is where it fits in the picture above.
A Transformer
is just reworking the data before forwarding them as a regular forwarder
would.
The example in WebSocketProcessor.java
is transforming the NMEA Data in the format expected by a Pebble (this is a smart watch) application.
See it here. Data are expected as a json
object, over WebSocket.
The expected data look like:
{
"gpstime": 1290377346000,
"gpsdatetime": 1290377346000,
"wp": "RANGI ",
"d2wp": 561.6,
"b2wp": 230,
"xte": 3.0,
"lat": -9.1102,
"lng": -140.21108333333333,
"gpssolardate": 1290343695340,
"log": 3013.0,
"daylog": 12.4,
"cog": 218,
"sog": 7.2,
"awa": -121,
"aws": 17.8,
"dbt": 1.7000000476837158,
"hdg": 220,
"bsp": 6.6,
"wtemp": 26.5,
"atemp": 0.0,
"D": 10.0,
"d": -0.9830777902388692,
"W": 9.01692220976113,
"leeway": 0.0,
"cmg": 229,
"tws": 21.4,
"twa": -139,
"twd": 89,
"cdr": 149,
"csp": 0.29,
"prmsl": 0.0,
"hum": 0.0
}
The transformer
reads the data from the cache and generates such an object. Then it is sent to a WebSocket server.
Start the websocket server, on a port of your choice:
$> node wsnmea.js -port:1234
Define your transformer in the properties
file:
forward.07.type=wsp
forward.07.wsuri=ws://localhost:1234/
Make sure you have configured the Pebble application as required (WebSocket URI), and you are good to go.
Application list
|
Press select to start
|
Scroll...
|
Choose...
|
Displayed!
|
Note: Pebble has been acquired by FitBit... There are other smart watch interfaces (like Samsung Frontier) available in the SmartWatches repo.
For more details and use-cases, see here.
WebSocket protocol is supported, in input, and in output.
If needed, you can start your own local WebSocket server, running on nodejs
.
To install it (once):
$> npm install
Then, to run it,
$> node wsnmea.js
or
$> npm start
There is a possibility to use Node-RED as a forwarder as well, that is a cool one. You can create a Node-RED flow that ingests data from a TCP port, and spits them out on a WebSocket one.
Here is the flow to import in Node-RED.
- Start the Mux (
$> ./mux.sh
)- Make sure there is a TCP Forwarder (port 7002)
- Start the node script
wsnmea.parser.js
.
node wsnmea.parser.js
- Start
Node-RED
and run the flow mentioned above.
- The Multiplexer reads the NMEA data and forwards them on a TCP Channel.
- Node-RED listens to the TCP port, and forwards the payloads to a WebSocket server
- The WebSocket server transforms the data it receives into the expected format, and broadcasts them to all the connected clients (Pebbles in this case).
Once everything runs, you can reach http://localhost:9876/data/web/wsconsole.html to see the data as they come through.
The properties files like nmea.mux.properties
defines the configuration at startup.
You can remotely manage the input channels and the re-broadcasting ones through a REST interface.
The soft includes a dedicated HTTP Server. The http port is driven by a property (in nmea.mux.properties
).
Same if you want the HTTP server to be started or not.
with.http.server=yes
http.port=9999
This HTTP Server is designed and written to run on small computers (like the Raspberry Pi Zero). It is NOT an enterprise server, and it will NOT scale as one. Think of it as a Micro server.
Examples of Web implementations (HTML, REST, etc) are gathered in another module, NMEA-multiplexer-basic.
A full list of the available REST services is available at
GET /oplist
All the end points and operations are defined in nmea.mux.GenericNMEAMultiplexer.java
. See the List<Operation>
named operations
.
GET /mux/serial-ports
returns a payload as:
[
"/dev/tty.Bluetooth-Incoming-Port",
"/dev/cu.Bluetooth-Incoming-Port"
]
The list of available serial ports.
GET /mux/channels
returns a payload like
[
{
"cls": "consumers.client.SerialClient",
"type": "serial",
"port": "/dev/ttyUSB0",
"br": 4800
},
{
"cls": "consumers.client.BME280Client",
"type": "bme280"
}
]
GET /mux/forwarders
returns a payload like
[
{
"cls": "forwarders.TCPWriter",
"port": 7001,
"type": "tcp"
},
{
"cls": "forwarders.ConsoleWriter",
"type": "console"
}
]
DELETE /mux/forwarders/{type}
type
is one of
file
. requires a body like
{
"log": "./data.nmea",
"type": "file"
}
identical to the elements returned by GET /mux/forwarders
.
console
. requires no body.tcp
. requires a body like
{
"port": 7002,
"type": "tcp"
}
identical to the elements returned by GET /mux/forwarders
.
ws
. requires a body like
{
"wsUri": "ws://localhost:9876/",
"type": "ws"
}
identical to the elements returned by GET /mux/forwarders
.
DELETE /mux/channels/{type}
POST /mux/forwarders
with payloads like:
file
. requires a body like
{
"log": "./data.nmea",
"type": "file"
}
identical to the elements returned by GET /mux/forwarders
.
console
. requires a body like
{
"type": "console"
}
tcp
. requires a body like
{
"port": 7002,
"type": "tcp"
}
identical to the elements returned by GET /mux/forwarders
.
ws
. requires a body like
{
"wsUri": "ws://localhost:9876/",
"type": "ws"
}
identical to the elements returned by GET /mux/forwarders
.
POST /mux/channels
There is a Web UI using the REST resources above, in raspberry-sailor/MUX-implementations/NMEA-multiplexer-basic
.
Note: This Web UI is to be considered as an example of the way to access the resources. Nothing more. Best case scenario, a Web-UI Developer might find it cute...
On the HTTP Port, use a url like http://machine-name:9999/web/admin.html
,
where machine-name
is the name of the machine where the multiplexer is running, and 9999
is the port defined in the properties.
And any REST client (Node.js, Postman, curl, your own code, ...) does the job.
Example with curl
:
$ curl -v http://192.168.1.181:9999/mux/last-sentence
* Trying 192.168.1.181...
* Connected to 192.168.1.181 (192.168.1.181) port 9999 (#0)
> GET /mux/last-sentence HTTP/1.1
> Host: 192.168.1.181:9999
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200
< Access-Control-Allow-Origin: *
< Content-Length: 110
< Content-Type: application/json
<
* Connection #0 to host 192.168.1.181 left intact
{
"last-data": "$GPGGA,171812.255,3718.7160,N,12142.3005,W,1,09,0.9,494.3,M,,,,0000*16",
"timestamp": 1499466116699
}
$
You can also visualize the REST traffic if needed; In (server to client)
on the left, Out (client to server)
on the right.
Click on the Flow value (top-right) to show/hide the graph.
Note: Don't be alarmed by the colors of the graph, they all rely on their own css
class, named .graphdisplay
.
The cool thing in this context is that whatever complex the rendering (what the user sees) looks like, the complexity belongs to the renderer (i.e. the client, the web browser in this case). The server is only responsible for providing the raw data the graph is based on; and typically here, providing the data is certainly not the most complex part, pinging the server does the job... As a matter of fact, a small board like a Raspberry Pi Zero can totally assume it, without noticing.
You have the possibility to dynamically load Channels, Forwarders and Computers.
To load a class, mention its name in the properties file used at startup, like for example:
#
# Dynamic loading sample
#
forward.03.class=nmea.forwarders.ProcessorSkeleton
#
This ProcessorSkeleton
is part of the project, it is provided as an example you can start from to develop your own forwarders.
Note: Dynamically loaded classes can also be managed from the REST admin interface. Use the
Custom
label when creating them.
They will show up in the admin interface, with their id in italic.
Notice the line that says skeleton
.
Among the forwarders available in this project some are to be dynamically loaded.
- SSD1306Processor
- MQTTPublisher (a cool one, for IoT)
- Character Console
- SQLite (log data in a SQL database)
- etc... list keeps growing.
Warning: for now, you cannot load more than one dynamically loaded forwarder, consumer or computer of the same class. They are identified by their class name, you cannot have more than one object
with a given class name in the lists. For example, if you have an MQTTPublisher
that uses a broker URL like tcp://192.168.1.136:1883
, you might very well want to
have another one, using a broker URL like tcp://io.adafruit.com:1883
. Currently, this is not possible.
This should not be too much of a problem though, specially if you use all this on a boat, you probably do not need in Internet connection. A small LAN would do the job in this case.
Whatever software understands NMEA is happy with all this. For example, OpenCPN:
In the screenshot above:
- The atmospheric pressure and air temperature come from a BME280 (~ $20)
- The True Wind is calculated by a
Computer
(as well as the current, not displayed here, but available) - Heel and Pitch come from an LSM303 (~ $15)
- Data are re-broadcasted on TCP
All the data can be logged, and replayed. Replayed data can be displayed just like above, in OpenCPN or any NMEA-savvy software. The screenshot above has been taken during one of those replays (that explains the disparity between air and water temperature...)
Some (good and open source) softwares
As you must have seen, we use Gradle
here, along with the ShadowJar
plugin. This plugin gathers all the dependencies, and puts them
all together in a single jar
file (named a fat-jar). This makes your life considerably easier,
just put the jar named build/libs/NMEA-multiplexer-1.0-all.jar
in your classpath (see for example in the mux.sh
), and you have everything you need in there.
This fat-jar
is currently (Apr-2017) a bit more than 7 Mb big. In some cases, you might want to trim the jar down, to make it smaller. If you do not need the classes that can be dynamically loaded,
if you are not interested in the I2C sensors, etc, you could very well prune those projects, the resulting jar
can be substantially smaller. To do so for yourself, refer to the Gradle documentation.
- UDP client
- Needs some cleanup...
Remote access is not a problem on any Raspberry Pi, ssh
does the trick. It can even be done from phone or other small devices. For example, several ssh
clients are available on Android, here is a screenshot from a phone:
In this kind of case, it could be a good idea to have scripts with small names... See go
and killmux
, for examples.
The Raspberry Pi can also be an hotspot, you connect to its network to be able to access the data. there is a good tutorial for that on the Adafruit website. This one also, is worth a look.
The definition of your network is in /etc/hostapd/hostapd.conf
.
scp
and other such tools are also conveniently available.
This can prove to be particularly convenient when you want to log data away from a stable Internet connection (in your car, in a plane, on a boat, etc). You start the Raspberry Pi, with a hotspot generating its own network. Then you can connect on that network, and you can drive the Multiplexer application (start, stop, monitor, etc).
Along the same lines - even if it can sound a bit disproportionate - VNC
works just fine, even on the Raspberry Pi Zero (see below)
This is Jessie/Pixel running on a Raspberry Pi Zero.
Instructions were moved here.
In some cases, you might want to start and stop the forwarders (doing logging for example) on demand. Like when you want to log data when driving, hiking, running, etc.
There is a possibility not to start the forwarders when the multiplexer is starting.
For that, set the system variable process.on.start
to false
, default value is true
.
In any case, the value can be set using the service
PUT /mux/mux-process/on
or
PUT /mux/mux-process/off
The current status can be read using
GET /mux/mux-process
A Web UI (using the above) is also available:
http://machine:9999/web/runner.html
Screenshots from a smart-phone:
Notice that this allows you to set the process.on.start
, but also to shutdown the Multiplexer.
Use it with caution.
Here is a use case:
You start from your home for a run, you want to log the data from a GPS. You start everything at home before you go, with
process.on.start=false
. All the stuff (Raspberry Pi Zero W, battery, GPS) is in a plastic box in your backpack, a Nalgene canteen, or something similar. You get out, and when you're about to start running, you connect to the Raspberry Pi from your cell phone, and from the UI above, you start the recording. Once done, you stop it the same way. The data have been collected only when you were running. Then you can even stop the Multiplexer, before going home to download and visualize your data file.
Follow this link.
They are here.
Also see a combination with the Project-Trunk:SunFlower
project. This takes the position from a GPS (serial port), and the device heading from an LSM303
.
Then it orients a solar panel so it faces the sun. The specific forwarder
that does the job is the
SunFlower project.
And there is an integration with the REST Nav Server.
- NMEA Multiplexer on a Raspberry Pi Zero W. Compared with Node-RED.
-
A Web UI to generate the
yaml
files defining the Multiplexer, just openmuxbuilder/text/mux-builder.html
in a browser, no HTTP server needed.- A Web GUI, Drag-n-Drop based, is also available, open
muxbuilder/dragndrop/mux-builder.html
in a browser.
Drag the Consumers from the left Edit each component's properties Same for Forwarders And Computers Edit general properties And you have your YAML - A Web GUI, Drag-n-Drop based, is also available, open
This yaml
is generated by the GUI above, it can be edited like any other yaml:
#
# Generated on Fri Apr 02 2021 06:57:24 GMT-0700 (Pacific Daylight Time)
#
name: "GUI Mux Builder"
context:
with.http.server: true
http.port: 8080
init.cache: true
default.declination: 14.0
deviation.file.name: dev.csv
max.leeway: 10.0
bsp.factor: 1.0
aws.factor: 1.0
hdg.offset: 0.0
awa.offset: 0.0
damping: 30
# 2 Channels
channels:
- type: serial
port: /dev/ttyS80
baudrate: 4800
verbose: false
reset.interval: 60000
- type: bme280
device.prefix: RP
verbose: false
# 2 Forwarders
forwarders:
- type: file
timebase.filename: true
filename.suffix: _LOG
log.dir: logged
split: day
flush: true
- type: tcp
port: 7001
# 1 Computer
computers:
- type: tw-current
prefix: CC
time.buffer.length: 30, 60, 600
Note: This does not work correctly on Safari, which does not support correctly the
<dialog>
element of HTML5.
Looks like Firefox also has issues...
Brave, Chromium, and Chrome work OK.
Several small utilities are available to do several operations on the data log files. You can
- merge several log files
- shrink (remove leading and trailing lines with no speed) log files
- turn a log-file (.nmea) into
- CSV
- GPX
- KML
- JSON
Note: scripts are available to invoke those utilities. See (for Linux-like systems):
log.analyzer.sh
log.merge.sh
log.shrinker.sh
log.to.csv.sh
log.to.gpx.sh
log.to.kml.sh
log.to.json.sh
- A sample of a log file analyzer is in
util.LogAnalyzer
:
$ java -cp ./build/libs/NMEA-multiplexer-1.0-all.jar util.LogAnalyzer ./sample.data/2017.06.17.nmea
Started 17-Jun-2017 09:11:01 PDT
Arrived 17-Jun-2017 11:42:37 PDT
9,097 record(s) out of 36,387. Total distance: 12.221 km, in 2 hour(s) 31 minute(s) 36.0 sec(s). Avg speed:4.837 km/h
Max Speed: 6.112 km/h
Top-Left :N 37°20.17' / W 121°43.62'
Bottom-Right:N 37°18.70' / W 121°41.46'
$
- A sample of a kml file generator is in
util.NMEAtoKML
:
$ java -cp ./build/libs/NMEA-multiplexer-1.0-all.jar util.NMEAtoKML sample.data/alcatraz.2018.may.5.nmea --title:Alcatraz --sub-title:"May 5, 2018"
Started 05-May-2018 10:32:23 PDT
Arrived 05-May-2018 15:52:31 PDT
38,426 record(s) out of 76,821. Total distance: 44.222 km, in 5 hour(s) 20 minute(s) 8.0 sec(s). Avg speed:8.288 km/h
Max Speed: 327.804 km/h
Min alt: -248.60 m, Max alt: 212.00 m, delta 460.60 m
Top-Left :N 37°49.84' / W 122°30.66'
Bottom-Right:N 37°44.91' / W 122°24.12'
Generated file sample.data/alcatraz.2018.may.5.nmea.kml is ready.
$
Then open the generated file in Google Map or Google Earth.
- The same feature is also available for GPX (for navigation software like OpenCPN), use
util.NMEAtoGPX
, from the scriptlog.to.gpx.sh
. - Idem for Comma Separated Values (CSV, spreadsheet compatible), use
util.NMEAtoCSV
, from the scriptlog.to.csv.sh
.
As an example, there is in the NMEA-mux-WebUI
module a script called to.prod.sh
that shows a way to
build the soft for distribution without the full git repository.
Just run
$ ./to.prod.sh
It will:
- Start a fresh gradle build
- Put all the required resources into a new directory (provided at runtime)
- Archive the directory into a
tar.gz
file - Drop the directory.
Then you can distribute the archive.
All the user has to do it to un-archive it and run the mux.sh
script.
See here
To read a Serial Port on Windows 10, with PowerShell:
Write-Host "Running PowerShell, reading Serial port"
[System.IO.Ports.SerialPort]::getportnames()
$port = new-Object System.IO.Ports.SerialPort COM1,4800,None,8,one
$port.open()
# $val = 0
# while ($val -ne 10) {
while ($true) {
# $val++
$port.ReadLine()
}
$port.close()
To authorize the execution of such a script:
Run once, as administrator:
dos> powershell
PS > get-executionpolicy
PS > set-executionpolicy unrestricted
PS > exit
dos>
To execute a script in PowerShell, with redirection:
dos> powershell ".\serial.ps1" > out.txt
See instructions for Windows 10 here