ϪfRdZddlmZddlZddlmZddlmZmZm Z ddl m Z ddl m Z ddlmZmZdd lmZmZmZdd lmZdd lmZdd lmZd ZdZdZdZdZdZdZ dZ!djExZ#\Z$Z%Z&e ejNGddZ(GddeZ)GddeZ*GddeZ+GddeZ,Gd d!Z-Gd"d#e-eZ.Gd$d%e-eZ/Gd&d'e-eZ0Gd(d)e-eZ1Gd*d+eZ2Gd,d-e d./Z3Gd0d1eZ4Gd2d3Z5Gd4d5e5eZ6Gd6d7e5eZ7dKd8Z8dLd9Z9dMd:Z:Gd;de5eZ<Gd?d@e5eZ=GdAdBe5eZ>GdCdDe5eZ?GdEdFe5eZ@GdGdHe5eZAGdIdJeZBy)Nz& Test cases for using NMEA sentences. ) annotationsN) attrgetter)CallableIterable TypedDict) implementer) NamedConstant)LiteralProtocol)base ipositioningnmea)Angles)MockPositioningReceiver)TestCasesA$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47sD$GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6As5$GPGSA,A,3,19,28,14,18,27,22,31,39,,,,,1.7,1.0,1.3*34s$GPHDT,038.005,T*3Bs'$GPGLL,4916.45,N,12311.12,W,225444,A*31s$GPGLL,3751.65,S,14507.36,E*77s;$GPGSV,1,1,11,03,03,111,00,04,15,270,00,06,01,010,00,,,,*4bs2$GPGSV,1,1,11,03,03,111,00,,,,,,,,,13,06,292,00*75s $GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74 $GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74 $GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D c(eZdZdZddZddZddZy)NMEATestReceiverzY An NMEA receiver for testing. Remembers the last sentence it has received. c$|jyN)clearselfs D/usr/lib/python3/dist-packages/twisted/positioning/test/test_nmea.py__init__zNMEATestReceiver.__init__3s  cd|_y)zq Forgets the received sentence (if any), by setting C{self.receivedSentence} to L{None}. NreceivedSentencers rrzNMEATestReceiver.clear6s ;?rc||_yrrrsentences rsentenceReceivedz!NMEATestReceiver.sentenceReceived=s (rNreturnNoner!znmea.NMEASentencer$r%)__name__ __module__ __qualname____doc__rrr"rrrr+s ?)rrc(eZdZdZddZddZddZy) CallbackTestsaO Tests if the NMEA protocol correctly calls its sentence callback. @ivar protocol: The NMEA protocol under test. @type protocol: L{nmea.NMEAProtocol} @ivar sentenceTypes: The set of sentence types of all sentences the test's sentence callback function has been called with. @type sentenceTypes: C{set} ct}tj||j|_t |_yr)rr NMEAProtocol_sentenceCallbackprotocolset sentenceTypesrreceivers rsetUpzCallbackTests.setUpLs.#%))(D4J4JK '*urcN|jj|jy)zC Remembers that a sentence of this type was fired. N)r3addtyper s rr0zCallbackTests._sentenceCallbackQs x}}-rcdgdgdgdgdgdgd}|jD]^\}}|D]T}|jj||j|j|h|jj V`y) zI The correct callbacks fire, and that *only* those fire. $GPGGA*56s $GPGLL*50s $GPGSA*42s $GPGSV*55s $GPHDT*4fs $GPRMC*4b)GPGGAGPGLLGPGSAGPGSVGPHDTGPRMCN)itemsr1 lineReceived assertEqualr3r)rsentencesByType sentenceType sentencesr!s rtest_callbacksCalledz"CallbackTests.test_callbacksCalledWs #^"^"^"^"^"^  (7'<'<'> + #L)% + **84  !3!3l^D""((* + +rNr#r&)r'r(r)r*r6r0rHr+rrr-r-As- . +rr-c(eZdZdZddZddZddZy)BrokenSentenceCallbackTestsz3 Tests for broken NMEA sentence callbacks. cbt}tj||j|_yr)rrr/r0r1r4s rr6z!BrokenSentenceCallbackTests.setUpps$#%))(D4J4JK rctd)z+ Raises C{AttributeError}. zERROR!!!)AttributeErrorr s rr0z-BrokenSentenceCallbackTests._sentenceCallbacktsZ((rc^|jj}|jt|dy)zt An C{AttributeError} in the sentence callback of an C{NMEAProtocol} doesn't get swallowed. r;N)r1rC assertRaisesrM)rrCs r"test_dontSwallowCallbackExceptionsz>BrokenSentenceCallbackTests.test_dontSwallowCallbackExceptionszs% }}11  ., ErNr#r&)r'r(r)r*r6r0rPr+rrrJrJksL) FrrJc eZdZdZddZddZy) SplitTestsz- Checks splitting of NMEA sentences. cVtjd}|j|gdy)zH An NMEA sentence with a checksum gets split correctly. s$GPGGA,spam,eggs*00sGPGGAsspamseggsNr_splitrDr splitSentences rtest_withChecksumzSplitTests.test_withChecksums$ $:;  (DErcVtjd}|j|gdy)zK An NMEA sentence without a checksum gets split correctly. s$GPGGA,spam,eggs*rTNrUrWs rtest_noCheckumzSplitTests.test_noCheckums$ $89  (DErNr#)r'r(r)r*rYr[r+rrrRrRsFFrrRc(eZdZdZddZddZddZy) ChecksumTestsz4 NMEA sentence checksum verification tests. c6tjty)z? Sentences with valid checksums get validated. Nr_validateChecksumr<rs r test_validzChecksumTests.test_valids u%rc<tjtddy)zA Sentences with missing checksums get validated. Nr_rs r test_missingzChecksumTests.test_missings uSbz*rctj}tjd\}}dt |ddzfz}|dz|zg}|D]#}|j t j||%y)zw Sentences with a bad checksum raise L{base.InvalidChecksum} when attempting to validate them. *s%dN)rr`r<splitintrOr InvalidChecksum)rvalidate bareSentencechecksum badChecksumrGss r test_invalidzChecksumTests.test_invalidsv ))!&T!2 hs8R01466 !D(;67  AA   d22Ha @ ArNr#)r'r(r)r*rardrqr+rrr]r]s& + Arr]ceZdZdZddZy)NMEAReceiverSetupaG A mixin for tests that need an NMEA receiver (and a protocol attached to it). @ivar receiver: An NMEA receiver that remembers the last sentence. @type receiver: L{NMEATestReceiver} @ivar protocol: An NMEA protocol attached to the receiver. @type protocol: L{twisted.positioning.nmea.NMEAProtocol} cjt|_tj|j|_y)z+ Sets up an NMEA receiver. N)rr5rr/r1rs rr6zNMEAReceiverSetup.setUps$)* ))$--8 rNr#)r'r(r)r*r6r+rrrsrss 9rrsc(eZdZdZddZddZddZy)GSVSequenceTestsz8 Tests for the interpretation of GSV sequences. c|jjt|jj}|J|j |j |j|jy)zO The first sentence in a GSV sequence is correctly identified. N) r1rC GPGSV_FIRSTr5r assertTrue_isFirstGSVSentence assertFalse_isLastGSVSentencer s rtest_firstSentencez#GSVSequenceTests.test_firstSentences] "";/==11### 4467 4467rc|jjt|jj}|J|j |j |j |jy)z A sentence in the middle of a GSV sequence is correctly identified (as being neither the last nor the first). N)r1rC GPGSV_MIDDLEr5rr{rzr|r s rtest_middleSentencez$GSVSequenceTests.test_middleSentences_ ""<0==11### 5578 4467rc|jjt|jj}|J|j |j |j|jy)zN The last sentence in a GSV sequence is correctly identified. N) r1rC GPGSV_LASTr5rr{rzryr|r s rtest_lastSentencez"GSVSequenceTests.test_lastSentences] "":.==11### 5578 3356rNr#)r'r(r)r*r}rrr+rrrvrvs 8 8 7rrvc4eZdZdZ ddZddZddZy)BogusSentenceTestszK Tests for verifying predictable failure for bogus NMEA sentences. cR|j||jj|y)a= Asserts that the protocol raises C{exceptionClass} when it receives C{sentence}. @param exceptionClass: The exception class expected to be raised. @type exceptionClass: C{Exception} subclass @param sentence: The (bogus) NMEA sentence. @type sentence: C{str} N)rOr1rC)rexceptionClassr!s rassertRaisesOnSentencez)BogusSentenceTests.assertRaisesOnSentences  .$--*D*DhOrc0|jtdy)z` Receiving a well-formed sentence of unknown type raises C{ValueError}. s $GPBOGUS*5bN)r ValueErrorrs rtest_raiseOnUnknownSentenceTypez2BogusSentenceTests.test_raiseOnUnknownSentenceTypes ##J?rcD|jtjdy)zP Receiving a malformed sentence raises L{base.InvalidSentence}. GPBOGUSN)rr InvalidSentencers rtest_raiseOnMalformedSentencesz1BogusSentenceTests.test_raiseOnMalformedSentences s ##D$8$8)DrN)rtype[Exception]r!z str | bytesr$r%r#)r'r(r)r*rrrr+rrrrs4 P- P9D P  P@ErrceZdZdZddZy)NMEASentenceTestsz1 Tests for L{nmea.NMEASentence} objects. ctdfg}|D]Q\}}|jj||jj}|j t ||Sy)zI The C{repr} of L{nmea.NMEASentence} objects is correct. aXN)r>r1rCr5rrDrepr)rsentencesWithExpectedReprr! expectedReprreceiveds r test_reprzNMEASentenceTests.test_reprse  % !*'@ ; "Hl MM & &x 0}}55H   T(^\ : ;rNr#)r'r(r)r*rr+rrrrs ;rrcXeZdZdZd dZd dZd dZd dZd dZd dZ d dZ d d Z d d Z y ) ParsingTestsz Tests if raw NMEA sentences get parsed correctly. This doesn't really involve any interpretation, just turning ugly raw NMEA representations into objects that are more pleasant to work with. c|jj||jj}|J|j ||j y)z Passes a sentence to the protocol and gets the parsed sentence from the receiver. Then verifies that the parsed sentence contains the expected data. N)r1rCr5rrD _sentenceData)rr!expectedrs r _parserTestzParsingTests._parserTest@sG ""8,==11### 8#9#9:rc Nddddddddd d d d d }|jt|y)z: A full RMC sentence is correctly parsed. rA4807.038N 01131.000Ez003.1Wz022.4123519230394z084.4A) r9 latitudeFloatlatitudeHemispherelongitudeFloatlongitudeHemispheremagneticVariationmagneticVariationDirection speedInKnots timestamp datestamp trueHeadingdataModeN)rrArrs r test_fullRMCzParsingTests.test_fullRMCKsA '"%)#&!(*-#!!"   )rcPdddddddddd d d d d }|jt|y)z: A full GGA sentence is correctly parsed. r<545.4M46.9z0.9rrrr08r1) r9altitude altitudeUnitsheightOfGeoidAboveWGS84heightOfGeoidAboveWGS84UnitshorizontalDilutionOfPrecisionrrrrnumberOfSatellitesSeenr fixQualityN)rr<rs r test_fullGGAzParsingTests.test_fullGGA_sD  '-,/-2'"%)#&&*!  )rcDdddddddd}|jt|y ) z: A full GLL sentence is correctly parsed. r=z4916.45rz12311.12r225444r)r9rrrrrrN)rr=rs r test_fullGLLzParsingTests.test_fullGLLts2 &"%(#&!  )rc@dddddd}|jt|y)z= A partial GLL sentence is correctly parsed. r=z3751.65Sz14507.36r)r9rrrrN)r GPGLL_PARTIALrs rtest_partialGLLzParsingTests.test_partialGLLs, &"%(#&   1rciddddddddd d d d d ddddddddddddddddddddd d d d d!}|jt|y")#z: A full GSV sentence is correctly parsed. r9r?GSVSentenceIndexrnumberOfGSVSentences3r11 azimuth_0111 azimuth_1270 azimuth_2010 azimuth_3292 elevation_003 elevation_115 elevation_201 elevation_306satellitePRN_0satellitePRN_104satellitePRN_2satellitePRN_313signalToNoiseRatio_000)signalToNoiseRatio_1signalToNoiseRatio_2signalToNoiseRatio_3N)rrxrs r test_fullGSVzParsingTests.test_fullGSVs G   #C  %d           4  4  4  4  d  d  d d! " #D# $%)$($() , h/rcidddddddddd d d d d dddddddddddddddddd}|jt|y) z= A partial GSV sentence is correctly parsed. r9r?rrrrrr067r311r244r42r14r05r22r24r27rr43rrN)rrrs rtest_partialGSVzParsingTests.test_partialGSVs G   #C  %d         4  4  4  d  d  d  #D  #D #D! $ X.rc:ddd}|jt|y)z: A full HDT sentence is correctly parsed. r@z038.005)r9rN)rr@rs r test_fullHDTzParsingTests.test_fullHDTs# $  )rcRddddddddd d d d d dd}|jt|y)z= A typical GSA sentence is correctly parsed. r>rr1928r18rr3139z1.7z1.0z1.3)r9rfixTypeusedSatellitePRN_0usedSatellitePRN_1usedSatellitePRN_2usedSatellitePRN_3usedSatellitePRN_4usedSatellitePRN_5usedSatellitePRN_6usedSatellitePRN_7positionDilutionOfPrecisionrverticalDilutionOfPrecisionN)rr>rs rtest_typicalGSAzParsingTests.test_typicalGSAsG "&"&"&"&"&"&"&"&+0-2+0  )rN)r!bytesrdict[str, str]r$r%r#) r'r(r)r*rrrrrrrrr r+rrrr8s4 ;*(** * 208/0**rrc0eZdZdZddZddZddZddZy) FixUnitsTestsz Tests for the generic unit fixing method, L{nmea.NMEAAdapter._fixUnits}. @ivar adapter: The NMEA adapter. @type adapter: L{nmea.NMEAAdapter} c\tjtj|_yrr NMEAAdapterr BasePositioningReceiveradapterrs rr6zFixUnitsTests.setUp''(D(D(FG rcGdd}||j_|jjdd|j|jjddy) zv Tests that when no C{valueKey} is provided, C{unitKey} is used, minus C{"Units"} at the end. ceZdZdZddZy)3FixUnitsTests.test_noValueKey..FakeSentencezJ A fake sentence that just has a "foo" attribute. cd|_y)Nrh)foors rrz.FakeSentence.__init__s rNr#r'r(r)r*rr+rr FakeSentencers   rrfooUnitsr)unitKeyunitrrhNrcurrentSentence _fixUnitsassertNotEqualrrrs rtest_noValueKeyzFixUnitsTests.test_noValueKeysR   (4~ $ z< DLL66u=qArcGdd}||j_|jjd|j|jjddy)z Tests that if a unit key is provided but the unit isn't, the unit is automatically determined from the unit key. ceZdZdZddZy)9FixUnitsTests.test_unitKeyButNoUnit..FakeSentencezX A fake sentence that just has "foo" and "fooUnits" attributes. c d|_d|_y)Nrhr)rrrs rrzBFixUnitsTests.test_unitKeyButNoUnit..FakeSentence.__init__ s # rNr#rr+rrrr's   $rrr)rrrhNrr#s rtest_unitKeyButNoUnitz#FixUnitsTests.test_unitKeyButNoUnitsP  $ $(4~ $ z2 DLL66u=qArc\|jt|jjdy)z Tests that when a unit is specified but neither C{valueKey} nor C{unitKey} is provided, C{ValueError} is raised. K)rN)rOrrr!rs rtest_noValueKeyAndNoUnitKeyz)FixUnitsTests.test_noValueKeyAndNoUnitKeys# *dll&<&<3GrNr#)r'r(r)r*r6r$r)r,r+rrrrsHB$B&HrrcheZdZUded<ded<ded<ded<ded <ded <d ed <d ed<ded<y)_Statez datetime.time_timez datetime.date_datezbase.Coordinatelatitude longitudez base.Altituderrz base.Speedspeedz base.Headingheadingzbase.PositionError positionErrorN)r'r(r)__annotations__r+rrr.r.s8  **  %%rr.F)totalc:eZdZeddZddZ ddZy)_FixerTestMixinBasecyrr+rs rrz_FixerTestMixinBase.adapter*s rcyrr+)rabs rrDz_FixerTestMixinBase.assertEqual.s rcyrr+)r exceptionfs rrOz _FixerTestMixinBase.assertRaises1s rN)r$znmea.NMEAAdapter)r<objectr=rAr$rA)r?rr@zCallable[[], object]r$rA)r'r(r)propertyrrDrOr+rrr9r9)s6     ( -A  rr9c8eZdZdZddZ d ddZy)FixerTestMixinz Mixin for tests for the fixers on L{nmea.NMEAAdapter} that adapt from NMEA-specific notations to generic Python objects. @ivar adapter: The NMEA adapter. @type adapter: L{nmea.NMEAAdapter} c\tjtj|_yrrrs rr6zFixerTestMixin.setUp@rrNctj|dfd }|.|jjj|nj ||jj y)a A generic adapter fixer test. Creates a sentence from the C{sentenceData} and sends that to the adapter. If C{exceptionClass} is not passed, this is assumed to work, and C{expected} is compared with the adapter's internal state. Otherwise, passing the sentence to the adapter is checked to raise C{exceptionClass}. @param sentenceData: Raw sentence content. @type sentenceData: C{dict} mapping C{str} to C{str} @param expected: The expected state of the adapter. @type expected: C{dict} or L{None} @param exceptionClass: The exception to be raised by the adapter. @type exceptionClass: subclass of C{Exception} c<jjyr)rr"r srreceiveSentencez2FixerTestMixin._fixerTest..receiveSentence]s LL ) )( 3rNr#)r NMEASentencerDr_staterOr)r sentenceDatarrrHr!s` @r _fixerTestzFixerTestMixin._fixerTestCsb0$$\2 4  !     T\\00( ;   no > rr#)NN) rr9rKr rz _State | Nonerztype[Exception] | Noner$r%)r'r(r)r*r6rLr+rrrDrD7sHH #'15 #!#$# #/ #  #rrDc eZdZdZddZddZy)TimestampFixerTestszL Tests conversion from NMEA timestamps to C{datetime.time} objects. cbddi}dtjdddi}|j||y)z< A simple timestamp is converted correctly. r123456r/ "8N)datetimetimerL)rdatars r test_simplezTimestampFixerTests.test_simplens3X&#X]]2r2%>? h'rcHd}|D]}|jd|ity)z: A broken timestamp raises C{ValueError}. )993456129956123499rrNrLr)r badTimestampsts r test_brokenzTimestampFixerTests.test_brokenvs/5  IA OO[!,ZO H IrNr#)r'r(r)r*rWr`r+rrrNrNis(IrrNc4eZdZddZddZddZddZddZy)DatestampFixerTestscP|j|jjdy)z5 The default year threshold is 1980. iN)rDr yearThresholdrs rtest_defaultYearThresholdz-DatestampFixerTests.test_defaultYearThresholds 33T:rcbdtjddd}}|jd|id|iy)z Dates before the threshold are interpreted as being in the century after the threshold. (Since the threshold is the earliest possible date.) 010115irhrr0NrTdaterLr datestringris rtest_beforeThresholdz(DatestampFixerTests.test_beforeThresholds1 $X]]4A%>D  j1GT?Crcbdtjddd}}|jd|id|iy)zr Dates after the threshold are interpreted as being in the same century as the threshold. 010195irhrr0Nrhrjs rtest_afterThresholdz'DatestampFixerTests.test_afterThresholds1 $X]]4A%>D  j1GT?Crc6|jddity)zQ A datestring with an invalid month (> 12) raises C{ValueError}. r011301r\Nr]rs rtest_invalidMonthz%DatestampFixerTests.test_invalidMonths h/ Krch|jddit|jddity)zy A datestring with an invalid day (more days than there are in that month) raises C{ValueError}. r320101r\300201Nr]rs rtest_invalidDayz#DatestampFixerTests.test_invalidDays. h/ K h/ KrNr#)r'r(r)rerlrorrrvr+rrrbrbs; DDL Lrrbcd||fzS)a^ Builds an NMEA float representation for a given angle in degrees and decimal minutes. @param degrees: The integer degrees for this angle. @type degrees: C{int} @param minutes: The decimal minutes value for this angle. @type minutes: C{float} @return: The NMEA float representation for this angle. @rtype: C{str} z%i%0.3fr+)degreesminutess r _nmeaFloatrzs ) ))rc|dvrdSdS)a8 Return the sign of a coordinate. This is C{1} if the coordinate is in the northern or eastern hemispheres, C{-1} otherwise. @param hemisphere: NMEA shorthand for the hemisphere. One of "NESW". @type hemisphere: C{str} @return: The sign of the coordinate value. @rtype: C{int} NErhr+ hemispheres r_coordinateSignrsd"1**rcJ|dvrtjStjS)ao Return the type of a coordinate. This is L{Angles.LATITUDE} if the coordinate is in the northern or southern hemispheres, L{Angles.LONGITUDE} otherwise. @param hemisphere: NMEA shorthand for the hemisphere. One of "NESW". @type hemisphere: C{str} @return: The type of the coordinate (L{Angles.LATITUDE} or L{Angles.LONGITUDE}) NS)rLATITUDE LONGITUDEr~s r_coordinateTypers )D06??Ff6F6FFrc@eZdZdZd dZd dZd dZd dZd dZd dZ y) CoordinateFixerTestszO Tests turning NMEA coordinate notations into something more pleasant. c~ddd}dtjdtji}|j ||y)zg NMEA coordinate representations in the northern hemisphere convert correctly. 1030.000rrrr1%@Nr CoordinaterrrLrrKstates r test_northzCoordinateFixerTests.test_norths5 *43O #T__T6??%KL  e,rc~ddd}dtjdtji}|j ||y)zg NMEA coordinate representations in the southern hemisphere convert correctly. rrrr1%Nrrs r test_southzCoordinateFixerTests.test_souths5 *43O #T__UFOO%LM  e,rc~ddd}dtjdtji}|j ||y)zf NMEA coordinate representations in the eastern hemisphere convert correctly. rrrrr2rNr rrrrLrs r test_eastzCoordinateFixerTests.test_easts7 +5SQ $doodFz=CoordinateFixerTests.test_badHemisphereSign.. s$,,99-HrN)rOr)rgetSigns` rtest_badHemisphereSignz+CoordinateFixerTests.test_badHemisphereSigns I *g.rNr#) r'r(r)r*rrrrrrr+rrrrs&----A/rrc eZdZdZddZddZy)AltitudeFixerTestszO Tests that NMEA representations of altitudes are correctly converted. cd\}}tjt|}|j||it |y)zo The NMEA representation of an altitude (above mean sea level) is correctly converted. )rr)rNr AltitudefloatrLr.rkeyvaluers rtest_fixAltitudez#AltitudeFixerTests.test_fixAltitudes6 ) U==u. e fh&?@rcd\}}tjt|}|j||it |y)z The NMEA representation of an altitude of the geoid (above the WGS84 reference level) is correctly converted. )rr)rNrrs rtest_heightOfGeoidAboveWGS84z/AltitudeFixerTests.test_heightOfGeoidAboveWGS84s6 7 U==u. e fX&NOrNr#)r'r(r)r*rrr+rrrrsAPrrceZdZdZddZy)SpeedFixerTestszL Tests that NMEA representations of speeds are correctly converted. cd\}}tjt|tjz}|j ||it |y)z` Speeds reported in knots correctly get converted to meters per second. )r10)r3N)r Speedr MPS_PER_KNOTrLr.)rrrr3s rtest_speedInKnotsz!SpeedFixerTests.test_speedInKnots.sA * U 5<$*;*;;< e f5&9:rNr#)r'r(r)r*rr+rrrr)s ;rrc(eZdZdZddZddZddZy)VariationFixerTestsz Tests if the absolute values of magnetic variations on the heading and their sign get combined correctly, and if that value gets combined with a heading correctly. cd\}}tjjdt|z}||d}|j |d|iy)z? Tests westward (negative) magnetic variation. )1.34rr}variationValuerrr4Nr Heading fromFloatsrrLr variation directionr4rKs rrzVariationFixerTests.test_west?sQ + 9,,))eI>N9N)O!**3  y'&:;rcd\}}tjjt|}||d}|j |d|iy)z? Tests eastward (positive) magnetic variation. )rrrrr4Nrrs rrzVariationFixerTests.test_eastLsL + 9,,))y9I)J!**3  y'&:;rcd\}}}|||d}tjjt|t|}|j |d|iy)zH Variation values get combined with headings correctly. )z123.12rr)rrrrr4Nr)rrrrrKr4s rtest_withHeadingz$VariationFixerTests.test_withHeadingYs`-B) Y &!**3 ,,)) + uY/?*   y'&:;rNr#)r'r(r)r*rrrr+rrrr8s < < rr9rrrN)rrr GPGSAFixTypes GSA_NO_FIXrrs rtest_badGSADataModez#InvalidFixTests.test_badGSADataModes?33::))44  \*rcddtjjtjjd}|j |y)z GSA sentence data is not used when the fix claims to be valid (albeit only 2D), but the data mode says the data is void. Some GPSes do this, unfortunately, and that means you shouldn't use the data. r>rrN)rrrr GSA_2D_FIXrrs rtest_badGSAFixTypez"InvalidFixTests.test_badGSAFixTypes?3388))44  \*rcddtjjtjjd}|j |y)zj GSA sentence data is not use when neither the fix nor the data mode is any good. r>rrN)rrrrrrrs rtest_badGSADataModeAndFixTypez-InvalidFixTests.test_badGSADataModeAndFixTypes? 3388))44  \*rN)rKr r$r%r#) r'r(r)r*rrrrrrr+rrrrs%* + + + + +rrceZdZdZddZddZ d ddZddZddZddZ dd Z dd Z dd Z dd Z dd ZddZddZddZddZddZy)NMEAReceiverTestsz& Tests for the NMEA receiver. ct|_tj|j|_tj |j|_yr)rr5rrrr/r1rs rr6zNMEAReceiverTests.setUps8/1 '' 6 ))$,,7 rc|jjthd}|jt |j j j||j j|j|jji|jjtdh}|jt |j j j|y)z If the current sentence does not contain any new fields for a particular callback, that callback is not called; even if all necessary information is still in the state from one or more previous messages. >altitudeReceivedpositionReceivedpositionErrorReceivedheadingReceivedN) r1rCr<rDr2r5calledkeysrr"rrJr@)rgpggaCallbacksgphdtCallbackss r1test_onlyFireWhenCurrentSentenceHasNewInformationzCNMEAReceiverTests.test_onlyFireWhenCurrentSentenceHasNewInformations ""5)  T]]116689>J  DLL//4 ""5)+, T]]116689>JrNcR|D]}|jj||jjj }|j t |t ||||jj|jjy)a A generic test for NMEA receiver behavior. @param sentences: The sequence of sentences to simulate receiving. @type sentences: iterable of C{str} @param expectedFired: The names of the callbacks expected to fire. @type expectedFired: iterable of C{str} @param extraTest: An optional extra test hook. @type extraTest: nullary callable N) r1rCr5rrrDr2rr)rrG expectedFired extraTestr! actuallyFireds r _receiverTestzNMEAReceiverTests._receiverTest"s " 1H MM & &x 0 1 ,,113  ]+S-?@  K  rchtgtz}ddg}dddfd }j|||y)zJ The positioning error is updated across multiple states. rbeaconInformationReceivedc>tttd|S)N identifier)sortedmapr)beaconss r_getIdentifierszONMEAReceiverTests.test_positionErrorUpdateAcrossStates.._getIdentifiersEs#j6@A Arcjjd}|j}gd}j|||j}j|gdy)NbeaconInformation)  rg)rrrrr)rrJ seenBeaconsrD usedBeacons)r seenIdentifiersrusedIdentifiersr rs rcheckBeaconInformationzVNMEAReceiverTests.test_positionErrorUpdateAcrossStates..checkBeaconInformationHsc $ 3 34G H -.?.K.KLO@H   _h 7-.?.K.KLO   _.B CrN)r zIterable[base.Satellite]r$z list[int]r#)r> GPGSV_SEQr)rrGcallbacksFiredrr s` @r$test_positionErrorUpdateAcrossStatesz6NMEAReceiverTests.test_positionErrorUpdateAcrossStates>s=Gi' 13NO B D 9n6LMrcLtg}dg}dfd }j|||y)z A GSV sentence with empty entries in any position does not mean that entries in subsequent positions of the same GSV sentence are ignored. rcjjd}|j}jt |dj d|Dcgc]}|j c}ycc}w)Nr r)rrJrrDlenassertInr)r rr=rs rrzENMEAReceiverTests.test_emptyMiddleGSV..checkBeaconInformation`sY $ 3 34G H +77K   S-q 1 MM"[Aq||A BAsA- Nr#GPGSV_EMPTY_MIDDLEr)rrGrrs` rtest_emptyMiddleGSVz%NMEAReceiverTests.test_emptyMiddleGSVXs0 (( 56 C 9n6LMrc>tg}gd}|j||y)z A sequence of GGA sentences fires C{positionReceived}, C{positionErrorReceived} and C{altitudeReceived}. )rrrN)r<rrrGrs rtest_GGASentencesz#NMEAReceiverTests.test_GGASentencesis$ G   9n5rctjddd|jjd<tg}gd}|j ||y)z When receiving a GPGGA sentence and a date was already in the state, the new time (from the GPGGA sentence) is combined with that date. irhr0)rrr timeReceivedN)rTrirrJr<rr)s rtest_GGAWithDateInStatez)NMEAReceiverTests.test_GGAWithDateInStatewsE (0}}T1a'@ G$G   9n5rc>tg}gd}|j||y)z A sequence of RMC sentences fires C{positionReceived}, C{speedReceived}, C{headingReceived} and C{timeReceived}. )r speedReceivedrr,N)rArr)s rtest_RMCSentencesz#NMEAReceiverTests.test_RMCSentencess$ G   9n5rc`tttg}dg}dfd }j|||y)zb A complete sequence of GSV sentences fires C{beaconInformationReceived}. rcRjdjjy)N_partialBeaconInformation) assertNotInrrJrsrcheckPartialInformationzDNMEAReceiverTests.test_GSVSentences..checkPartialInformations   8$,,:M:M NrNr#)rxrrr)rrGrr5s` rtest_GSVSentencesz#NMEAReceiverTests.test_GSVSentencess4 !, ; 56 O 9n6MNrc8tg}|j|dgy)z A complete sequence of GSV sentences with empty entries in the middle still fires C{beaconInformationReceived}. rNr%rrGs r"test_emptyMiddleEntriesGSVSequencez4NMEAReceiverTests.test_emptyMiddleEntriesGSVSequences ((  9'B&CDrc4tg}|j|y)zV An incomplete sequence of GSV sentences does not fire any callbacks. N)rxrr8s rtest_incompleteGSVSequencez,NMEAReceiverTests.test_incompleteGSVSequences!M  9%rc8tg}|j|dgy)z The parser does not fail badly when the sequence consists of only one sentence (but is otherwise complete). rN) GPGSV_SINGLErr8s rtest_singleSentenceGSVSequencez0NMEAReceiverTests.test_singleSentenceGSVSequences "N  9'B&CDrcBttg}|j|dgy)z9 GLL sentences fire C{positionReceived}. rN)rr=rr8s rtest_GLLSentencesz#NMEAReceiverTests.test_GLLSentencess"#E*  9'9&:;rc8tg}|j|dgy)z8 HDT sentences fire C{headingReceived}. rN)r@rr8s rtest_HDTSentencesz#NMEAReceiverTests.test_HDTSentencessG  9'8&9:rcXttg}gd}dfd }j|||y)zA A mix of sentences fires the correct callbacks. )rr/rrr,rctjdddddd}jjjd|y)NirrQ#rrU)rTrDrrJ)expectedDateTimers r checkTimez8NMEAReceiverTests.test_mixedSentences..checkTimes>'00q"b"bI    T\\008:J KrNr#)rAr<r)rrGrrHs` rtest_mixedSentencesz%NMEAReceiverTests.test_mixedSentencess/EN   L 9ni@rcptgtztttgz}gd}|j ||y)a# Sends an entire gamut of sentences and verifies the appropriate callbacks fire. These are more than you'd expect from your average consumer GPS device. They have most of the important information, including beacon information and visibility. )rrr/rr,rrN)r>rrAr<r=rr)s rtest_lotsOfMixedSentencesz+NMEAReceiverTests.test_lotsOfMixedSentencess5Gi'5%*??   9n5rr#)r+N)rGzIterable[bytes]rz Iterable[str]rzCallable[[], None] | Noner$r%)r'r(r)r*r6rrrr'r*r-r0r6r9r;r>r@rBrIrKr+rrrrs8 K:(*/3 "%-   8N4N" 66$ 6 OE&E<;A(6rr)rxrjryrr$str)rrLr$zLiteral[1, -1])rrLr$r )Cr* __future__rrToperatorrtypingrrrzope.interfacer constantlyr r r twisted.positioningr r rtwisted.positioning.baser!twisted.positioning.test.receiverrtwisted.trial.unittestrr<rAr>r@r=rr=r&rirrxrr INMEAReceiverrr-rJrRr]rsrvrrrrr.r9rDrNrbrzrrrrrrrrrrr+rrrWs #00&$$88+E+ MO@21 M J  EG   \ ' '())))*'+H'+TF(F0FF(AHA@99&%7((%7PE*HED!;)8!;Hj*$hj*Z5HH5Hp &Ye &  (  //dI.(I.$L.($LN * + G 8/>88/vPP0 ;nh ;.<.(.