1
2
3
4 __version__ = '$Revision: 6041 $'.split()[1]
5 __date__ = '$Date: 2007-04-23 11:22:18 -0400 (Mon, 23 Apr 2007) $'.split()[1]
6 __author__ = ''
7
8 __doc__='''
9 Create AIS NMEA strings for NOAA CO-OPS tide data. Try to pull all the
10 water level messages for a station over a long time period
11
12 fugly code
13
14 @requires: U{Python<http://python.org/>} >= 2.4
15 @requires: U{epydoc<http://epydoc.sourceforge.net/>} >= 3.0beta1
16 @requires: U{lxml}
17 @requires: U{soappy}
18
19 @author: U{'''+__author__+'''<http://schwehr.org/>}
20 @version: ''' + __version__ +'''
21 @copyright: 2007
22 @var __date__: Date of last svn commit
23 @undocumented: __version__ __author__ __doc__ parser success
24 @since: 2007-Apr-23
25 @status: Intial working version. Still needs development
26 @organization: U{CCOM<http://ccom.unh.edu/>}
27
28 @license: GPL v2
29
30 '''
31
32 import sys
33 from SOAPpy import SOAPProxy
34
35
36
37
38 import ais.waterlevel as wl_ais
39 import ais.ais_msg_8 as msg8_ais
40 from ais.nmea import buildNmea
41 import noaadata.stations as Stations
42 from decimal import Decimal
43 import calendar
44
45 stations = Stations.ActiveStations(forceCache=True)
46
47 url ='http://opendap.co-ops.nos.noaa.gov/axis/services/WaterLevelRawSixMin'
48 namespace='urn:WaterLevelRawSixMin'
49
50 daysPerMon=[-1,31,28,31,30,31,30,31,31,30,31,30,31]
51 monthLUT = {
52 'Jan':1,
53 'Feb':2,
54 'Mar':3,
55 'Apr':4,
56 'May':5,
57 'Jun':6,
58 'Jul':7,
59 'Aug':8,
60 'Sep':9,
61 'Oct':10,
62 'Nov':11,
63 'Dec':12
64 }
66 '''
67 Splits a noaa utc time into fields that are more usable.
68
69 #>>> splitNoaaDateTime('Jan 4 2007 4:36PM')
70 #(2007,1,4,16,36)
71
72 >>> splitNoaaDateTime('2007-01-31 00:06:00.0')
73 (2007,1,13,00,06)
74
75 '''
76 fields = datetimeStr.split()
77 yr,mo,da=fields[0].split('-')
78
79 hr,mi,sec, = fields[1].split(':')
80
81 return yr,mo,da,hr,mi
82
84 '''
85 Return one long NMEA string. This will be oversized for the nmea spec.
86 '''
87
88 payloadBits = noaawaterlevel2aisBits(stationID,mmsi=mmsi,datum=datum,wl=wl,verbose=verbose,debug=debug)
89
90 nmeaStr = buildNmea(payloadBits)
91
92 ts=wl.timeStamp
93 fields = ts.split()
94 yr,mo,da=fields[0].split('-')
95 hr,mi,sec = fields[1].split(':')
96 sec=sec.split('.')[0]
97 if sec[0]=='0': sec=sec[1:]
98 timestamp = calendar.timegm((int(yr),int(mo),int(da),int(hr),int(mi),int(sec)))
99 nmeaStr += ',r'+str(mmsi)+','+str(timestamp)
100
101 return nmeaStr
102
104 '''
105 Return an AIS string of the latest waterlevel.
106 @param stationID: which station to query (e.g. '8639348')
107 @type stationID: str
108 @param wl: one entry from a soap query
109 @param verbose: Set to true for print messages
110 @param debug: Do not actually fetch any real data (fast for debugging)
111 @param datum: MSL,MLLW
112
113 @return: bits for the message payload
114 @rtype: BitVector
115 '''
116
117
118 if verbose: print 'water level dict:',wl
119
120
121
122 params = {}
123
124
125
126 params['RepeatIndicator'] = 1
127 params['UserID'] = int(mmsi)
128
129
130
131
132 yearDummy, monthDummy, dayDummy, hourDummy, minDummy = splitNoaaDateTimeSoap(wl.timeStamp)
133 params['month'] = int(monthDummy)
134 params['day'] = int(dayDummy)
135 params['hour'] = int(hourDummy)
136 params['min'] = int(minDummy)
137 params['sec'] = 0
138 params['stationid'] = str(stationID)
139 station = stations.getStation(str(stationID))
140 params['longitude'] = Decimal(str(station.getLon()))
141 params['latitude'] = Decimal(str(station.getLat()))
142 params['waterlevel'] = int(float(wl.WL)*100)
143 if verbose:
144 print params['waterlevel'], wl.WL
145 params['datum'] = int(wl_ais.datumEncodeLut[datum])
146 params['sigma'] = float(wl.sigma)
147 params['o'] = int(wl.O)
148
149 if params['o']<0:
150 print 'wl.O',wl.O, params['o'],'FIX: what does this mean? Forcing O to be positive'
151 params['o'] = -params['o']
152
153
154 if bool(wl.L): params['levelinferred'] = True
155 else: params['levelinferred'] = False
156 if bool(wl.F): params['flat_tolerance_exceeded'] = True
157 else: params['flat_tolerance_exceeded'] = False
158 if bool(wl.R): params['rate_tolerance_exceeded'] = True
159 else: params['rate_tolerance_exceeded'] = False
160 params['temp_tolerance_exceeded'] = False
161 params['expected_height_exceeded'] = False
162 params['link_down'] = False
163
164 if verbose:
165 wl_ais.printFields(params)
166 print 'params dump:'
167 for item in params.keys():
168 print ' ',item,params[item]
169
170 return wl_ais.encode(params)
171
172 if __name__=='__main__':
173
174 from optparse import OptionParser
175
176 parser = OptionParser(usage="%prog [options] [file1] [file2] ...",
177 version="%prog "+__version__+' ('+__date__+')')
178
179 parser.add_option('-y','--year',dest='year',default='2006'
180 ,help='Year of the water levels (Default is Money Point) [default: %default]')
181
182 parser.add_option('-m','--month-start',dest='monthStart',default='1',type='int'
183 ,help='Starting month (Default is Money Point) [default: %default]')
184 parser.add_option('-M','--month-end',dest='monthEnd',default='12',type='int'
185 ,help='Ending month (Default is Money Point) [default: %default]')
186
187 parser.add_option('-s','--station',dest='station',default='8639348'
188 ,help='Specify the station to print. (Default is Money Point) [default: %default]')
189 parser.add_option('--mmsi',dest='mmsi',default='338040883'
190 ,help='Specify the station to print. (Default MMSI belongs to Kurt) [default: %default]')
191 parser.add_option('-o','--output',dest='outputFileName',default=None,
192 help='Name of the python file to write [default: stdout]')
193
194
195 parser.add_option('-d','--datum',dest='datum',default='MSL',
196 help='What reference datum to use for the water levels [default: %default]')
197
198
199 parser.add_option('-v','--verbose',dest='verbose',default=False,action='store_true',
200 help='Make the test output verbose')
201
202 (options,args) = parser.parse_args()
203
204 verbose = options.verbose
205 stationId=options.station
206 mmsi = options.mmsi
207
208
209
210 o=sys.stdout
211 if options.outputFileName!=None:
212 o = file(options.outputFileName,'w')
213
214
215 server = SOAPProxy(url,namespace)
216
217
218
219
220
221
222
223
224
225
226 for mon in range(options.monthStart,options.monthEnd+1):
227
228 beginDate=str(options.year)+('%02d' % mon )+'01'
229 endDate=str(options.year)+('%02d' % mon )+str(daysPerMon[mon])
230
231 print beginDate,'...', endDate
232 response = server.getWaterLevelRawSixMin(stationId=str(stationId)
233 ,beginDate=beginDate,endDate=endDate,
234 datum=options.datum
235 ,unit=0
236 ,timeZone=0)
237 for wl in response.item:
238
239
240 try:
241 wlStr = noaawaterlevel2aisMsg8Nmea(stationId,mmsi,datum=options.datum,wl=wl)
242 except:
243 print 'ERROR: something with this line'
244 print wl
245 continue
246
247 o.write( wlStr + '\n' )
248
249 if False:
250 beginDate='20070401'
251 endDate='20070401'
252
253
254 response = server.getWaterLevelRawSixMin(stationId=str(stationId),beginDate=beginDate,endDate=endDate,datum=options.datum,unit=0,timeZone=0)
255
256
257 for wl in response.item:
258
259 wlStr = noaawaterlevel2aisMsg8Nmea(stationId,mmsi,datum=options.datum,wl=wl)
260 if verbose:
261 print wlStr
262 o.write( wlStr + '\n' )
263