X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=plugins%2Fgpsnmea%2Fgpsnmea.cpp;h=ec01f9086d782d5a0ab3669338aaefa5015219c0;hb=eda9be7528ed04a3cd7f678aac0a82ffdf6d35a0;hp=e241e10a44a9819c75ebde6a0f878bb4b26aaae8;hpb=6f2315fd39746941f6e0b87cc5c66d4313cf02fe;p=profile%2Fivi%2Fautomotive-message-broker.git diff --git a/plugins/gpsnmea/gpsnmea.cpp b/plugins/gpsnmea/gpsnmea.cpp index e241e10..ec01f90 100644 --- a/plugins/gpsnmea/gpsnmea.cpp +++ b/plugins/gpsnmea/gpsnmea.cpp @@ -20,6 +20,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "timestamp.h" #include "serialport.hpp" #include "bluetooth.hpp" +#include "bluetooth5.h" +#include +#include +#include + +#include +#include #include #include @@ -33,6 +40,10 @@ using namespace std; #include "abstractpropertytype.h" #define GPSTIME "GpsTime" +#define GPSSPEED "GpsSpeed" +#define GpsFix "GpsFix" +#define GpsSatsUsed "GpsSatsUsed" +#define GpsNmea "GpsNmea" template inline T2 lexical_cast(const std::string &in) { @@ -43,53 +54,81 @@ inline T2 lexical_cast(const std::string &in) { return out; } +class GpsInfo: public DBusSink +{ +public: + GpsInfo(VehicleProperty::Property, AbstractRoutingEngine* re, GDBusConnection* connection) + :DBusSink("GpsInfo", re, connection, map()) + { + wantPropertyVariant(GPSTIME, "GpsTime", VariantType::Read); + wantPropertyVariant(GPSSPEED, "Speed", VariantType::Read); + wantPropertyVariant(GpsFix, "Fix", VariantType::Read); + wantPropertyVariant(GpsSatsUsed, "SattelitesUsed", VariantType::Read); + wantPropertyVariant(GpsNmea, "RawNmea", VariantType::Read); + } +}; + class Location { public: - Location(AbstractRoutingEngine* re, std::string uuid); + enum FixType { + NoFix = 1, + Fix2D = 2, + Fix3D = 3 + }; + + Location(AmbPluginImpl *source, std::shared_ptr lat, + std::shared_ptr lon, + std::shared_ptr alt, + std::shared_ptr dir, + std::shared_ptr spd, + std::shared_ptr time, + std::shared_ptr fix, + std::shared_ptr satsUsed, + std::shared_ptr vspd); void parse(std::string gprmc); - VehicleProperty::LatitudeType latitude() + AbstractPropertyType * latitude() { - return mLatitude; + return mLatitude.get(); } - VehicleProperty::LongitudeType longitude() + AbstractPropertyType * longitude() { - return mLongitude; + return mLongitude.get(); } - VehicleProperty::AltitudeType altitude() + AbstractPropertyType * altitude() { - return mAltitude; + return mAltitude.get(); } - VehicleProperty::DirectionType direction() + AbstractPropertyType * direction() { - return mDirection; + return mDirection.get(); } - VehicleProperty::VehicleSpeedType speed() + AbstractPropertyType * speed() { - return mSpeed; + return mSpeed.get(); } - BasicPropertyType gpsTime() + AbstractPropertyType * gpsTime() { - return mGpsTime; + return mGpsTime.get(); } std::list fix() { std::list l; - l.push_back(&mLatitude); - l.push_back(&mLongitude); - l.push_back(&mAltitude); - l.push_back(&mDirection); - l.push_back(&mSpeed); - l.push_back(&mGpsTime); + l.push_back(mLatitude.get()); + l.push_back(mLongitude.get()); + l.push_back(mAltitude.get()); + l.push_back(mDirection.get()); + l.push_back(mSpeed.get()); + l.push_back(mGpsTime.get()); return l; } @@ -98,6 +137,7 @@ private: ///methods: void parseGprmc(string gprmc); void parseGpgga(string gpgga); + void parseGpgsa(string gpgsa); void parseTime(std::string h, std::string m, std::string s, string dd, string mm, string yy); void parseLatitude(std::string d, std::string m, std::string ns); @@ -110,30 +150,48 @@ private: ///methods: private: - VehicleProperty::LatitudeType mLatitude; - VehicleProperty::LongitudeType mLongitude; - VehicleProperty::AltitudeType mAltitude; - VehicleProperty::DirectionType mDirection; - VehicleProperty::VehicleSpeedType mSpeed; - BasicPropertyType mGpsTime; + std::shared_ptr mLatitude; + std::shared_ptr mLongitude; + std::shared_ptr mAltitude; + std::shared_ptr mDirection; + std::shared_ptr mSpeed; + std::shared_ptr mVehicleSpeed; + std::shared_ptr mGpsTime; + std::shared_ptr mFix; + std::shared_ptr mSatelitesUsed; bool isActive; - std::string mUuid; - - AbstractRoutingEngine* routingEngine; + AmbPluginImpl * parent; }; -Location::Location(AbstractRoutingEngine* re, std::string uuid) - :mLatitude(0), mLongitude(0), mAltitude(0), mDirection(0), mSpeed(0), mGpsTime(GPSTIME,0), isActive(false), routingEngine(re), mUuid(uuid) +Location::Location(AmbPluginImpl* source, + std::shared_ptr lat, + std::shared_ptr lon, + std::shared_ptr alt, + std::shared_ptr dir, + std::shared_ptr spd, + std::shared_ptr time, + std::shared_ptr fix, + std::shared_ptr satsUsed, + std::shared_ptr vspd) + :parent(source), isActive(false) { - + mLatitude = lat; + mLongitude = lon; + mAltitude = alt; + mDirection = dir; + mSpeed = spd; + mGpsTime = time; + mFix = fix; + mSatelitesUsed = satsUsed; + mVehicleSpeed = vspd; } void Location::parse(string nmea) { - if(boost::algorithm::starts_with(nmea,"GPRMC")) + if(boost::algorithm::starts_with(nmea,"GPRMC") || boost::algorithm::starts_with(nmea,"GNRMC")) { parseGprmc(nmea); } @@ -141,9 +199,13 @@ void Location::parse(string nmea) { parseGpgga(nmea); } + else if(boost::algorithm::starts_with(nmea, "GPGSA")) + { + parseGpgsa(nmea); + } else { - DebugOut(DebugOut::Warning)<<"unknown/unhandled message: "< tokens; boost::split(tokens, gprmc, boost::is_any_of(",")); + if(!tokens.size()) + { + return; + } + if(tokens[2] == "A") { isActive = true; } + if(tokens[1].empty() || tokens[9].empty() || tokens[3].empty() || tokens[4].empty() || tokens[5].empty() || tokens[6].empty() || tokens[7].empty() || tokens[8].empty()) + { + return; + } + parseTime(tokens[1].substr(0,2),tokens[1].substr(2,2),tokens[1].substr(4,2),tokens[9].substr(0,2),tokens[9].substr(2,2),tokens[9].substr(4,2)); parseLatitude(tokens[3], "", tokens[4]); @@ -191,6 +263,37 @@ void Location::parseGpgga(string gpgga) parseAltitude(tokens[9]); } +void Location::parseGpgsa(string gpgsa) +{ + std::vector tokens; + boost::split(tokens, gpgsa, boost::is_any_of(",")); + + if(tokens.size() != 18) + { + DebugOut()<<"Invalid GPGSA message: "<(tokens[2]); + + uint16_t numsats = 0; + + for(int i=3; i<15; i++) + { + std::string sat = tokens[i]; + if(!sat.empty()) + { + numsats ++; + } + } + + if(mFix->value() != fix) + parent->setValue(mFix, fix); + + if(mSatelitesUsed->value() != numsats) + parent->setValue(mSatelitesUsed, numsats); +} + void Location::parseTime(string h, string m, string s, string dd, string mm, string yy) { try @@ -200,22 +303,19 @@ void Location::parseTime(string h, string m, string s, string dd, string mm, str t.tm_min = boost::lexical_cast(m); t.tm_sec = boost::lexical_cast(s); t.tm_mday = boost::lexical_cast(dd); - t.tm_mon = boost::lexical_cast(mm); + t.tm_mon = boost::lexical_cast(mm) - 1; t.tm_year = boost::lexical_cast(yy) + 100; time_t time = mktime(&t); - BasicPropertyType temp(GPSTIME,(double)time); - - if(mGpsTime != temp) + if(mGpsTime->value() != (double(time))) { - mGpsTime = temp; - routingEngine->updateProperty(&mGpsTime, mUuid); + parent->setValue(mGpsTime, double(time)); } } catch(...) { - DebugOut(DebugOut::Warning)<<"Failed to parse time "<value() != dec) { - mLatitude = temp;\ - routingEngine->updateProperty(&mLatitude, mUuid); + parent->setValue(mLatitude, dec); } } catch(...) { - DebugOut(DebugOut::Warning)<<"Failed to parse latitude"<value() != dec) { - mLongitude = temp;\ - routingEngine->updateProperty(&mLongitude, mUuid); + parent->setValue(mLongitude, dec); } } catch(...) { - DebugOut(DebugOut::Warning)<<"failed to parse longitude"<(s); + + if(mSpeed->value() != speed) { - mSpeed = temp; - routingEngine->updateProperty(&mSpeed, mUuid); + parent->setValue(mSpeed, speed); } } catch(...) { - DebugOut(DebugOut::Warning)<<"failed to parse speed"<(dir); - VehicleProperty::DirectionType temp(d); - if(mDirection != temp) + if(mDirection->value() != d) { - mDirection = temp; - routingEngine->updateProperty(&mDirection, mUuid); + parent->setValue(mDirection, d); } } catch(...) { - DebugOut(DebugOut::Warning)<<"Failed to parse direction: "<(alt); - VehicleProperty::AltitudeType temp(a); - if(mAltitude != temp) + if(mAltitude->value() != a) { - mAltitude = temp; - routingEngine->updateProperty(&mAltitude, mUuid); + parent->setValue(mAltitude, a); } - - mAltitude = VehicleProperty::AltitudeType(a); } catch(...) { - DebugOut(DebugOut::Warning)<<"failed to parse altitude"< config) +extern "C" void create(AbstractRoutingEngine* routingengine, map config) { - return new GpsNmeaSource(routingengine, config); - + auto plugin = new AmbPlugin(routingengine, config); + plugin->init(); } -GpsNmeaSource::GpsNmeaSource(AbstractRoutingEngine *re, map config) - :AbstractSource(re,config), mUuid("33d86462-1708-4f78-a001-99ea8d55422b") +GpsNmeaSource::GpsNmeaSource(AbstractRoutingEngine *re, map config, AbstractSource &parent) + :AmbPluginImpl(re, config, parent), mUuid("33d86462-1708-4f78-a001-99ea8d55422b"), device(nullptr), bt(nullptr) { int baudrate = 0; - location =new Location(re, mUuid); - - VehicleProperty::registerProperty(GPSTIME,[](){ return new BasicPropertyType(GPSTIME,0); }); - - addPropertySupport(VehicleProperty::Latitude, Zone::None); - addPropertySupport(VehicleProperty::Longitude, Zone::None); - addPropertySupport(VehicleProperty::Altitude, Zone::None); - addPropertySupport(VehicleProperty::VehicleSpeed, Zone::None); - addPropertySupport(VehicleProperty::Direction, Zone::None); - addPropertySupport(GPSTIME, Zone::None); - - - ///test: - - if(config.find("test") != config.end()) - { - Location location(routingEngine, mUuid); - location.parse("GPRMC,061211,A,2351.9605,S,15112.5239,E,000.0,053.4,170303,009.9,E*6E"); - DebugOut(0)<<"lat: "<(Zone::None); + auto lon = addPropertySupport(Zone::None); + auto alt = addPropertySupport(Zone::None); + auto spd = addPropertySupport(Zone::None, [](){ return new BasicPropertyType(GPSSPEED, 0); }); + auto vspd = addPropertySupport(Zone::None); + auto dir = addPropertySupport(Zone::None); + auto time = addPropertySupport(Zone::None, [](){ return new BasicPropertyType(GPSTIME, 0); }); + auto fix = addPropertySupport(Zone::None, []() { return new BasicPropertyType(GpsFix, Location::NoFix); }); + auto satsUsed = addPropertySupport(Zone::None, []() { return new BasicPropertyType(GpsSatsUsed, 0); }); + rawNmea = addPropertySupport(Zone::None, []() { return new StringPropertyType(GpsNmea); }); - g_assert(location.latitude().toString() == "-23.86600833"); - g_assert(location.gpsTime().toString() == "1050585131"); - - location.parse("GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"); - - DebugOut(0)<<"alt: "< conf if(config.find("device")!= config.end()) { std::string dev = config["device"]; + if(dev.find(":") != string::npos) { - BluetoothDevice bt; - dev = bt.getDeviceForAddress(dev, btaddapter); - } +#ifdef USE_BLUEZ5 + bt = new Bluetooth5(); + bt->getDeviceForAddress(dev, [this](int fd) { + DebugOut() << "fd: " << fd << endl; + device = new SerialPort(fd); + int baudrate=0; + + if(baudrate!=0) + { + if((static_cast(device))->setSpeed(baudrate)) + DebugOut(DebugOut::Error)<<"Unsupported baudrate " << configuration["baudrate"] << endl; + } - device = new SerialPort(dev); + DebugOut()<<"read from device: "<read()<(device))->setSpeed(baudrate)) - DebugOut(DebugOut::Error)<<"Unsupported baudrate " << config["baudrate"] << endl; - } + GIOChannel *chan = g_io_channel_unix_new(device->fileDescriptor()); + g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)readCallback, this); + g_io_channel_set_close_on_unref(chan, true); + g_io_channel_unref(chan); + }); +#else + bt = new BluetoothDevice(); + dev = bt->getDeviceForAddress(dev, btaddapter); - if(!device->open()) - { - DebugOut(DebugOut::Error)<<"Failed to open gps tty: "<(device))->setSpeed(baudrate)) + DebugOut(DebugOut::Error)<<"Unsupported baudrate " << config["baudrate"] << endl; + } + + if(!device->open()) + { + DebugOut(DebugOut::Error)<<"Failed to open gps tty: "<read()<fileDescriptor()); + g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)readCallback, this); + g_io_channel_set_close_on_unref(chan, true); + g_io_channel_unref(chan); +#endif } + else + { + device = new SerialPort(dev); + + if(baudrate!=0) + { + if((static_cast(device))->setSpeed(baudrate)) + DebugOut(DebugOut::Error)<<"Unsupported baudrate " << config["baudrate"] << endl; + } + + if(!device->open()) + { + DebugOut(DebugOut::Error) << "Failed to open gps tty: " << config["device"] << endl; + perror("Error"); + return; + } - DebugOut()<<"read from device: "<read()<read()<fileDescriptor()); - g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR),(GIOFunc)readCallback, this); - g_io_channel_set_close_on_unref(chan, true); - g_io_channel_unref(chan); //Pass ownership of the GIOChannel to the watch. + GIOChannel *chan = g_io_channel_unix_new(device->fileDescriptor()); + g_io_add_watch(chan, GIOCondition(G_IO_IN | G_IO_HUP | G_IO_ERR), (GIOFunc)readCallback, this); + g_io_channel_set_close_on_unref(chan, true); + g_io_channel_unref(chan); + } } } GpsNmeaSource::~GpsNmeaSource() { - device->close(); + if(device && device->isOpen()) + device->close(); + if(bt) + delete bt; } -const string GpsNmeaSource::uuid() +const string GpsNmeaSource::uuid() const { return mUuid; } - -void GpsNmeaSource::getPropertyAsync(AsyncPropertyReply *reply) +int GpsNmeaSource::supportedOperations() const { - DebugOut()<<"GpsNmeaSource: getPropertyAsync called for property: "<property< f = location->fix(); +void GpsNmeaSource::init() +{ + if(configuration.find("test") != configuration.end()) + { + test(); + } - for(auto property : f) + routingEngine->subscribeToProperty(DBusConnected,[this](AbstractPropertyType* value) { - if(property->name == reply->property) + if(value->name == DBusConnected) { - reply->success = true; - reply->value = property; - reply->completed(reply); - return; + if(value->value()) + { + amb::Exporter::instance()->exportProperty(routingEngine); + } } - } - - reply->success = false; - reply->error = AsyncPropertyReply::InvalidOperation; - reply->completed(reply); + }); } -void GpsNmeaSource::getRangePropertyAsync(AsyncRangePropertyReply *reply) +void GpsNmeaSource::canHasData() { + std::string data = device->read(); + tryParse(data); } -AsyncPropertyReply *GpsNmeaSource::setProperty(AsyncSetPropertyRequest request ) +void GpsNmeaSource::test() { + location->parse("GPRMC,061211,A,2351.9605,S,15112.5239,E,000.0,053.4,170303,009.9,E*6E"); -} + DebugOut(0)<<"lat: "<latitude()->toString()<gpsTime()->toString()<latitude()->toString() == "-23.86600833"); + g_assert(location->gpsTime()->toString() == "1050585131"); -PropertyList GpsNmeaSource::supported() -{ - return mSupported; -} + location->parse("GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"); -int GpsNmeaSource::supportedOperations() -{ - return Get; -} + DebugOut(0)<<"alt: "<altitude()->toString()<latitude()->toString()<altitude()->toString() == "545.4"); + g_assert(location->latitude()->toString() == "48.1173"); -void GpsNmeaSource::canHasData() -{ - std::string data = device->read(); + location->parse("GPRMC,060136.00,A,3101.40475,N,12126.87095,E,0.760,,160114,,,A*74"); + DebugOut(0)<<"lon: "<longitude()->toString()<latitude()->toString()<parse("GPGSA,A,3,04,05,,09,12,,,24,,,,,2.5,1.3,2.1*39"); + + //Test incomplete message: + location->parse("GPRMC,023633.00,V,,,,,,,180314,,,N*75"); + DebugOut(0)<<"lon: "<longitude()->toString()<latitude()->toString()<parse("GPRMC,,V,,,,,,,,,,N*53"); + + //test false message: + + g_assert(!checksum("GPRMC,172758.296,V")); } bool GpsNmeaSource::tryParse(string data) @@ -562,7 +689,7 @@ bool GpsNmeaSource::tryParse(string data) buffer += line; } - uint pos = buffer.find('G'); + std::string::size_type pos = buffer.find('G'); if(pos != std::string::npos && pos != 0) { @@ -575,6 +702,9 @@ bool GpsNmeaSource::tryParse(string data) /// we have a complete message. parse it! DebugOut(7)<<"Complete message: "<parse(buffer); + boost::algorithm::erase_all(buffer, "\n"); + boost::algorithm::erase_all(buffer, "\r"); + setValue(rawNmea, buffer); weFoundAMessage = true; buffer = ""; } @@ -582,11 +712,10 @@ bool GpsNmeaSource::tryParse(string data) { if(pos == 0 ) { - uint cs = buffer.find('*'); - if (cs != std::string::npos) + std::string::size_type cs = buffer.find('*'); + if (cs != std::string::npos && cs != buffer.length()-1) { - ///This means we have a false flag somewhere. - buffer = buffer.substr(cs+3); + buffer = buffer.substr(cs+(buffer.length() - cs)); } } } @@ -597,27 +726,9 @@ bool GpsNmeaSource::tryParse(string data) return weFoundAMessage; } -void GpsNmeaSource::unsubscribeToPropertyChanges(VehicleProperty::Property property) -{ - mRequests.remove(property); -} - -void GpsNmeaSource::addPropertySupport(VehicleProperty::Property property, Zone::Type zone) -{ - mSupported.push_back(property); - - std::list zones; - - zones.push_back(zone); - - PropertyInfo info(0, zones); - - propertyInfoMap[property] = info; -} - bool GpsNmeaSource::checksum(std::string sentence) { - if(sentence.empty() || sentence.length() < 4) + if(sentence.empty() || sentence.length() < 4 || sentence.find("*") == string::npos || sentence.find("*") >= sentence.length()-2) { return false; }