From a6cdb6ce4b9ef37da5d30b4cbe63680b1b59d644 Mon Sep 17 00:00:00 2001 From: Tony Bentley Date: Tue, 2 Jan 2024 17:42:44 -0800 Subject: [PATCH] feat: Adding nmea 0183 parser and instructions --- README.md | 12 ++++++--- package-lock.json | 9 +++++++ package.json | 1 + src/App.tsx | 65 ++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 0dda145..f83bed4 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,14 @@ # signalk-multiplex-viewer A plugin for tracing NMEA 0183 and 2000 multiplexed events from Signalk server -- Select from one or more event emitters -- Choose from a list of associated events -- Filter and search for targeted NMEA sentences/pgns -- Find duplicates or missing values and validate that Signalk is providing the correct values for your NMEA connections +### Instructions +- Check the Emitters associated with the NMEA data source +- Check the Events associated with the NMEA data source +- Supported NMEA 0183 sentences will display in the Capture Window: APB, BWC, DBT, DTM, GGA, GLL, GNS, GSA, GST, GSV, HDG, HDM, HDT, MTK, MWV, RDID, RMC, VHW, VTG, ZDA +- All Signalk converted NMEA 2000 PGNs will display in the Capture Window +- Cick a row to inspect the formatted data in the Capture Window +- Use the filters to reduce the rows to match specific criteria +- You can export the rows into a CSV file NOTE: Depends on signalk-server branch [ws-events](https://github.com/SignalK/signalk-server/tree/ws-events) until merged. diff --git a/package-lock.json b/package-lock.json index f2c647a..9061458 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@types/node": "^16.18.68", "@types/react": "^18.2.45", "@types/react-dom": "^18.2.18", + "nmea-simple": "^3.3.0", "react": "^18.2.0", "react-dom": "^18.2.0", "styled-components": "^6.1.3", @@ -15703,6 +15704,14 @@ "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", "dev": true }, + "node_modules/nmea-simple": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/nmea-simple/-/nmea-simple-3.3.0.tgz", + "integrity": "sha512-jYJBoxgYBUAbm2tLv0NeqK4dxhv8hhrf8rhiWGJ3+i0ubv7gn5NGyoMgPEqkE8wKscQrMT9AyA09gtuNR+70ng==", + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", diff --git a/package.json b/package.json index d119b51..8abab12 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@types/node": "^16.18.68", "@types/react": "^18.2.45", "@types/react-dom": "^18.2.18", + "nmea-simple": "^3.3.0", "react": "^18.2.0", "react-dom": "^18.2.0", "styled-components": "^6.1.3", diff --git a/src/App.tsx b/src/App.tsx index ce4e6a8..7a75efc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,6 +5,8 @@ import { GridToolbarExport, GridToolbarFilterButton } from '@mui/x-data-grid'; +import DialogTitle from '@mui/material/DialogTitle'; +import Dialog from '@mui/material/Dialog'; import { Grid, @@ -14,18 +16,20 @@ import { Accordion, AccordionSummary, Typography, - AccordionDetails + AccordionDetails, } from '@mui/material'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import InfoRoundedIcon from '@mui/icons-material/InfoRounded'; import { useState, useEffect, useCallback, useRef } from 'react'; import { Data, Event, EventData, EEListItem, EListItem, EventItem } from './interfaces'; import { v4 as uuid } from 'uuid'; +import * as nmea from 'nmea-simple'; import './App.css'; -const location = `${window.location.host.split(':')[0]}:3000`; + const getData = async () => { - const res = await fetch(`http://${location}/skServer/eventsRoutingData`); + const res = await fetch(`${window.location.host}/skServer/eventsRoutingData`); return await res.json(); } @@ -39,13 +43,15 @@ const CustomToolbar = () => { ); } - function App() { const [events, setEvents] = useState(Array ()); const [emitters, setEmitters] = useState(Array ()); const [eventItems, setEventItems] = useState(Array ()); const socketConnection = useRef(null); + const [styled, setStyled] = useState() + + const [dialog, setDialog] = useState(false); const columnHeader = [ { field: 'identifier', headerName: 'ID', description:'PGN/Sentence Unique Identifier', width: 80 }, @@ -53,6 +59,25 @@ function App() { { field: 'data', headerName: 'Data', description:'NMEA 0183 string, or NMEA 2000 JSON', width: 650 }, ]; + const showJSONFormatted = (event: any) => { + let parsed: any + const isString = typeof event.row.identifier === 'string'; + if(isString){ + const replaced = event.row.data.replace(/"/g, '') + try{ + parsed = nmea.parseNmeaSentence(replaced) + } catch (err) { + parsed = {error: `Unable to parse sentence for ${event.row.identifier}`} + console.log(err) + } + + } else { + parsed = JSON.parse(event.row.data) + } + + setStyled(parsed) + } + const initData = (eventData: Data) => { let eventList: Array = [] let emittersList: Array = [] @@ -146,7 +171,7 @@ function App() { const updateSocketEvents = useCallback(() => { const checkedVisibleEvents = events.filter((event: EEListItem) => event.checked === true && event.visible === true) const eventList = checkedVisibleEvents.map(event => event.value).join(','); - const socketAddress = `ws:${location}/signalk/v1/stream?events=${eventList}&subscribe=none`; + const socketAddress = `ws:${window.location.host}/signalk/v1/stream?events=${eventList}&subscribe=none`; if(checkedVisibleEvents.length > 0){ socketConnection.current?.close(); const socket = new WebSocket(socketAddress); @@ -209,9 +234,10 @@ function App() { }, [emitters]); return ( -
+
+ setDialog(true)}/> } @@ -238,7 +264,7 @@ function App() { } - aria-controls="panel1a-content" + aria-controls="panel1b-content" aria-expanded={true} id="events"> Events ({events.filter(item=>item.visible).length}) @@ -260,9 +286,23 @@ function App() { + + + } + aria-controls="panel1c-content" + aria-expanded={true} + id="capture"> + Capture Window + + + {
 { JSON.stringify(styled, null, 2) } 
} +
+
Total Rows: {eventItems.length}
+ {setDialog(false)}}> + Instructions +
    +
  • Check the Emitters associated with the NMEA data source
  • +
  • Check the Events associated with the NMEA data source
  • +
  • Cick a row to inspect the formatted data in the Capture Window
  • +
  • Use the filters to reduce the rows to match specific criteria
  • +
  • You can export the rows into a CSV file
  • +
  • Currently only the following NMEA 0183 sentences can be parsed: APB, BWC, DBT, DTM, GGA, GLL, GNS, GSA, GST, GSV, HDG, HDM, HDT, MTK, MWV, RDID, RMC, VHW, VTG, ZDA
  • +
+
); }