@furkot/garmin-data 1.0.1 → 2.0.0

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 CHANGED
@@ -1 +1 @@
1
- module.exports = require('./lib/garmin');
1
+ module.exports = require('./lib');
package/lib/garmin.js CHANGED
@@ -7,7 +7,7 @@ module.exports = {
7
7
  4: 'Trail Head', // snowshoeing
8
8
  5: 'Library', // book
9
9
  6: 'Bank', // deal
10
- //7: '', // pin
10
+ 7: 'Pin, Blue', // pin
11
11
  8: 'Bike Trail', // biking
12
12
  9: 'Picnic Area', // picnic
13
13
  10: 'Gas Station', // charging
@@ -26,7 +26,7 @@ module.exports = {
26
26
  23: 'Airport', // airplane
27
27
  24: 'Restaurant', // restaurant
28
28
  25: 'Gas Station', // fillingstation
29
- //26: '', // motorcycle
29
+ 26: 'Bike Trail', // motorcycle
30
30
  27: 'Food Source', // farmstand
31
31
  28: 'Bar', // brewery
32
32
  29: 'Amusement Park', // amusementpark
@@ -43,7 +43,7 @@ module.exports = {
43
43
  40: 'Building', // worldheritagesite
44
44
  41: 'City Hall', // officebuilding
45
45
  42: 'Church', // shrine
46
- 43: 'Tower', // tower
46
+ 43: 'Tall Tower', // tower
47
47
  44: 'Church', // temple
48
48
  45: 'Museum', // sciencemuseum
49
49
  46: 'Building', // landmark
@@ -69,13 +69,13 @@ module.exports = {
69
69
  66: 'Library', // library
70
70
  67: 'Zoo', // zoo
71
71
  68: 'Stadium', // stadium
72
- //69: '', // windmill
73
- //70: '', // square
72
+ 69: 'Short Tower', // windmill
73
+ 70: 'Square, Green', // square
74
74
  71: 'City (Medium)', // town
75
- //72: '', // statue
75
+ 72: 'Buoy, White', // statue
76
76
  73: 'Information', // information
77
- //74: '', // amphitheater
78
- //75: '', // observatory
77
+ 74: 'Diamond, Green', // amphitheater
78
+ 75: 'Scenic Area', // observatory
79
79
  //76: '', // passthru
80
80
  77: 'Drinking Water', // tap
81
81
  78: 'Convenience Store', // minimarket
@@ -86,27 +86,129 @@ module.exports = {
86
86
  83: 'Truck Stop', // truck
87
87
  84: 'RV Park', // rvpark
88
88
  85: 'Bridge', // bridge
89
- 86: 'City (Capitol)', // star
89
+ 86: 'Favorite', // star
90
90
  87: 'Geocache', // treasure
91
- //88: '', // teleport
91
+ 88: 'Parachute Area', // teleport
92
92
  89: 'Crossing', // railroadcrossing
93
93
  90: 'Restaurant', // coffee
94
94
  91: 'ATV', // atv
95
95
  92: 'Dog, sitting', // pets
96
- //93: '', // fire
96
+ 93: 'Triangle, Red', // fire
97
97
  94: 'Fishing Area', // pier
98
98
  95: 'Ferry', // ferry
99
99
  96: 'Live Theater', // theater
100
100
  97: 'Railway', // train
101
101
  98: 'Parking Area', // parking
102
102
  99: 'Shopping Center', // cart
103
- 100: 'Boat Ramp' // boatramp
103
+ 100: 'Boat Ramp', // boatramp
104
+ 101: 'Covey', // bird
105
+ 102: 'Mile Marker', // clock
106
+ 103: 'Movie Theater', // film
107
+ 104: 'Horn', // music
108
+ 105: 'Contact, clown', // entertain
109
+ 106: 'Ground Transportation', // bus
110
+ 107: 'Ground Transportation', // taxi
111
+ 108: 'ATV', // off-road
112
+ 109: 'Dam', // dam
113
+ 110: 'Skull and Crossbones', // danger
114
+ 111: 'Exit', // enter
115
+ 112: 'Geocache', // gift
116
+ 113: 'Contact, Blonde', // hairdresser
117
+ 114: 'Favorite', // heart
118
+ 115: 'Oil Field', // industry
119
+ 116: 'Happy Face', // laundry
120
+ 117: 'Beacon', // lighthouse
121
+ 118: 'Controlled Area', // one-way
122
+ 119: 'Fitness Center', // playground
123
+ 120: 'Police Station', // police
124
+ 121: 'Police Station', // prison
125
+ 122: 'Laydown', // roadblock
126
+ 123: 'Contact, Alien', // rocket
127
+ 124: 'School', // school
128
+ 125: 'Fishing Hot Spot Facility',// shelter
129
+ 126: 'Shipwreck', // suitcase
130
+ 127: 'Dog, running', // veterinary
131
+ 128: 'Sad Face', // remove
132
+ 129: 'Underwater Grass', // wetland
133
+ 130: 'Circle with X', // wheelchair
134
+ 131: 'Golf Course', // golf
135
+ 132: 'Post Office', // envelope
136
+ 133: 'Funicular', // aerialway
137
+ 134: 'Ultralight Area', // airfield
138
+ 135: 'Bar', // alcohol_shop
139
+ 136: 'Stadium', // american_football
140
+ 137: 'Fishing Area', // aquarium
141
+ 138: 'Scenic Area', // attraction
142
+ 139: 'Pizza', // bakery
143
+ 140: 'Ball Park', // baseball
144
+ 141: 'Stadium', // basketball
145
+ 142: 'Building', // building
146
+ 143: 'Contact, Pig', // butcher
147
+ 144: 'Building', // castle
148
+ 145: 'Navaid, White', // radio-unchecked
149
+ 146: 'Circle, Blue', // circle
150
+ 147: 'Department Store', // clothing_store
151
+ 148: 'School', // college
152
+ 149: 'Scales', // commercial
153
+ 150: 'Stadium', // cricket
154
+ 151: 'Crossing', // cross
155
+ 152: 'Hospital', // dentist
156
+ 153: 'Hospital', // doctor
157
+ 154: 'City Hall', // embassy
158
+ 155: 'Exit', // entrance
159
+ 156: 'Fast Food', // fast_food
160
+ 157: 'Heliport', // heliport
161
+ 158: 'Fast Food', // ice_cream
162
+ 159: 'Pin, Green', // marker
163
+ 160: 'Summit', // mountain
164
+ 161: 'Parking, Pay', // parking_garage
165
+ 162: 'Pharmacy', // pharmacy
166
+ 163: 'Telephone', // phone
167
+ 164: 'Stadium', // pitch
168
+ 165: 'Church', // place_of_worship
169
+ 166: 'Railway', // rail_light
170
+ 167: 'Railway', // rail_metro
171
+ 168: 'Stadium', // soccer
172
+ 169: 'Square, Yellow', // square-stroke
173
+ 170: 'Square, Blue', // square-fill
174
+ 171: 'City (Capitol)', // star-stroke
175
+ 172: 'Restaurant', // sushi
176
+ 173: 'Stadium', // tennis
177
+ 174: 'Triangle, Blue', // triangle
178
+ 175: 'Triangle, Yellow', // triangle_stroked
179
+ 176: 'Multi-Cache', // warehouse
180
+ 177: 'Weed Bed', // garden
181
+ 178: 'Gas Station', // diesel
182
+ 179: 'Gas Station', // ethanol-free
183
+ 180: 'Swimming Area', // swimming
184
+ 181: 'Puzzle Cache' // question
104
185
  },
105
186
  toFurkot: {
187
+ 'ATV': 91, // atv
188
+ 'Bar': 31, // bar
189
+ 'Bike Trail': 8, // biking
190
+ 'Building': 51, // structure
106
191
  'Church': 34, // church
192
+ 'City Hall': 41, // officebuilding
193
+ 'Crossing': 89, // railroadcrossing
194
+ 'Exit': 155, // entrance
195
+ 'Fast Food': 156, // fast_food
196
+ 'Favorite': 86, // star
197
+ 'Fishing Area': 137, // aquarium
198
+ 'Gas Station': 25, // fillingstation
199
+ 'Geocache': 87, // treasure
200
+ 'Ground Transportation': 106, // bus'
201
+ 'Hospital': 81, // hospital
107
202
  'Lodging': 0, // hotel
108
203
  'Museum': 33, // museum
109
204
  'Park': 50, // park
205
+ 'Police Station': 120, // police
206
+ 'Railway': 97, // train
207
+ 'Residence': 12, // house
208
+ 'Restaurant': 24, // restaurant
209
+ 'Scenic Area': 61, // lookout
210
+ 'School': 124, // school
211
+ 'Stadium': 68, // stadium
110
212
  'Summit': 59, // mountains
111
213
  'Swimming Area': 54, // watersport
112
214
  'Trail Head': 3 // guide
package/lib/index.js ADDED
@@ -0,0 +1,233 @@
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 && 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.address) {
79
+ yield* start('gpxx:Address');
80
+ yield* elIfText('gpxx:StreetAddress', st.stopStreetAddress);
81
+ if (st.locality) {
82
+ yield* elIfText('gpxx:City', st.locality.town);
83
+ yield* elIfText('gpxx:State', st.locality.province);
84
+ yield* elIfText('gpxx:Country', st.locality.country_long);
85
+ }
86
+ yield* end();
87
+ }
88
+ yield* elIfText('gpxx:PhoneNumber', st.phone);
89
+ yield* end();
90
+ };
91
+ }
92
+
93
+ function getRteExt({ ctx, start, end, el, elIfText }) {
94
+ return function* (rt) {
95
+ yield* start('gpxx:RouteExtension');
96
+ yield* elIfText('gpxx:IsAutoNamed', 'false');
97
+ yield* elIfText('gpxx:DisplayColor', colors[rt.color] || 'Blue');
98
+ yield* end();
99
+
100
+ const { mode, name } = ctx?.metadata || {};
101
+
102
+ if (rt.mode !== undefined || mode !== undefined) {
103
+ yield* start('trp:Trip');
104
+ //- The <trp:TransportationMode> extension tells the devices Trip Planner algorithm what calculation type to use:
105
+ //- Automotive, Motorcycling, Walking, Bicycling, Direct.
106
+ yield* elIfText('trp:TransportationMode', getMode(rt.mode, mode));
107
+ yield* end();
108
+
109
+ if (name || rt.routeTimestamp || rt.day) {
110
+ yield* start('tmd:TripMetaData');
111
+ yield* el('tmd:TripName', null, name || '');
112
+ if (rt.routeTimestamp) {
113
+ yield* elIfText('tmd:Date', rt.routeTimestamp);
114
+ }
115
+ yield* elIfText('tmd:DayNumber', rt.day);
116
+ yield* end();
117
+ }
118
+ }
119
+ };
120
+ }
121
+
122
+ function getRtePtExt({ ctx, precision, start, end, each, el, elIfText }) {
123
+
124
+ function* $gpxxRpt(p, subclass) {
125
+ const attribs = {
126
+ lat: p[1].toFixed(precision),
127
+ lon: p[0].toFixed(precision)
128
+ };
129
+
130
+ if (subclass) {
131
+ yield* start('gpxx:rpt', attribs);
132
+ yield* el('gpxx:Subclass', null, subclass);
133
+ yield* end();
134
+ } else {
135
+ yield* el('gpxx:rpt', attribs);
136
+ }
137
+ }
138
+
139
+ return function* (rt, st, index, next) {
140
+ let shapingPoint;
141
+
142
+ if (st.stopIsActualStop || index % 124 === 0 || !next) {
143
+ //- The <trp:ViaPoint> is equivalent to a Furkot Stop.
144
+ yield* start('trp:ViaPoint');
145
+ if (st.stopDeparture && next) {
146
+ yield* elIfText('trp:DepartureTime', st.stopDeparture);
147
+ }
148
+ if (index && next) {
149
+ yield* elIfText('trp:StopDuration', formatDuration(st));
150
+ }
151
+ if (st.stopTimestamp && index > 0) {
152
+ yield* elIfText('trp:ArrivalTime', st.stopTimestamp);
153
+ }
154
+ yield* elIfText('trp:CalculationMode', 'FasterTime');
155
+ yield* elIfText('trp:ElevationMode', 'Standard');
156
+ yield* end();
157
+ } else {
158
+ shapingPoint = true;
159
+ //- The <trp:ShapingPoint> is equivalent to Furkot Pass-through Points.
160
+ //- These points are displayed in the Route point list on the GPS but are not announced during navigation.
161
+ //- There can be up to 124 ShapingPoints between each ViaPoint.
162
+ yield* el('trp:ShapingPoint');
163
+ }
164
+ if (next && next.mode !== undefined) {
165
+
166
+ //- The <vptm:ViaPointTransportationMode> extension tells the devices Trip Planner algorithm
167
+ //- what calculation type to use between this and next point:
168
+ //- Automotive, Motorcycling, Walking, Bicycling, Direct.
169
+ yield* start('vptm:ViaPointTransportationMode');
170
+ yield* elIfText('vptm:TransportationMode', getMode(next.mode));
171
+ yield* end();
172
+ }
173
+ if (ctx.RoutePointExtension) {
174
+ yield* start('gpxx:RoutePointExtension');
175
+
176
+ //- The <gpxx:Subclass> is a special Garmin code for older Garmin devices that do not use
177
+ //- the Trip Planner algorithm. This specific code says to use the above RoutePoint as a waypoint.
178
+ //- Older Garmin devices don't use the Trip Planner algorithm.
179
+ yield* el('gpxx:Subclass', null, '000000000000FFFFFFFFFFFFFFFFFFFFFFFF');
180
+ const expanded = next && next.track;
181
+
182
+ if (expanded) {
183
+ yield* each(expanded, function* (p) {
184
+ let subclass;
185
+
186
+ //- All of the <gpxx:rpt> are equivalent to Furkot Track Points generated between Stops.
187
+ //- These points are not displayed on the GPS or announced during navigation.
188
+ if (next.custom || next.mode === 3) {
189
+ //- This Subclass code denotes a route point that is not on a mapped road (off-road).
190
+ //- There are usually many of these in succession to define the route path
191
+ //- and each off-road point needs to have this Subclass.
192
+ subclass = 'FFFF00000000FFFFFFFF2117000000000000';
193
+ } else if (shapingPoint) {
194
+ shapingPoint = false;
195
+ //- A Subclass other than 000000000000FFFFFFFFFFFFFFFFFFFFFFFF must be added after a ShapingPoint.
196
+ //- Any other ‘valid’ Subclass code works.
197
+ subclass = '0300F2F7C403DD6E00002116000025490404';
198
+ }
199
+
200
+ yield* $gpxxRpt(p, subclass);
201
+ });
202
+ yield* $gpxxRpt(expanded[expanded.length - 1], '000000000000FFFFFFFFFFFFFFFFFFFFFFFF');
203
+ }
204
+
205
+ yield* end();
206
+ }
207
+ };
208
+ }
209
+
210
+ function getTrkExt({ start, end, elIfText }) {
211
+ return function* (tr) {
212
+ yield* start('gpxx:TrackExtension');
213
+ yield* elIfText('gpxx:DisplayColor', colors[tr.color]);
214
+ yield* end();
215
+ };
216
+ }
217
+
218
+ module.exports = {
219
+ getWptCmt: st => st.notes,
220
+ getWptSym: st => toGarmin[st.sym],
221
+ hasWptExt: st => st.address || st.phone || st.tags?.length,
222
+ getWptExt,
223
+ hasRteExt: () => true,
224
+ getRteExt,
225
+ hasRtePtExt: () => true,
226
+ getRtePtExt,
227
+ hasTrkExt: tr => tr.color,
228
+ getTrkExt,
229
+ schema,
230
+ toGarmin,
231
+ toFurkot,
232
+ colors
233
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@furkot/garmin-data",
3
- "version": "1.0.1",
3
+ "version": "2.0.0",
4
4
  "description": "Data used by Furkot modules dealing with Garmin GPX format.",
5
5
  "author": {
6
6
  "name": "Damian Krzeminski",