128 lines
3.1 KiB
TypeScript
128 lines
3.1 KiB
TypeScript
import EventEmitter from 'events'
|
||
import { defineStore } from 'pinia'
|
||
import { parse, Helpers } from 'nmea'
|
||
|
||
export class NMEADataSource extends EventEmitter {}
|
||
|
||
|
||
const verify = (value: String) => {
|
||
if (!value) {
|
||
return false
|
||
}
|
||
|
||
const dollar_index = value.indexOf('$')
|
||
const star_index = value.indexOf('*')
|
||
if (value.indexOf('$') !== 0 || star_index <= dollar_index) {
|
||
return false
|
||
}
|
||
|
||
const [sentence, checksum, ] = value.split('*')
|
||
return Helpers.verifyChecksum(sentence, checksum)
|
||
}
|
||
|
||
export const useNMEAStore = defineStore('nmea', {
|
||
state: () => ({
|
||
GGA: null,
|
||
GLL: null,
|
||
GSA: {},
|
||
GSV: {},
|
||
RMC: null,
|
||
VTG: null,
|
||
ZDA: null,
|
||
TXT: null,
|
||
// ANT: null,
|
||
// DHV: null,
|
||
// LPS: null,
|
||
// UTC: null,
|
||
// GST: null,
|
||
// INS: null,
|
||
// TIM: null,
|
||
handled: false,
|
||
}),
|
||
getters: {
|
||
dateTime () {
|
||
if (!this.RMC || !this.RMC.date || !this.RMC.timestamp) return
|
||
|
||
return Helpers.parseDateTime(this.RMC.date, this.RMC.timestamp)
|
||
},
|
||
longitude () {
|
||
if (!this.RMC || !this.RMC.lon || !this.RMC.lonPole) return
|
||
|
||
return Helpers.parseLongitude(this.RMC.lon, this.RMC.lonPole)
|
||
},
|
||
latitude () {
|
||
if (!this.RMC || !this.RMC.lat || !this.RMC.latPole) return
|
||
|
||
return Helpers.parseLatitude(this.RMC.lat, this.RMC.latPole)
|
||
},
|
||
altitude () {
|
||
if (!this.GGA || !this.GGA.alt || !this.GGA.altUnit) return
|
||
|
||
return Helpers.parseAltitude(this.GGA.alt, this.GGA.altUnit)
|
||
},
|
||
satellites () {
|
||
return (talker_id) => {
|
||
const gsa = this.GSA[talker_id]
|
||
const gsvs = this.GSV[talker_id]
|
||
|
||
if (!gsa || !gsvs ) return
|
||
|
||
const satelliteArr = []
|
||
|
||
const active_satellites = gsa.satellites
|
||
|
||
gsvs.forEach(({ satellites }) => {
|
||
satellites.forEach(satellite => {
|
||
if (active_satellites.indexOf(parseInt(satellite.id)) < 0) {
|
||
satellite.active = false
|
||
} else {
|
||
satellite.active = true
|
||
}
|
||
|
||
satelliteArr.push(satellite)
|
||
})
|
||
})
|
||
|
||
return satelliteArr
|
||
}
|
||
},
|
||
},
|
||
actions: {
|
||
bindDataSource(source: NMEADataSource) {
|
||
source.on('open', () => this.$reset())
|
||
|
||
let result;
|
||
source.on('data', (data: String) => {
|
||
if (!verify(data)) return
|
||
|
||
result = parse(data)
|
||
if (!result) return
|
||
|
||
// 监控第一条语句,并重置所有state
|
||
if (result.sentence === 'GGA') this.$reset()
|
||
|
||
switch (result.sentence) {
|
||
case 'GSA':
|
||
this.GSA[result.talker_id] = result
|
||
break;
|
||
case 'GSV':
|
||
if (!this.GSV[result.talker_id]) {
|
||
this.GSV[result.talker_id] = []
|
||
}
|
||
|
||
this.GSV[result.talker_id].push(result)
|
||
break;
|
||
default:
|
||
this.$state[result.sentence] = result
|
||
break;
|
||
}
|
||
|
||
// 监听最后一条语句,并设置handled为true
|
||
if (result.sentence === 'TXT') {
|
||
this.handled = true
|
||
}
|
||
})
|
||
},
|
||
},
|
||
})
|