Skip to content

Commit e847711

Browse files
committed
Add MobileGPS support for DMR.
1 parent 2caa2e9 commit e847711

16 files changed

+255
-12
lines changed

Conf.cpp

+31-2
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ enum SECTION {
5555
SECTION_NEXTION,
5656
SECTION_OLED,
5757
SECTION_LCDPROC,
58-
SECTION_LOCK_FILE
58+
SECTION_LOCK_FILE,
59+
SECTION_MOBILE_GPS
5960
};
6061

6162
CConf::CConf(const std::string& file) :
@@ -242,7 +243,10 @@ m_lcdprocLocalPort(0U),
242243
m_lcdprocDisplayClock(false),
243244
m_lcdprocUTC(false),
244245
m_lockFileEnabled(false),
245-
m_lockFileName()
246+
m_lockFileName(),
247+
m_mobileGPSEnabled(false),
248+
m_mobileGPSAddress(),
249+
m_mobileGPSPort(0U)
246250
{
247251
}
248252

@@ -320,6 +324,8 @@ bool CConf::read()
320324
section = SECTION_LCDPROC;
321325
else if (::strncmp(buffer, "[Lock File]", 11U) == 0)
322326
section = SECTION_LOCK_FILE;
327+
else if (::strncmp(buffer, "[Mobile GPS]", 12U) == 0)
328+
section = SECTION_MOBILE_GPS;
323329
else
324330
section = SECTION_NONE;
325331

@@ -800,6 +806,13 @@ bool CConf::read()
800806
m_lockFileEnabled = ::atoi(value) == 1;
801807
else if (::strcmp(key, "File") == 0)
802808
m_lockFileName = value;
809+
} else if (section == SECTION_MOBILE_GPS) {
810+
if (::strcmp(key, "Enable") == 0)
811+
m_mobileGPSEnabled = ::atoi(value) == 1;
812+
else if (::strcmp(key, "Address") == 0)
813+
m_mobileGPSAddress = value;
814+
else if (::strcmp(key, "Port") == 0)
815+
m_mobileGPSPort = (unsigned int)::atoi(value);
803816
}
804817
}
805818

@@ -1727,3 +1740,19 @@ std::string CConf::getLockFileName() const
17271740
{
17281741
return m_lockFileName;
17291742
}
1743+
1744+
bool CConf::getMobileGPSEnabled() const
1745+
{
1746+
return m_mobileGPSEnabled;
1747+
}
1748+
1749+
std::string CConf::getMobileGPSAddress() const
1750+
{
1751+
return m_mobileGPSAddress;
1752+
}
1753+
1754+
unsigned int CConf::getMobileGPSPort() const
1755+
{
1756+
return m_mobileGPSPort;
1757+
}
1758+

Conf.h

+8
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,10 @@ class CConf
268268
bool getLockFileEnabled() const;
269269
std::string getLockFileName() const;
270270

271+
// The Mobile GPS section
272+
bool getMobileGPSEnabled() const;
273+
std::string getMobileGPSAddress() const;
274+
unsigned int getMobileGPSPort() const;
271275

272276
private:
273277
std::string m_file;
@@ -481,6 +485,10 @@ class CConf
481485

482486
bool m_lockFileEnabled;
483487
std::string m_lockFileName;
488+
489+
bool m_mobileGPSEnabled;
490+
std::string m_mobileGPSAddress;
491+
unsigned int m_mobileGPSPort;
484492
};
485493

486494
#endif

MMDVM.ini

+5
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,8 @@ UTC=0
247247
Enable=0
248248
File=/tmp/MMDVM_Active.lck
249249

250+
[Mobile GPS]
251+
Enable=0
252+
Address=127.0.0.1
253+
Port=7834
254+

MMDVMHost.cpp

+28-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ m_callsign(),
157157
m_id(0U),
158158
m_cwCallsign(),
159159
m_lockFileEnabled(false),
160-
m_lockFileName()
160+
m_lockFileName(),
161+
m_mobileGPS(NULL)
161162
{
162163
}
163164

@@ -941,6 +942,9 @@ int CMMDVMHost::run()
941942
if (m_pocsagNetwork != NULL)
942943
m_pocsagNetwork->clock(ms);
943944

945+
if (m_mobileGPS != NULL)
946+
m_mobileGPS->clock(ms);
947+
944948
m_cwIdTimer.clock(ms);
945949
if (m_cwIdTimer.isRunning() && m_cwIdTimer.hasExpired()) {
946950
if (m_mode == MODE_IDLE && !m_modem->hasTX()){
@@ -996,6 +1000,11 @@ int CMMDVMHost::run()
9961000
m_display->close();
9971001
delete m_display;
9981002

1003+
if (m_mobileGPS != NULL) {
1004+
m_mobileGPS->close();
1005+
delete m_mobileGPS;
1006+
}
1007+
9991008
if (m_ump != NULL) {
10001009
m_ump->close();
10011010
delete m_ump;
@@ -1222,6 +1231,24 @@ bool CMMDVMHost::createDMRNetwork()
12221231
return false;
12231232
}
12241233

1234+
bool mobileGPSEnabled = m_conf.getMobileGPSEnabled();
1235+
if (mobileGPSEnabled) {
1236+
std::string mobileGPSAddress = m_conf.getMobileGPSAddress();
1237+
unsigned int mobileGPSPort = m_conf.getMobileGPSPort();
1238+
1239+
LogInfo("Mobile GPS Parameters");
1240+
LogInfo(" Address: %s", mobileGPSAddress.c_str());
1241+
LogInfo(" Port; %u", mobileGPSPort);
1242+
1243+
m_mobileGPS = new CMobileGPS(address, port, m_dmrNetwork);
1244+
1245+
ret = m_mobileGPS->open();
1246+
if (!ret) {
1247+
delete m_mobileGPS;
1248+
m_mobileGPS = NULL;
1249+
}
1250+
}
1251+
12251252
m_dmrNetwork->enable(true);
12261253

12271254
return true;

MMDVMHost.h

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "P25Network.h"
2828
#include "DMRNetwork.h"
2929
#include "DMRLookup.h"
30+
#include "MobileGPS.h"
3031
#include "Display.h"
3132
#include "Timer.h"
3233
#include "Modem.h"
@@ -87,6 +88,7 @@ class CMMDVMHost
8788
std::string m_cwCallsign;
8889
bool m_lockFileEnabled;
8990
std::string m_lockFileName;
91+
CMobileGPS* m_mobileGPS;
9092

9193
void readParams();
9294
bool createModem();

MMDVMHost.vcxproj

+3-1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
<ClInclude Include="LCDproc.h" />
188188
<ClInclude Include="Log.h" />
189189
<ClInclude Include="MMDVMHost.h" />
190+
<ClInclude Include="MobileGPS.h" />
190191
<ClInclude Include="Modem.h" />
191192
<ClInclude Include="ModemSerialPort.h" />
192193
<ClInclude Include="Mutex.h" />
@@ -274,6 +275,7 @@
274275
<ClCompile Include="LCDproc.cpp" />
275276
<ClCompile Include="Log.cpp" />
276277
<ClCompile Include="MMDVMHost.cpp" />
278+
<ClCompile Include="MobileGPS.cpp" />
277279
<ClCompile Include="Modem.cpp" />
278280
<ClCompile Include="ModemSerialPort.cpp" />
279281
<ClCompile Include="Mutex.cpp" />
@@ -325,4 +327,4 @@
325327
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
326328
<ImportGroup Label="ExtensionTargets">
327329
</ImportGroup>
328-
</Project>
330+
</Project>

MMDVMHost.vcxproj.filters

+7-1
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@
275275
<ClInclude Include="I2CController.h">
276276
<Filter>Header Files</Filter>
277277
</ClInclude>
278+
<ClInclude Include="MobileGPS.h">
279+
<Filter>Header Files</Filter>
280+
</ClInclude>
278281
</ItemGroup>
279282
<ItemGroup>
280283
<ClCompile Include="BPTC19696.cpp">
@@ -514,5 +517,8 @@
514517
<ClCompile Include="I2CController.cpp">
515518
<Filter>Source Files</Filter>
516519
</ClCompile>
520+
<ClCompile Include="MobileGPS.cpp">
521+
<Filter>Source Files</Filter>
522+
</ClCompile>
517523
</ItemGroup>
518-
</Project>
524+
</Project>

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LDFLAGS = -g
99
OBJECTS = \
1010
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
1111
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
12-
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
12+
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
1313
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
1414
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
1515
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \

Makefile.Pi

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LDFLAGS = -g -L/usr/local/lib
99
OBJECTS = \
1010
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
1111
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
12-
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
12+
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
1313
NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \
1414
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o \
1515
QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \

Makefile.Pi.Adafruit

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LDFLAGS = -g -L/usr/local/lib
99
OBJECTS = \
1010
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
1111
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
12-
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
12+
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
1313
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
1414
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
1515
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \

Makefile.Pi.HD44780

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LDFLAGS = -g -L/usr/local/lib
99
OBJECTS = \
1010
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
1111
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
12-
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
12+
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
1313
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
1414
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
1515
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \

Makefile.Pi.OLED

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LDFLAGS = -g -L/usr/local/lib
99
OBJECTS = \
1010
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
1111
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
12-
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
12+
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
1313
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
1414
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
1515
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \

Makefile.Pi.PCF8574

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LDFLAGS = -g -L/usr/local/lib
99
OBJECTS = \
1010
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
1111
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
12-
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
12+
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
1313
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
1414
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
1515
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \

Makefile.Solaris

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ LDFLAGS = -g
99
OBJECTS = \
1010
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
1111
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
12-
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
12+
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
1313
NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \
1414
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o \
1515
QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \

MobileGPS.cpp

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (C) 2018 by Jonathan Naylor G4KLX
3+
*
4+
* This program is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation; either version 2 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program; if not, write to the Free Software
16+
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17+
*/
18+
19+
#include "MobileGPS.h"
20+
21+
#include <cstdio>
22+
#include <cassert>
23+
#include <cstring>
24+
#include <cmath>
25+
26+
CMobileGPS::CMobileGPS(const std::string& address, unsigned int port, CDMRNetwork* network) :
27+
m_idTimer(1000U, 60U),
28+
m_address(),
29+
m_port(port),
30+
m_socket(),
31+
m_network(network)
32+
{
33+
assert(!address.empty());
34+
assert(port > 0U);
35+
assert(network != NULL);
36+
37+
m_address = CUDPSocket::lookup(address);
38+
}
39+
40+
CMobileGPS::~CMobileGPS()
41+
{
42+
}
43+
44+
bool CMobileGPS::open()
45+
{
46+
bool ret = m_socket.open();
47+
if (!ret)
48+
return false;
49+
50+
m_idTimer.start();
51+
52+
return true;
53+
}
54+
55+
void CMobileGPS::clock(unsigned int ms)
56+
{
57+
m_idTimer.clock(ms);
58+
59+
if (m_idTimer.hasExpired()) {
60+
pollGPS();
61+
m_idTimer.start();
62+
}
63+
64+
sendReport();
65+
}
66+
67+
void CMobileGPS::close()
68+
{
69+
m_socket.close();
70+
}
71+
72+
bool CMobileGPS::pollGPS()
73+
{
74+
return m_socket.write((unsigned char*)"MMDVMHost", 9U, m_address, m_port);
75+
}
76+
77+
void CMobileGPS::sendReport()
78+
{
79+
// Grab GPS data if it's available
80+
unsigned char buffer[200U];
81+
in_addr address;
82+
unsigned int port;
83+
int ret = m_socket.read(buffer, 200U, address, port);
84+
if (ret <= 0)
85+
return;
86+
87+
buffer[ret] = '\0';
88+
89+
// Parse the GPS data
90+
char* pLatitude = ::strtok((char*)buffer, ",\n"); // Latitude
91+
char* pLongitude = ::strtok(NULL, ",\n"); // Longitude
92+
93+
if (pLatitude == NULL || pLongitude == NULL)
94+
return;
95+
96+
float latitude = ::atof(pLatitude);
97+
float longitude = ::atof(pLongitude);
98+
99+
m_network->writeHomePosition(latitude, longitude);
100+
}
101+

0 commit comments

Comments
 (0)