@furkot/garmin-data 1.0.2 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +1 -1
- package/lib/garmin.js +18 -19
- package/lib/index.js +234 -0
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports = require('./lib
|
|
1
|
+
module.exports = require('./lib');
|
package/lib/garmin.js
CHANGED
|
@@ -81,7 +81,7 @@ module.exports = {
|
|
|
81
81
|
78: 'Convenience Store', // minimarket
|
|
82
82
|
79: 'Anchor', // anchor
|
|
83
83
|
80: 'Toll Booth', // tollbooth
|
|
84
|
-
81: '
|
|
84
|
+
81: 'Medical Facility', // hospital
|
|
85
85
|
82: 'Restroom', // toilets
|
|
86
86
|
83: 'Truck Stop', // truck
|
|
87
87
|
84: 'RV Park', // rvpark
|
|
@@ -92,9 +92,9 @@ module.exports = {
|
|
|
92
92
|
89: 'Crossing', // railroadcrossing
|
|
93
93
|
90: 'Restaurant', // coffee
|
|
94
94
|
91: 'ATV', // atv
|
|
95
|
-
92: 'Dog
|
|
95
|
+
92: 'Dog Sitting', // pets
|
|
96
96
|
93: 'Triangle, Red', // fire
|
|
97
|
-
94: '
|
|
97
|
+
94: 'Bait and Tackle', // pier
|
|
98
98
|
95: 'Ferry', // ferry
|
|
99
99
|
96: 'Live Theater', // theater
|
|
100
100
|
97: 'Railway', // train
|
|
@@ -112,24 +112,24 @@ module.exports = {
|
|
|
112
112
|
109: 'Dam', // dam
|
|
113
113
|
110: 'Skull and Crossbones', // danger
|
|
114
114
|
111: 'Exit', // enter
|
|
115
|
-
112: 'Geocache',
|
|
115
|
+
112: 'Geocache Found', // gift
|
|
116
116
|
113: 'Contact, Blonde', // hairdresser
|
|
117
117
|
114: 'Favorite', // heart
|
|
118
118
|
115: 'Oil Field', // industry
|
|
119
|
-
116: '
|
|
119
|
+
116: 'Contact, Smiley', // laundry
|
|
120
120
|
117: 'Beacon', // lighthouse
|
|
121
121
|
118: 'Controlled Area', // one-way
|
|
122
122
|
119: 'Fitness Center', // playground
|
|
123
123
|
120: 'Police Station', // police
|
|
124
124
|
121: 'Police Station', // prison
|
|
125
|
-
122: '
|
|
125
|
+
122: 'Restricted Area', // roadblock
|
|
126
126
|
123: 'Contact, Alien', // rocket
|
|
127
127
|
124: 'School', // school
|
|
128
|
-
125: '
|
|
128
|
+
125: 'Lodge', // shelter
|
|
129
129
|
126: 'Shipwreck', // suitcase
|
|
130
|
-
127: 'Dog
|
|
130
|
+
127: 'Dog Running', // veterinary
|
|
131
131
|
128: 'Sad Face', // remove
|
|
132
|
-
129: '
|
|
132
|
+
129: 'Levee', // wetland
|
|
133
133
|
130: 'Circle with X', // wheelchair
|
|
134
134
|
131: 'Golf Course', // golf
|
|
135
135
|
132: 'Post Office', // envelope
|
|
@@ -137,7 +137,7 @@ module.exports = {
|
|
|
137
137
|
134: 'Ultralight Area', // airfield
|
|
138
138
|
135: 'Bar', // alcohol_shop
|
|
139
139
|
136: 'Stadium', // american_football
|
|
140
|
-
137: '
|
|
140
|
+
137: 'Reef', // aquarium
|
|
141
141
|
138: 'Scenic Area', // attraction
|
|
142
142
|
139: 'Pizza', // bakery
|
|
143
143
|
140: 'Ball Park', // baseball
|
|
@@ -152,8 +152,8 @@ module.exports = {
|
|
|
152
152
|
149: 'Scales', // commercial
|
|
153
153
|
150: 'Stadium', // cricket
|
|
154
154
|
151: 'Crossing', // cross
|
|
155
|
-
152: '
|
|
156
|
-
153: '
|
|
155
|
+
152: 'Medical Facility', // dentist
|
|
156
|
+
153: 'Medical Facility', // doctor
|
|
157
157
|
154: 'City Hall', // embassy
|
|
158
158
|
155: 'Exit', // entrance
|
|
159
159
|
156: 'Fast Food', // fast_food
|
|
@@ -169,15 +169,15 @@ module.exports = {
|
|
|
169
169
|
166: 'Railway', // rail_light
|
|
170
170
|
167: 'Railway', // rail_metro
|
|
171
171
|
168: 'Stadium', // soccer
|
|
172
|
-
169: '
|
|
172
|
+
169: 'Dot, White', // square-stroke
|
|
173
173
|
170: 'Square, Blue', // square-fill
|
|
174
174
|
171: 'City (Capitol)', // star-stroke
|
|
175
175
|
172: 'Restaurant', // sushi
|
|
176
176
|
173: 'Stadium', // tennis
|
|
177
177
|
174: 'Triangle, Blue', // triangle
|
|
178
|
-
175: 'Triangle,
|
|
178
|
+
175: 'Triangle, Green', // triangle_stroked
|
|
179
179
|
176: 'Multi-Cache', // warehouse
|
|
180
|
-
177: '
|
|
180
|
+
177: 'Stump', // garden
|
|
181
181
|
178: 'Gas Station', // diesel
|
|
182
182
|
179: 'Gas Station', // ethanol-free
|
|
183
183
|
180: 'Swimming Area', // swimming
|
|
@@ -194,11 +194,9 @@ module.exports = {
|
|
|
194
194
|
'Exit': 155, // entrance
|
|
195
195
|
'Fast Food': 156, // fast_food
|
|
196
196
|
'Favorite': 86, // star
|
|
197
|
-
'Fishing Area': 137, // aquarium
|
|
198
197
|
'Gas Station': 25, // fillingstation
|
|
199
|
-
'
|
|
200
|
-
'
|
|
201
|
-
'Hospital': 81, // hospital
|
|
198
|
+
'Ground Transportation': 106, // bus
|
|
199
|
+
'Medical Facility': 81, // hospital
|
|
202
200
|
'Lodging': 0, // hotel
|
|
203
201
|
'Museum': 33, // museum
|
|
204
202
|
'Park': 50, // park
|
|
@@ -208,6 +206,7 @@ module.exports = {
|
|
|
208
206
|
'Restaurant': 24, // restaurant
|
|
209
207
|
'Scenic Area': 61, // lookout
|
|
210
208
|
'School': 124, // school
|
|
209
|
+
'Shopping Center': 99, // cart
|
|
211
210
|
'Stadium': 68, // stadium
|
|
212
211
|
'Summit': 59, // mountains
|
|
213
212
|
'Swimming Area': 54, // watersport
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
const {
|
|
2
|
+
toGarmin,
|
|
3
|
+
toFurkot,
|
|
4
|
+
colors
|
|
5
|
+
} = require('./garmin');
|
|
6
|
+
|
|
7
|
+
const schema = [
|
|
8
|
+
[
|
|
9
|
+
'xmlns:gpxx', 'http://www.garmin.com/xmlschemas/GpxExtensions/v3',
|
|
10
|
+
'http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd'
|
|
11
|
+
],
|
|
12
|
+
[
|
|
13
|
+
'xmlns:trp', 'http://www.garmin.com/xmlschemas/TripExtensions/v1',
|
|
14
|
+
'http://www.garmin.com/xmlschemas/TripExtensionsv1.xsd'
|
|
15
|
+
],
|
|
16
|
+
[
|
|
17
|
+
'xmlns:tmd', 'http://www.garmin.com/xmlschemas/TripMetaDataExtensions/v1',
|
|
18
|
+
'http://www.garmin.com/xmlschemas/TripMetaDataExtensionsv1.xsd'
|
|
19
|
+
],
|
|
20
|
+
[
|
|
21
|
+
'xmlns:vptm', 'http://www.garmin.com/xmlschemas/ViaPointTransportationModeExtensions/v1',
|
|
22
|
+
'http://www.garmin.com/xmlschemas/ViaPointTransportationModeExtensionsv1.xsd'
|
|
23
|
+
]
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const modeMap = [
|
|
27
|
+
'Motorcycling',
|
|
28
|
+
'Automotive',
|
|
29
|
+
'Bicycling',
|
|
30
|
+
'Walking',
|
|
31
|
+
'Direct',
|
|
32
|
+
'Direct',
|
|
33
|
+
'RV',
|
|
34
|
+
'Direct'
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
function getMode(rMode, mMode) {
|
|
38
|
+
if (rMode !== undefined) {
|
|
39
|
+
return modeMap[rMode + 1] || 'Unknown';
|
|
40
|
+
}
|
|
41
|
+
return modeMap[(mMode || 0) + 1] || 'Unknown';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const millisInMinute = 60 * 1000;
|
|
45
|
+
const millisInHour = 60 * millisInMinute;
|
|
46
|
+
|
|
47
|
+
function formatDuration(step) {
|
|
48
|
+
const duration = ['P'];
|
|
49
|
+
if (step.nights) {
|
|
50
|
+
duration.push(step.nights, 'D');
|
|
51
|
+
}
|
|
52
|
+
if (step.visit_duration) {
|
|
53
|
+
duration.push('T');
|
|
54
|
+
let dur = Math.floor(step.visit_duration / millisInHour);
|
|
55
|
+
if (dur) {
|
|
56
|
+
duration.push(dur, 'H');
|
|
57
|
+
}
|
|
58
|
+
dur = Math.floor((step.visit_duration % millisInHour) / millisInMinute);
|
|
59
|
+
if (dur) {
|
|
60
|
+
duration.push(dur, 'M');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (duration.length > 2) {
|
|
64
|
+
return duration.join('');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getWptExt({ start, end, el, elIfText, each }) {
|
|
69
|
+
return function* (st) {
|
|
70
|
+
yield* start('gpxx:WaypointExtension');
|
|
71
|
+
if (st.tags?.length) {
|
|
72
|
+
yield* start('gpxx:Categories');
|
|
73
|
+
yield* each(st.tags, function* (cat) {
|
|
74
|
+
yield* el('gpxx:Category', null, cat);
|
|
75
|
+
});
|
|
76
|
+
yield* end();
|
|
77
|
+
}
|
|
78
|
+
if (st.stopStreetAddress || st.locality?.town || st.locality?.province || st.locality?.country_long) {
|
|
79
|
+
yield* start('gpxx:Address');
|
|
80
|
+
yield* elIfText('gpxx:StreetAddress', st.stopStreetAddress);
|
|
81
|
+
yield* elIfText('gpxx:City', st.locality?.town);
|
|
82
|
+
yield* elIfText('gpxx:State', st.locality?.province);
|
|
83
|
+
yield* elIfText('gpxx:Country', st.locality?.country_long);
|
|
84
|
+
yield* end();
|
|
85
|
+
}
|
|
86
|
+
yield* elIfText('gpxx:PhoneNumber', st.phone);
|
|
87
|
+
yield* end();
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function getRteExt({ ctx, start, end, el, elIfText }) {
|
|
92
|
+
return function* (rt) {
|
|
93
|
+
yield* start('gpxx:RouteExtension');
|
|
94
|
+
yield* elIfText('gpxx:IsAutoNamed', 'false');
|
|
95
|
+
yield* elIfText('gpxx:DisplayColor', colors[rt.color] || 'Blue');
|
|
96
|
+
yield* end();
|
|
97
|
+
|
|
98
|
+
const { mode, name } = ctx?.metadata || {};
|
|
99
|
+
|
|
100
|
+
if (rt.mode !== undefined || mode !== undefined) {
|
|
101
|
+
yield* start('trp:Trip');
|
|
102
|
+
//- The <trp:TransportationMode> extension tells the devices Trip Planner algorithm what calculation type to use:
|
|
103
|
+
//- Automotive, Motorcycling, Walking, Bicycling, Direct.
|
|
104
|
+
yield* elIfText('trp:TransportationMode', getMode(rt.mode, mode));
|
|
105
|
+
yield* end();
|
|
106
|
+
|
|
107
|
+
if (name || rt.routeTimestamp || rt.day) {
|
|
108
|
+
yield* start('tmd:TripMetaData');
|
|
109
|
+
yield* el('tmd:TripName', null, name || '');
|
|
110
|
+
if (rt.routeTimestamp) {
|
|
111
|
+
yield* elIfText('tmd:Date', rt.routeTimestamp);
|
|
112
|
+
}
|
|
113
|
+
yield* elIfText('tmd:DayNumber', rt.day);
|
|
114
|
+
yield* end();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function getRtePtExt({ ctx, precision, start, end, each, el, elIfText }) {
|
|
121
|
+
|
|
122
|
+
function* $gpxxRpt(p, subclass) {
|
|
123
|
+
const attribs = {
|
|
124
|
+
lat: p[1].toFixed(precision),
|
|
125
|
+
lon: p[0].toFixed(precision)
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
if (subclass) {
|
|
129
|
+
yield* start('gpxx:rpt', attribs);
|
|
130
|
+
yield* el('gpxx:Subclass', null, subclass);
|
|
131
|
+
yield* end();
|
|
132
|
+
} else {
|
|
133
|
+
yield* el('gpxx:rpt', attribs);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return function* (rt, st, index, next) {
|
|
138
|
+
let shapingPoint;
|
|
139
|
+
|
|
140
|
+
if (st.stopIsActualStop || index % 124 === 0 || !next) {
|
|
141
|
+
//- The <trp:ViaPoint> is equivalent to a Furkot Stop.
|
|
142
|
+
yield* start('trp:ViaPoint');
|
|
143
|
+
if (st.stopDeparture && next) {
|
|
144
|
+
yield* elIfText('trp:DepartureTime', st.stopDeparture);
|
|
145
|
+
}
|
|
146
|
+
if (index && next) {
|
|
147
|
+
yield* elIfText('trp:StopDuration', formatDuration(st));
|
|
148
|
+
}
|
|
149
|
+
if (st.stopTimestamp && index > 0) {
|
|
150
|
+
yield* elIfText('trp:ArrivalTime', st.stopTimestamp);
|
|
151
|
+
}
|
|
152
|
+
yield* elIfText('trp:CalculationMode', 'FasterTime');
|
|
153
|
+
yield* elIfText('trp:ElevationMode', 'Standard');
|
|
154
|
+
yield* end();
|
|
155
|
+
} else {
|
|
156
|
+
shapingPoint = true;
|
|
157
|
+
//- The <trp:ShapingPoint> is equivalent to Furkot Pass-through Points.
|
|
158
|
+
//- These points are displayed in the Route point list on the GPS but are not announced during navigation.
|
|
159
|
+
//- There can be up to 124 ShapingPoints between each ViaPoint.
|
|
160
|
+
yield* el('trp:ShapingPoint');
|
|
161
|
+
}
|
|
162
|
+
if (next && next.mode !== undefined) {
|
|
163
|
+
|
|
164
|
+
//- The <vptm:ViaPointTransportationMode> extension tells the devices Trip Planner algorithm
|
|
165
|
+
//- what calculation type to use between this and next point:
|
|
166
|
+
//- Automotive, Motorcycling, Walking, Bicycling, Direct.
|
|
167
|
+
yield* start('vptm:ViaPointTransportationMode');
|
|
168
|
+
yield* elIfText('vptm:TransportationMode', getMode(next.mode));
|
|
169
|
+
yield* end();
|
|
170
|
+
}
|
|
171
|
+
if (ctx.RoutePointExtension) {
|
|
172
|
+
yield* start('gpxx:RoutePointExtension');
|
|
173
|
+
|
|
174
|
+
//- The <gpxx:Subclass> is a special Garmin code for older Garmin devices that do not use
|
|
175
|
+
//- the Trip Planner algorithm. This specific code says to use the above RoutePoint as a waypoint.
|
|
176
|
+
//- Older Garmin devices don't use the Trip Planner algorithm.
|
|
177
|
+
yield* el('gpxx:Subclass', null, '000000000000FFFFFFFFFFFFFFFFFFFFFFFF');
|
|
178
|
+
const expanded = next && next.track;
|
|
179
|
+
|
|
180
|
+
if (expanded) {
|
|
181
|
+
yield* each(expanded, function* (p) {
|
|
182
|
+
let subclass;
|
|
183
|
+
|
|
184
|
+
//- All of the <gpxx:rpt> are equivalent to Furkot Track Points generated between Stops.
|
|
185
|
+
//- These points are not displayed on the GPS or announced during navigation.
|
|
186
|
+
if (next.custom || next.mode === 3) {
|
|
187
|
+
//- This Subclass code denotes a route point that is not on a mapped road (off-road).
|
|
188
|
+
//- There are usually many of these in succession to define the route path
|
|
189
|
+
//- and each off-road point needs to have this Subclass.
|
|
190
|
+
subclass = 'FFFF00000000FFFFFFFF2117000000000000';
|
|
191
|
+
} else if (shapingPoint) {
|
|
192
|
+
shapingPoint = false;
|
|
193
|
+
//- A Subclass other than 000000000000FFFFFFFFFFFFFFFFFFFFFFFF must be added after a ShapingPoint.
|
|
194
|
+
//- Any other ‘valid’ Subclass code works.
|
|
195
|
+
subclass = '0300F2F7C403DD6E00002116000025490404';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
yield* $gpxxRpt(p, subclass);
|
|
199
|
+
});
|
|
200
|
+
yield* $gpxxRpt(expanded[expanded.length - 1], '000000000000FFFFFFFFFFFFFFFFFFFFFFFF');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
yield* end();
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function getTrkExt({ start, end, elIfText }) {
|
|
209
|
+
return function* (tr) {
|
|
210
|
+
yield* start('gpxx:TrackExtension');
|
|
211
|
+
yield* elIfText('gpxx:DisplayColor', colors[tr.color]);
|
|
212
|
+
yield* end();
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = {
|
|
217
|
+
getWptCmt: st => st.notes,
|
|
218
|
+
getWptSym: st => toGarmin[st.sym],
|
|
219
|
+
hasWptExt: st => st.stopStreetAddress ||
|
|
220
|
+
st.locality?.town || st.locality?.province || st.locality?.country_long ||
|
|
221
|
+
st.phone ||
|
|
222
|
+
st.tags?.length,
|
|
223
|
+
getWptExt,
|
|
224
|
+
hasRteExt: () => true,
|
|
225
|
+
getRteExt,
|
|
226
|
+
hasRtePtExt: () => true,
|
|
227
|
+
getRtePtExt,
|
|
228
|
+
hasTrkExt: tr => colors[tr.color],
|
|
229
|
+
getTrkExt,
|
|
230
|
+
schema,
|
|
231
|
+
toGarmin,
|
|
232
|
+
toFurkot,
|
|
233
|
+
colors
|
|
234
|
+
};
|