Campbell 4WPB100 Specifications

GlacioBasis Manual
Revision 1 (3rd November 2009)
Compiled by Michele Citterio, GEUS
Table of contents
Table of contents.......................................................................................................... 1
Preface........................................................................................................................... 2
Revisions history......................................................................................................... 2
GlacioBasis ................................................................................................................... 3
General instructions ..................................................................................................... 5
Safety .......................................................................................................................... 5
Data collection, safeguarding and documentation ...................................................... 5
Field procedures........................................................................................................... 7
Ablation and velocity stakes ....................................................................................... 7
Snow pits..................................................................................................................... 8
AWS establishment and maintenance......................................................................... 9
GPS surveys .............................................................................................................. 11
GPR surveys.............................................................................................................. 12
Contacts....................................................................................................................... 14
Appendix A - AWS establishment and maintenance checklist ........................................ 16
Appendix B – AWS station design ................................................................................... 21
Appendix C – AWS plugs internal wirings ...................................................................... 29
Appendix D – Datalogger program................................................................................... 37
Appendix E – Telemetry data retrieval program .............................................................. 55
1
Preface
This manual provides information required to properly carry out GlacioBasis
glaciological fieldwork at the A.P. Olsen ice cap taking advantage of the logistic support
provided by the Zackenberg Research Station. The focus is on the field procedures and
technical details to be strictly followed to ensure the consistency and continuity of the
data collection in the field.
The manual in this first version should be regarded as being still in draft status.
Furthermore, some information such as deployed sensors or the updated location of the
ablation stakes can change slightly over time as a result of additions to the present setup
or re-establishment of lost stakes.
Revisions history
3rd November 2009, version 1
2
GlacioBasis
The primary aim of the GlacioBasis monitoring programme at Zackenberg is to produce a
record of high quality glaciological observations from the A.P. Olsen Ice Cap and its
outlet glacier in the Zackenberg river basin. The A.P. Olsen Ice Cap is located at 74° 39’
N and 21° 42’ W. The summit reaches an elevation of 1425 m and the terminus of the
outlet glacier contributing to the Zackenberg river basin is at 525 m (figure 1).
Zackenberg Research Station is located SE of the site, approximately 35 km downstream.
The most direct access to the glacier terminus is through Store Sødal. The need to
measure winter accumulation requires fieldwork to be carried out during springtime,
immediately before the onset of significant snow melt. This timing is also necessary for
snow-mobile use, which greatly simplify access to the glacier and transport of equipment
and instrumentation. Fieldwork must be carried out every year in order to maintain the
stakes network operational and to service the automatic weather stations (AWS) on the
glacier.
AWS2
AWS3
AWS1
Fig. 1 – Map of the investigated outlet glacier with the position of the stakes and AWS.
The severe scarceness of glacier mass balance measurements from glaciers and local ice
caps in East Greenland, the strong impact that local glaciers and ice caps outside the Ice
Sheet are expected to exert on sea level rise in the present century (Meier et al. 2007),
and the warming expected to occur in the Arctic (IPCC 2007) highlight the scientific
3
importance of GlacioBasis monitoring tasks. The anticipated use of the monitoring data is
to model the surface energy balance and the glacier mass budget with physically based
models that, once calibrated and validated with in situ data, will allow to model the
response of the glacier to future climate change scenarios.
Figure 1 provides an overview and map of the investigated outlet glacier of the A.P.
Olsen ice cap. The position of the 14 ablation and displacement stakes is shown, together
with the position of the three AWS.
GlacioBasis is conceptually linked to the other monitoring programmes in the
Zackenberg river basin through the contribution of glacier melt water discharge to the
river, its regime and seasonality, and its impact on solutes and sediment fluxes to the sea.
Furthermore, the study site offers opportunities to extend investigations to the glacier
dammed lake on the eastern side of the studied outlet glacier (which is regarded as the
source of several floods recorded downstream in the past years), and to the formation of
superimposed ice, which is expected to be significant at this site.
‘
4
General instructions
All GlacioBasis personnel arriving at Zackenberg station must have read the ZERO Site
Manual (available from http://www.zackenberg.dk/NR/rdonlyres/8BA15D73-8D584C17-ABDA-99C0067FD571/0/ZERO20Site20Manual2C20ver2027102008.pdf)
and
must commit to follow its instructions. This is particularly important with regard to the
restricted mobility in the protected areas around Zackenberg Station.
Safety
Safety is the first priority for all GlacioBasis personnel in the field. All instructions from
the Zackenberg Station manager must be followed strictly. Due care and sound judgment
must be applied at all times, especially upon leaving the immediate surroundings of the
station, when driving snowmobiles, and on the glacier.
All personnel will need to be confident in the use of firearms for defending themselves
and their colleagues against polar bears and musk oxen, and is requireed to carry a rifle
and ammunition when leaving the station’s surroundings. Firearms, ammunitions and
flare guns are provided by Zackenberg Station. All GEUS personnel is required to have
attended to the GEUS shooting course, the first aid course, the glacier safety course and
the snow safety course. These courses are intended to enable each participant to
make an informed assessment of the safety conditions at all times. Since VHF radio
communication is not possible from the glacier to Zackenberg Station due to the terrain
morphology, an Iridium phone must be carried during every trip to the glacier. VHF
radios may be useful to locally coordinate work on the glacier.
It is the participant’s responsibility to plan ahead before leaving Denmark and make sure
all the required personal field gear is available and in good working conditions. Personal
safety equipment for GEUS personnel can be procured through GEUS.
Data collection, safeguarding and documentation
GlacioBasis aims at producing a consistent dataset of high quality observation data, and
this requires that documented field procedures are followed strictly and that metadata be
always attached to all data produced in the field. All maintenance work on the automatic
weather stations (AWS) must be documented using the field maintenance checklist in
Appendix A, with special care to recording the serial numbers of the instruments and the
initial readings. Pictures should always be numbered and referenced in the maintenance
checklist. Further details relevant to the specific monitoring tasks are provided in the
following sections.
It is important to safeguard against accidental loss of data by duplicating field notes on a
daily basis and ensuring that one copy remains at the Station while the other (if necessary
5
for reference) is carried in the field. Use of special field notebooks, A4 size sheets and
printed forms made with water-resistant paper is recommended. Electronic data will need
to be duplicated on at least two separate storage supports to safeguard against data
corruption.
Since fieldwork is being carried out at a remote location posing significant operative
challenges, a trade-off may be required at times to ensure that the most important
measurements are carried out even when the prescribed field plans and procedures can
not be implemented fully due to unexpected weather or field conditions. The field leader
is responsible for prioritizing the pending tasks in consideration of the available resources
and without compromising safety and the quality of the measurements. In the exceptional
case that a measurement can not be made by strictly following the prescribed protocol,
this must be fully documented in the metadata.
Relevant GlacioBasis data will need to be fed into the Zackenberg Basis database.
6
Field procedures
Ablation and velocity stakes
A network of 14 ablation and surface velocity stakes distributed along the central flow
line has been established in spring 2008 on the outlet glacier of the A.P. Olsen ice cap
and along three transects at elevations of approximately 675, 900 and 1300 m (figure 1
and table. 1) respectively. Each 6 m long stake was assembled from 2 m lengths of
aluminium tube. A Kovacs drill was used with success, allowing very fast drilling
operations.
ID
01
02
05
04
03
06
08
07
10
09
12
11
13
14
LAT
N7437.1293
N7437.4536
N7438.3637
N7437.9356
N7437.6633
N7438.5687
N7438.9168
N7438.5616
N7439.6703
N7439.2688
N7439.7398
N7439.0492
N7440.5023
N7439.8511
LONG
W02121.8890
W02123.0806
W02125.6941
W02123.9705
W02122.1934
W02125.3384
W02128.2411
W02129.0397
W02133.1732
W02130.5855
W02136.0492
W02136.2686
W02136.3062
W02140.4234
Tab. 1 – Position of the ablation and displacement stakes.
The stakes must be measured and re-drilled every year following this procedure
(assuming the current planning of only one visit per year in springtime):
1. upon approaching an existing stake, take a picture documenting the undisturbed
site
2. measure the length of the stake above the snow surface
3. place the GPS antenna on top of the existing stake and start a measurement with
the most accurate survey mode available (see GPS section). If tilted, note attitude.
4. take a note of stake number, date, time, picture number, air temperature, GPS
survey mode being used for the precision survey and GPS fix from the handheld
5. probe with an avalanche probe the snow depth in the immediate surroundings of
the stake and record all measurements, not just the average
7
6. if time or weather constraints prevent digging a snow pit at every stake, pay
particular care when probing to “feel” the snowpack stratigraphy and assess how
similar it appears to be to other stake sites where a snow pit has been dug. A snow
pit is required in any case if the elevation of the stake site or the
snowpack depth are significantly different from the closest snow pit measured.
7. dig a snow pit in the surroundings of the stake site without disturbing the stake,
and survey it following the procedure in the “snow pits” section.
8. recover the emerging lengths of aluminum tube from the old stake
9. mark the top of the remaining old stake by over-expanding one of the old joints in
such a way that it will permanently remain attached to the stake end.
10. drill the new stake close to the existing one using the Kovacs drill (pay special
care when using the Milwakee electric drill to avoid being hardly hit by the drill
in case the drill suddenly gets stuck in the hole. The two strokes engine has lower
torque.
11. never leave the drill sitting still in the hole to avoid it getting frozen to the hole, or
otherwise it will be lost.
12. measure the length of the new stake above the ice and snow surface
13. place the GPS antenna on top of the stake and start a measurement with the most
accurate survey mode available (see GPS section)
14. probe with an avalanche probe the snow depth in the immediate surroundings of
the new stake and record all measurements, not just the average
15. upon leaving, take a picture documenting the site conditions
Required equipment:

map and updated coordinates of the stakes

handheld GPS with waypoints in memory marking the position of stakes

measuring tape

camera and field notebook

avalanche probe

spare aluminium tubing and connection fittings

snow pit kit (see below)
Snow pits
The most important data obtained from a snow pit are the water equivalent depth and the
density profile of the snow pack. Additional observations should be carried out whenever
possible following this priority: temperature profile, snow crystallography, dusts layers,
penetrability profile. The snow pit will be surveyed following this procedure:
8
1. mark in the snow surface the intended outline of the snow pit orienting it so that
the side wall where observations will be made is facing away from the sun
2. take a picture documenting the unexcavated site
3. take a note of snow pit position, date, time, pictures number and air temperature
4. dig the snow pit paying attention not to disturb the snow surface along the side
where observations will be made
5. deepen the snow pit until glacier ice or the previous summer surface are found
and prepare the vertical surface to be measured
6. measure the temperature profile allowing sufficient time for the thermometers to
settle to a stable reading
7. identify the snow stratigraphy and mark the surfaces of the various levels
8. measure and record the total thickness of the snowpack and the thickness of the
individual snow layers, recording any surface enriched with dust
9. using a sampler of known volume take an horizontal core at 1/3 from the bottom
of each snow layer, weigh the sample with a precision spring scale
10. describe the crystallography of the snow and proceed to the following layer
11. take pictures documenting the snow pit
12. fill back the snow pit before leaving
Required equipment:




map and handheld GPS
camera and field notebook
avalanche probe
shovel (it is recommended to have both a broad light shovel and a smaller one
with sharpened edge to negotiate high strength wind drifted or refrozen snow)
 snow pit kit, containing:
 known volume sampler
 rubber head hammer
 plastic bags
 precision scale
 snow stratigraphy survey forms
 reference scale and crystal type card
 insertion thermometers
 lens
 foldable measuring bar or measuring tape
AWS establishment and maintenance
The establishment and setup of an AWS need to be carried out following the checklist in
Appendix A, filling in all details required in the form and taking pictures documenting
the conditions of the AWS both upon arrival (before any disturbance to the instruments
and the snow cover) and upon leaving the site. Particular care must be paid at the proper
leveling and orientation of the sensors. All technical details of the AWS desing, internal
9
and plugs wiring, and datalogger programming are contained in Appendix B, C and D
respectively. Fig. 3 provides an overview of the station marked as AWS 1 in Fig. 1
3
6
5
4
2
1
7
8
9
10
11
Fig. 3 – Overview of the AWS and the sensors. 1. Air temperature and humidity
(aspirated); 2. SW↓, LW↓, SW↑, LW↑ radiation; 3. Wind speed and direction; 4. Snow
surface level; 5. two-axes tilt meter; 6. Iridium satellite antenna; 7. GPS receiver and
Iridium modem; 8. Air pressure; 9. Surface level (sonic ranger); 10. Thermistors string
(GEUS); 11. Hydraulic ablation meter (GEUS)
Telemetry data transmitted through the Iridium satellite system is received at GEUS as
email messages and the data can be retrieved from within GEUS intranet by a user with
appropriate permissions to access the dedicated mailbox using the Python program
attached in Appendix E.
10
Required equipment:
The following table 2 (prepared by Søren Nielesn, GEUS) describes various
recommended set of tools to setup or carry out maintenance on a GlacioBasis AWS.
Some of the items may only be required when testing the instruments at Zackenberg
Station and may be left behind when leaving for the glacier.
Svensknøgler
Svensknøgle
Løse skraldefastnøgler
MINIMUM
8" el. 6" med brede kæber
4"
10 - 13 - 17 mm
Skruetrækker & bit sæt
Urmagerskruetrækkersæt
Bacho PH1x75
MEDIUM
COMPLETE
Fastnøglesæt 8-10-13-15-17-19 mm
For iridium antenna
Bacho 1x5,5x100
BE-8150
Umbraco, mm
Umbraco, "
1 sæt løse, 1 - 10 mm
1 sæt løse, 1/16 - 3/8 "
Umbraco, mm, with handle
Umbraco, ", with handle
4 - 6 - 8 mm
1/4 - 5/16
Elektronik skruertækker
Lille elektronik skruertækker
Campbell
CK 2,5x75 el. Bacho 0,4x75
Vandpumpetang
Stor skævbider
Mora Kniv
Stanleykniv
Skalpel
Multimeter
Digitalt waterpas
Magnetisk kompas
S-Digit Mini
Silva pejlekompas
186 mm Kabelbindere
360 mm Kabelbindere
Umbraco, mm, "Knife model"
Umbraco, ", "Knife model"
Elektronik bidetang
Elektronik spidstang
Loddekolbe, gas eller opladelig
Loddetin
Batteries:
Låseolie
Silicone
DowCorning 732 (Cheap)
do.
DowCorning 3140 (Flowable)
Nødvendige umbrako:
1/4" - 5/16" KeeKlamp
4 mm CNR1
8 mm Letrona
AAA - AA - 9V
Wiresaks
1" Rørskærer
Juniorbue
Topnøgler 5,5 - 7 - 8 mm
5,5: 3 mm nuts on plugs
7 - mm: Forskellige
spændbånd
Lille borsæt
Crimptang
Bolts 8x20 SS
Nuts 8 mm
Bolts 8x16 SS
Nuts 8 mm
5mm battery nuts
Nuts 5 mm
3mm Bolts & Nuts
Selftapping screws
1mm² wire
Small cable tiers
M10 Bolts & Nuts
Terminal strips
Spare plugs:
CA6LS
CA3LD
CA6GD
CA3GS
9pole plugs
9pole panel sockets
For sensors (Solder)
For batterycable, solar panel
Panel connectors, sensors (Solder)
Panel connectors, power
For t:string, CNR1 (Crimp)
Panel conn., 9 pole (Crimp)
Div. Spares:
Silicon
Hose clamps
2 tubes, 732 (Cheap) - 3140 (Fluid)
Large (ex. For CNR1)
Crimp conn. (Red)
Tube clamps small
Tube clamps medium
CF Cards
Washers
6mm Bolts
6 mm Nuts
KeeKlamp screws
2
2
2
2
2
2
Tab. 2 – Various options for the recommended tools for AWS setup and maintenance.
GPS surveys
GlacioBasis has three main uses for GPS measurements: tracking the displacement of the
stakes, positioning the GPR radar traces, and mapping the surface elevation of the
glacier. These tasks require differential GPS (DGPS)
accuracy, and all efforts should be expended in obtaining them. Standalone GPS
measurements should be avoided since they are much less accurate, and should only be
11
taken when the available equipment or other technical circumstances prevent operations
in DGPS mode.
The detailed procedure for taking DGPS measurements vary with the specific receiver
model used, see the instrument documentation for details.
Whatever the instrument used, the model, configuration and setup must be recorded and
special care must be paid in properly configurating the antenna parameters and in
positioning the antenna on the stake. Unobstructed view of the sky must be ensured.
GPR surveys
Snow depth profiles are surveyed with a 500 or 800 MHz shielded antenna and either
constant time (0.25 sec) or constant distance (0.5 m) settings by setting up the antenna on
a fiberglass sled towed by a snowmobile. The monitor should be setup so that the
snowmobile driver can see the data being acquired and adjust the speed consequently.
Every few hundred meters, and also every time unclear features are seen on the display,
the snowmobile must stop and a few measurements of the snopack depth must be taken
with the avalanche probe, recording all the values and not just the average.
Data files will be frequently downloaded from the GPR instrument to a USB stick and
daily backed-up to a second storage support to be kept at Zackenberg Station.
The tracks to be followed during the GPR survey should cover the glacier as evenly as
feasible, but avoiding dangerous crevassed areas unless the snow cover is abundant and
safe. As an example, Fig. 2 shows the tracks followed in 2008. GIS files with the tracks
surveyed during previous years are available from within GEUS intranet in the folder:
\\Geusnt1\glaciologi\GlacioBasis\GlacioBasis Manual\GIS files\
12
1389
1337
P. O L S E N
1416
L A N D
Fig. 2 – GPR tracks followed during the 2008 snow depth survey.
Reasonably accurate positioning of the GPS traces is important, even though D-GPS
accuracy is not a strict requirement for snow depth monitoring.
13
Contacts
This is the updated list of contact details including phone numbers and addresses for use
during the fieldwork season fieldwork. It is mainly for the personnel in the field, but also
contains some contacts useful during the trip to Greenland and for arranging
unanticipated shipments.
name
Michele
Citterio
email
phone
mobile (*)
mcit@geus.dk +45 38142113
Andreas
Ahlstrøm
Søren Nielsen
apa@geus.dk
+45 38142794
sn@geus.dk
+45 38142321
Marianne
Vestergaard
mve@geus.dk +45 38142200
GEUS
switchboard
GEUS doctor
geus@geus.dk +45 38142000
Malå
Geoscience
Geoteam
Zackenberg
Station
Henrik
Spanggård
Morten Rasch
technical issues with
AWS, support with
shipments
reporting of accidents
and injuries during
fieldwork (for GEUS
personnel)
general contact
emergency medical
consultation
technical support for
GPR-related issues
technical support for
GPS-related issues
communications to
people in the field (must
specify name)
issues
Logistics
+46 95334550
support@geote +45 77332233
am.dk
logistics@zack
enberg.com
hesm@fi.dk
+45 72488134
mr@fi.dk
45 7248 8110
Air Greenland
+299 991044
Constable Pynt
Norlandair
+354 4146960
Akureyri
Kristbjörg
kibba@norlan
Björnsdóttir
dair.is
competence
scientific and technical
issues, fieldwork
planning, project
management
scientific issues
Zackenberg Station
scientific leader
issues related to
unanticipated shipments
+354 8601208 arranging or tracking
unanticipated shipments
14
* several phone numbers are not published here and must be obtained before leaving
Denmark. The complete page is available from within the GEUS intranet in this folder:
\\Geusnt1\glaciologi\GlacioBasis\GlacioBasis Manual\contacts.doc
Boxes and all cargo to be delivered to GEUS shall always be addressed to:
GEUS varemodtagelsen, Riegensgade 13, DK-1316 Copenhagen K
Alternatively and only upon agreement with the logistic staff at Zackenberg Station, the
delivery can be routed through DMU in Roskilde. This option may in general be cheaper
but slower, and either Michele and/or Søren at GEUS will need to be notified of the
shipment.
The address for regular mail correspondence is to:
Michele Citterio, GEUS, Øster Voldgade 10, 1350 Copenhagen K
15
Appendix A - AWS establishment and maintenance
checklist
(Dirk van As, GEUS)
16
AWS maintenance / establishment checklist version 5
Station name
Observer(s)
Purpose of visit
Establishment of new AWS: Go to Metadata after maintenance / establishment
Metadata upon arrival
Date & time of arrival at station
Time difference between logger clock and UTC
Adjust logger time to UTC
Download data to PC and/or change CF Card (wait for green light)
Download logger program to PC
Note or photograph current values in fast scan mode
Latitude (dd mm.mmm)
Longitude (dd mm.mmm)
Altitude (m, from GPS)
Photos of tripod, sensors, logger box wiring etc.
Mast inclination in CNR1 direction (+ if CNR1 tilting down)
Mast incl. across boom looking from CNR1 (- if clockwise)
Boom direction relative to true/magnetic north
Young box direction along boom? If not, measure direction
CNR1 aligned with mast and inclinometer? If not, measure
Young height (center of propeller – surface)
Rotronic height (bottom of casing – surface)
SR50 height on AWS (membrane – surface)
SR50 height on stakes (membrane – surface)
Free length of stake – outer, holding boom with SR50
Free length of stake – middle
Free length of stake – outer, holding boom without SR50
Length of ablation sensor tubing on the surface (to T-piece)
Or: depth of ablation sensor using markings on hose
Length of thermistor string on surface from surface marking
+/Y/N
Y/N
Y/N
Y/N
Y/N


 true/magn
Y/N
Y/N
cm
cm
cm
cm
cm
cm
cm
cm
cm
cm
Remarks:
17
Maintenance step-by-step
Change Internal battery? Data and program will be lost!
Change vent filter in logger enclosure?
Change wires or aluminum of tripod?
Change sonic rangers membranes or replace by new sensors
Align CNR1 and inclinometer with mast within 0.5
Clean domes and check fastenings of CNR1
Change Hygroclip in Rotronic
Rotronic fan OK?
Apparent damage to Young wind sensor?
Clean solar panel
Voltage solar panel OK?
Refill ablation hose?
Redrill stakes
Refill Ablation drinking bag (With______________L, 100/50%)
Redrill old ablation hose?
Redrill old thermistor string?
Change desiccant bags in logger box
Change desiccant bags in battery box
Upload new logger program? (Name:______________________)
Y/N
Y/N
Y/N
Y / N / New
Y/N
Y/N
Y/N
Y/N
Y/N
Y/N
Y/N
Y/N
Y/N
Y/ N
Y / N / new
Y / N / new
Y/N
Y/N
Y/N
Remarks:
18
Metadata after maintenance / establishment
Latitude (dd mm.mmm)
Longitude (dd mm.mmm)
Photos of tripod, sensors, logger box wiring etc.
Mast inclination in CNR1 direction (+ if CNR1 tilting down)
Mast incl. across boom looking from CNR1 (- if clockwise)
Boom direction relative to true/magnetic north
Young box direction along boom? If not, measure direction
CNR1 aligned with mast and inclinometer? If not, measure
Young height (center of propeller – surface)
Rotronic height (bottom of casing – surface)
SR50 height on AWS (membrane – surface)
SR50 height on stakes (membrane – surface)
Free length of stake – outer, holding boom with SR50
Free length of stake – middle
Free length of stake – outer, holding boom without SR50
Number of 2-m pieces used for new stakes
Length of ablation sensor tubing on the surface (to T-piece)
Or: depth of ablation sensor using markings on hose
Length of thermistor string on surface from surface marking
Approximate height of surface irregularities
Time of departure
Y/N


 true / magn
Y/N
Y/N
cm
cm
cm
cm
cm
cm
cm
1/2/3/4/5
cm
cm
cm
cm
Remarks:
19
Serial numbers of hardware
SR50 Snow (sonic ranger on AWS)
Replaced with:
SR50 Abl (sonic ranger on stakes)
Replaced with:
Rotronic assembly (Assembly no. if new assembly)
Hygroclip S3 no.
replaced with:
MP100H no.
replaced with:
RS12T (Fan) no.
replaced with:
MKRS (Arm) no.
replaced with:
NT1400 pressure transducer (Retrieved / Left in ice)
Replaced with:
Thermistor string (Retrieved / Left in ice)
Replaced with:
CNR1 radiation sensor
Replaced with:
Young wind sensor
Replaced with:
Inclinometer
Replaced with:
Solar Panel
Replaced with:
Iridium modem (if present), IMEI number:
Replaced with:
DC-DC Converter (SYN-DC-936)
Replaced with:
Satellite antenna
Replaced with:
GPS antenna
Replaced with:
In loggerbox:
Logger Cr1000/CR10X
Replaced with:
Card reader CFM100
Replaced with:
Multiplex AM16/32
Replaced with:
Barometer
Replaced with:
Remarks:
20
Appendix B – AWS station design
(Michele Citterio, GEUS)
21
Glaciobasis Main AWS
Rev. MCIT 17 Mar 2008
NOTE: This is the working setup with program revision 1.3
Design changes or additions from the previous revision (9 Feb 2008) are written like this. See also
the list of changes at the end of the document.
Datalogger and multiplexer box
CR1000 wirings
Top wiring strip
CR1000 side
SE1
DIFF1
SE2
GND
SE3
DIFF2
SE4
GND
SE5
DIFF3
SE6
GND
SE7
DIFF4
SE8
GND
EX1
GND
P1
GND
P2
GND
SE9
DIFF5
SE10
GND
SE11
DIFF6
SE12
GND
SE13
DIFF7
SE14
GND
SE15
SE16
GND
EX2
GND
DIFF8
EX3
Sensor side
H  EX2
L – RED
G -- VIO
ORA
BLK
shield
H  EX2
L – RED
G -- BLU
YEL
GRE
SHIELD
BLU
open
RED
BLK
open
open
Device name
HygroClip n. 1 (through a Campbell 4WPB100)
HygroClip n. 1 (through a Campbell 4WPB100)
HygroClip n. 1
HygroClip n. 1
HygroClip n. 1
CNR1 – Pt100 cable (through a Campbell 4WPB100)
CNR1 – Pt100 cable (through a Campbell 4WPB100)
CNR1 – Pt100 cable
CNR1 – Pt100 cable
CNR1 – Pt100 cable
Young wind
Young wind
Young wind
Middle wiring strip
H  EX2
L – RED
HygroClip n. 2 (through a Campbell 4WPB100)
G -- VIO
HygroClip n. 2 (through a Campbell 4WPB100)
ORA
HygroClip n. 2
BLK
HygroClip n. 2
shield
HygroClip n. 2
 MUX ODD H
Multiplexer COMMON, ODD DIFF. CHANNEL
 MUX ODD L
Multiplexer COMMON, ODD DIFF. CHANNEL
 MUX GND
Multiplexer COMMON
+ YEL + YEL
HygroClip n. 1 and n. 2
 RES. PANEL n. A
Resistor bridges panel for the thermistor string
 RES. PANEL n. B
Resistor bridges panel for the thermistor string
 RES. PANEL n. C
Resistor bridges panel for the thermistor string
 SE1+SE5+SE9
The black wires of the Campbell 4WPB100 bridges
shield + shield
SR50 n.1 e n. 2
WHI (thermistor sring) Termistor string and NT1400 bridge pressure
transducer
+ RED (NT1400)
22
G
5V
G
SW-12
G
12V
12V
G
C1
COM1
C2
C3
COM2
C4
G
C5
COM3
C6
C7
COM4
C8
G
RS232
Ground lug
Bottom wiring strip
open
open
BLK
Setra barometer
 SW-12V DISTRIB.
 MUX GND
Multiplexer CONTROL & POWER
open
open
 LED node A
Low current LED with resistor
 MUX RES
Multiplexer CONTROL & POWER
 MUX CLK
Multiplexer CONTROL & POWER
open
From CR1000 manual, this shouldn’t be used since
we already use COM2 as a serial port
WHI
Garmin GPS
BLK+YEL+shield
Garmin GPS
 LED node B
Low current LED with resistor
TX module relais control, active high
GRE + GRE
SR50 n.1 e n. 2
Fan relais control, active high
WHI+BLK+WHI+BLK SR50 n.1 e n. 2
other
To NAL Iridium and GPS module. Needs a male-to-male 9 poles D adapter
Current sensing shunts wiring box terminal post 15
RESISTOR BRIDGES PANEL FOR THE THERMISTOR STRING
(see drawing for the bridge circuit and the meaning of the node letters below)
Circuit side
Node A
Node B
Node C
Node D
Node E
Logger and string side
 SE15
 SE16
 GND
 MUX EVEN H
 MUX EVEN L
Device name
CR1000
CR1000
CR1000
Multiplexer COMMON, EVEN DIFF. CHANNEL
Multiplexer COMMON, EVEN DIFF. CHANNEL
Node E
Node D
249k
249k
Node A
Node B
1k
1k
GND = node C
23
MULTIPLEXER
(it must be configured as a 4x16 MUX)
COMMON
Multiplexer side
RES
CONTROL
CLK
&
GND
POWER
12V
H
ODD
L
GND
H
EVEN
L
GND
H
1
L
1
GND
H
2
L
GND
H
3
L
GND
2
H
4
L
GND
H
5
L
GND
3
H
6
L
GND
H
7
L
GND
4
H
8
L
GND
H
9
L
GND
5
H
10
L
GND
H
11
L
6
GND
12
H
Device side
 C1
 C2
G
 SW-12V DISTRIB. PANEL
SE13
SE14
 GND (between SE14 - SE15)
SE15
SE16
open
GRE
GRE
open
open
open
WHI, shield
 current sense shunts, post 13
 current sense shunts, post 14
open
ORA
BLK
open
 current sense shunts, post 9
 current sense shunts, post 10
open
BLU
YEL
open
 current sense shunts, post 6
 current sense shunts, post 5
open
GRE
BRO
open
 current sense shunts, post 2
 current sense shunts, post 1
open
PNK
VIO
open
YEL
GRE
GRY
open
Device name
CR1000
CR1000
CR1000
SW-12V DISTRIB. PANEL
CR1000
CR1000
CR1000
CR1000
CR1000
Setra Barometer
Young wind
Young wind
Battery low side current sensing R hi
Battery low side current sensing R lo
Termistor string level 1
Termistor string level 2
Solar panel low side current sensing R hi
Solar panel low side current sensing R lo
Termistor string level 3
Termistor string level 4
Fan low side current sensing R hi
Fan low side current sensing R lo
Termistor string level 5
Termistor string level 6
Iridium low side current sensing R hi
Iridium low side current sensing R lo
Termistor string level 7
Termistor string level 8
Tilt sensor
Tilt sensor
Tilt sensor
24
L
GND
H
L
GND
H
14
L
GND
H
15
L
GND
H
16
L
GND
H
17
L
GND
H
18
L
GND
H
19
L
GND
H
20
L
GND
H
21
L
GND
H
22
L
GND
H
23
L
GND
H
24
L
GND
H
25
L
GND
H
26
L
GND
H
27
L
GND
H
28
L
13
7
8
9
10
11
12
13
14
open
open
RED
BLU
open
open
open
open
GRY
YEL
open
open
open
shield
WHI
BLK
open
open
open
open
BRO
GRE
open
open
open
open
WHI
BRO
GRY
open
open
open
WHI
BRO
GRY
open
open
open
YEL
BLU
WHI
open
open
open
open
open
open
open
open
CNR1 – Radiometers cable
CNR1 – Radiometers cable
CNR1 – Radiometers cable
CNR1 – Radiometers cable
CNR1 – Radiometers cable
CNR1 – Radiometers cable
CNR1 – Radiometers cable
CNR1 – Radiometers cable
HygroClip n. 1
HygroClip n. 1
HygroClip n. 1
HygroClip n. 2
HygroClip n. 2
HygroClip n. 2
NT1400
NT1400
NT1400
25
GND
H
29
L
GND
H
30
L
GND
H
31
L
GND
H
32
L
GND
15
16
open
open
open
open
open
open
open
open
open
open
open
open
open
SW-12V DISTRIBUTION PANEL
Circuit side
Just wire
everything
together
Sensor side
 SW-12
GRE
GRE
RED
 MUX 12V
RED
RED
BRO
Device name
CR1000
HigroClip n. 1
HigroClip n. 2
Setra barometer
Multiplexer CONTROL & POWER
SR50 n.1
SR50 n.2
Tilt sensor
LED
The LED ishould be a low current type not to overload the CR1000 output which are specified to
max. 2 mA. Buy RS code n. 826-521 or 826-802 (buy both, RS must have some mistake on their
website so it isn’t clear which one is transparent, but they are still cheap enough…). Otherwise use
type recommended by Peer Jorgensen.
1k
Node A
Node B
26
CURRENT SENSING SHUNTS
(see drawing for the bridge circuit and the meaning of the node letters below)
Circuit side
15 Datalogger GND
12
16
4
8
9
10
13
14
6
5
2
1
17
SP(-)
BAT(-)
TxGND
FanGND
SP-H
SP-L
BAT-H
BAT-L
FAN-H
FAN-L
TX-H
TX-L
GND BOLT
other side
POWER IN G
GND LUG
Solar panel negative
Batteries negative
Tx ground return
Fan ground return
MUX SE5H
MUX SE5L
MUX SE3H
MUX SE3L
MUX SE7H
MUX SE7L
MUX SE9H
MUX SE9L
GND BOLT
Device name
CR1000
Solar panels
Batteries (the negative terminals are all tied together)
Iridium module
Rotronic Fan
MUX
MUX
MUX
MUX
MUX
MUX
MUX
MUX
CR1000 (connect to the GND screw on the enclosure)
15 / Datalogger GND + datalogger GND lug
(and sensors ground, since their ground
returns are through the datalogger signal
ground wiring terminals)
1, 3, 5, 7, 9, 11, 13, 15,
17 are all tied together
in the wiring box
5 / FAN-L
17 / GND
BOLT
13 / BAT-H
9 / SP-H
1 / TX-L
14 / BAT-L
6 / FAN-H
10 / SP-L
2 / TX-H
4 / TxGND
Iridium
ground
return
8 / FanGND
Fan ground
return
terminal
12 / SP(-) 16 / BAT(-)
Solar panel
Battery
negative
negative
terminal
27
RS232 GENDER CHANGER AND TX-RX CROSSOVER ADAPTER
(numbers refer to a standard 9 pins D-type connector, see drawing)
SYN-DC-936
1
2
3
4
5
6
7
8
9
CR1000 RS232
open
3
2
6
5
4
8
7
open
1
9
viewed from the pins side
List of design changes
1. The LED is moved from C3 to C5 in order to leave C3 unused. This is required according to
the CR1000 documentation because we are using COM2 as a serial port (for the Garmin)
2. The previous connection from C5 to the manual FastScan switch is therefore removed, and
the switch is not available anymore since no spare control ports are available.
3. The EX3 excitation channel is now also exciting the NT1400 pressure transducer
4. In the MUX, the connections to the current sensing shuts have been added (at SE channels 3,
5, 7, 9)
5. In the MUX, the missing connection to the other thermistors in the thermistor string have
been added (at SE channels 6, 8, 10)
6. in the MUX the connection for the NT1400 has been added (at SE channel 25)
7. added the wirings for the current sensing shunts
8. added RS232 adapter wiring
9. changed ground routing for the return of the pulse signal of the
10. added RS232 adapter wiring
11. changed ground routing for the return of the pulse signal of the Young sensor
12. the GREY wires of the HygroClips have moved from the CR1000 to the MUX
28
Appendix C – AWS plugs and internal wirings
(Søren Nielsen, GEUS)
29
Plug no.
Plug type Sensor
Remarks:
ZAK_M and ZAK_S1 wiring:
Plug 1
4 pole
Battery box
Female cable, male logger box
Plug 2
4 pole
Solar Panel
Female cable, male logger box
Plug 3
7 pole
WD&S
Plug 4
7 pole
Tasp Signal
Plug 5
7 pole
Tasp Fan
Plug 6
7 pole
SR50 Abl - Adress 0
ZAK_M only wiring:
Plug 7
7 pole
Inclinometer
Plug 8
7 pole
SR50 Snow - Adress 1
Plug 9
7 pole
CNR Temp
Plug 10
9 pole
CNR-1 signal
Plug 11
9 pole
Thermistor string
Plug 12
7 pole
NT1400
Plug 13
7 pole
Tasp2 Signal
Plug 14
7 pole
Tasp2 Fan
Gland
PG11
Iridium antenna
Internal
Barometer
Internal
Iridium modem
Internal
GPS antenna to modem
ZAK_S1 only wiring:
Internal
Garmin GPS
Zak_M
4 pole
2 male
7 pole
9 female
9 pole
2 female
Total
14 + PG11
On battery box:
4 pole
1 female
ZAK_S
2 male
4 female
0
6
1 female
SN for the ZAK_M amd ZAK_S1 stations:
ZAK_M:
CR1000
E1350
CFM100
3355
AS16/32
E3903
CS100
3440 409
ZAK_S1: CR1000
E1349
CFM100
2489
Garmin 16-HVS 3333 4963
30
Plug numbers and positions for ZAK MAIN AWS
ZAK SECONDARY AWS only uses plug 1 - 6
9 pole
9 pole
11: Thermist.
6: SR50 Abl
7: Incl
8: SR50 Snow
9: CNR Temp
9,5
10: CNR Sig
6,5
Í
4P
male
1: Battery
Vent
4
3,5
4P
male
2: Solar P
6,5
4: Tasp S3
3: WS&D
5
5
Iridium Ant
14: Tasp2 Fan
13: Tasp2 Sig
12: NT1400
5
5
5
5: Tasp Fan-Pt100
5
5
Unmarked plugs are femal 7 pole.
31
Battery Group A +
Logger, Sensors
Terminal strip
Solar Panel Charge in
Grey

A

Pin 3
Battery Group B +
Pin 1
12V A out Brown
Pin 2
12V B out Black

B
Fan, SatCom, GPS
A:
B:
2 Diodes 1N5450 (RS Comp 348-5460)
Diode 80SQ045 (RS Comp 254-0730)
Pin G:
All negative battery terminals
Blue
Plug: 4 pole female
32
PLUGS 1-6 ZAK_M + ZAK_S1
Plug no.
Pin no.
Plug 1
Batterycable
Black cable
1,5 mm²
Plug 2
Solar panel
Blue cable
0,75 mm²
Plug 3
WS&D
Sensor cable
Sensor cable
Blue
Brown
Black
Grey
Blue
Brown

1
2
3

1
2
3
 Shield
1 Black
2 White
3 Green
4 Blue
5 Red
6
Plug 4
 Drain
1 Red
Tasp A
Hygroclip +
2 Black
Cable comp.
3 Blue
4 Yellow
9721 cable
5 Green
6 White
Plug 5
 Drain
1 Red
Tasp B
Fan + Pt100
2 Black
3 Blue
4 Yellow
9721 cable
5 Green
6 White
Plug 6
 Clear
1 Black
SR50 Abl
Sensor cable
2 Red
Adress 1
3 Green
4 White
5
6
Extension cable for SR50 Abl:
 Drain
Male plug
1 Red
2 Black
3 Blue
4 Yellow
5 Green
6 White
Female plug
Rotronic Tasp and RH wiring:
Function
MP100H ColoTerminal box
Probe Supply Green
1
RH Signal
White
2
T Signal
Brown
3
Cable Comp. Yellow
4
GND
Grey
5
Digital I/O
nc
6
Pt100 Ex+
Pt100 Signal+
Pt100 SignalPt100 ExFan Supply
Fan GND
Shield
Red
Pink
Black
Violet
Fan Brown
Fan Blue
nc
Sensor cable
Function
Ground
12 V A in
12 V B in
12 V charge out
Ground
Power +
nc
nc
Shield
WS reference
AZ reference
AZ signal
AZ exitation
WS signal
nc
Shield
Probe Supply
GND
nc
Cable comp.
RH signal
T signal
Shield
Fan Supply
Fan GND
Pt100 Ex+
Pt100 ExPt100 Signal+
Pt100 SignalShield
Power ground
12 V
SDI-12 databus
Not used
nc
nc
15 m 9721
7
8
9
10
11
12
Cable Colour
Red
Green
White
Yellow
Black
Blue (nc)
Drain
Blue
Green
White
Yellow
Red
Black
Drain
9721 cables
Inside cable
Black 1mm²
Red 1mm²
Red 1mm²
Grey 1,5mm²
Black 1mm²
Grey 1,5mm²
Connected to IN MAIN
Interface 1 no 16 (Power meas.)
Cr1000 +12V
Interface 3 no 4
Plug 2 pin 1
Interface 1 no 12 (Power meas.)
Plug 1 pin 3
Connected to IN SEC
Interface 1 no 12
Cr1000 +12V
Interface 2 no 4
Plug 2 pin 1
Interface no 8
Plug 1 pin 3
White
MUX1G
Orange
G (P1)
Black
MUX2G
Blue
MUX1L
Yellow
EX1
Green
P1
Brown
nc
White
nc
Orange
Interface 2 no 10
Black
G6
Blue
nc
Yellow
G14
Green
MUX21H
Brown
MUX21L
White
G4
Orange
Interface 3 no 1
Black
Interface 1 no 8
Blue
SE2L (4WPB100 L)
Yellow
G1 (4WPB100 G)
Green
SE3
Brown
SE4
White
G (EX2)
Orange
G (C8)
Black
Interface 2 no 13
Blue
C7
Yellow
G (C8)
Green
nc
Brown
nc
3 Campbell 4-wire Terminal Input Modules
4WPB100
DIFF1 - Black EX2 (Pt100 Tasp 1)
ZAK_M only:
4WPB100
DIFF3 - Black EX2 (Pt100 CRN-1)
4WPB100
DIFF5 - Black EX2 (Pt100 Tasp 2)
Plug
Pin
4
4
4
4
4
4
4 
5
5
5
5
5
5
5 
G (EX1)
G (P1)
G8
SE8
EX1
P1
nc
nc
Interface 1 no 16
G6
nc
G14
SE5
SE6
G4
Interface 2 no 1
Interface 1 no 4
SE2L (4WPB100 L)
G1 (4WPB100 G)
SE3
SE4
G (EX2)
G (C8)
Interface 1 no 18
C7
G (SW12V)
nc
nc
1
5
6
4
2
3
3
5
6
4
1
2
Internal Colour
Orange
Green
Brown
Yellow
Black
Blue (nc)
White
Blue
Green
Brown
Yellow
Orange
Black
White
In enclosure
33
PLUGS 7-14: ZAK_M only
Plug no.
Plug 7
Inclinometer
Pin no.

1
2
9720/1 cable
3
4
5
6
Plug 8

1
SR50 Snow
2
Adress 0
3
4
5
6
Plug 9

1
CNR-1 temp.
2
Sensor cable
3
4
5
6
1
Plug 10
2
CNR-1 signal
3
Sensor cable
4
5
6
7
8
9
1
Plug 11
2
Thermistor
3
string
4
Cable :
5
Farnell
6
123-5597
7
8
9
Plug 12

1
NT1400
2
Sensor cable
3
4
5
6
Plug 13

1
Tasp A
Hygroclip +
2
Cable comp.
3
4
9721 cable
5
6
Plug 14

1
Tasp B
Fan + Pt100
2
3
(Fan nc)
4
9721 cable
5
6
Sensor cable Function
Black
Ground
Red
+7…24 V
nc
White
Xout
Green
Yout
nc
nc
Clear
Shield
Black
Power ground
Red
12 V
Green
SDI-12 databus
White
nc
nc
nc
Black
Shield
nc
Blue
Pt100 exitation Red
Pt100 exitation +
Yellow
Pt100 signal +
Green
Pr100 signal nc
Red
CM3 up signal
Blue
CM3 up ref
White
CM3 down signal
Black
CM3 down ref
Grey
CG3 up signal
Yellow
CG3 up ref
Brown
CG3 down signal
Green
CG3 down ref
Shield
Shield
Orange
Signal level 1
Black
Signal level 2
Blue
Signal level 3
Yellow
Signal level 4
Green
Signal level 5
Brown
Signal level 6
Pink
Signal level 7
Violet
Signal level 8
White
Exitation
Shield Shield
White
VS Red
VS +
nc
nc
Blue
VO Yellow
VO +
Drain
Shield
Red
Probe Supply
Black
GND
Blue
nc
Yellow
Cable comp.
Green
RH signal
White
T signal
Drain
Shield
Red
Fan Supply
Black
Fan GND
Blue
Pt100 Ex+
Yellow
Pt100 ExGreen
Pt100 Signal+
White
Pt100 Signal-
Inside cable
White
Orange
Black
Blue
Yellow
Green
Brown
White
Orange
Black
Blue
Yellow
Green
Brown
White
Orange
Black
Blue
Yellow
Green
Brown
Orange
Black
Blue
Yellow
Green
Brown
Pink
Violet
White
Orange
Black
Blue
Yellow
Green
Brown
Pink
Violet
White
White
Orange
Black
Blue
Yellow
Green
Brown
White
Orange
Black
Blue
Yellow
Green
Brown
White
Orange
Black
Blue
Yellow
Green
Brown
Connected to
MUX11G
Interface 2 no 16
nc
MUX11H
MUX11L
nc
nc
G (EX2)
G (C8)
Interface 2 no 15
C7
nc
nc
nc
G8
nc
G6 (4WPB100 G)
SE6 (4WPB100 L)
DIFF4H
DIFF4L
nc
MUX13H
MUX13L
MUX17H
MUX17L
MUX15H
MUX15L
MUX19H
MUX19L
MUX16G
MUX4H
MUX4L
MUX6H
MUX6L
MUX8H
MUX8L
MUX10H
MUX10L
EX3
MUX25G
EX3
nc
nc
MUX25L
MUX25H
nc
Interface 2 no 12
MUX23G
nc
G14
MUX23H
MUX23L
G12
nc
nc
SE10L (4WPB100 L)
G10 (4WPB100 G)
SE11
SE12
34
Internal ZAK_M
Internal
Barometer
Internal
Iridium modem
Function
Ext. Trigger
nc
GND
12V
VOUT
Pin 1
Pin 2
Pin 3
Pin 4
Pin 5
RS232
1
2
3
4
5
6
7
8
9
NAL female
changed to
RS232 male
Iridium anten.
Red
Black
SMA Gold
SMA Silver
Cable
Gland
TNC male
SMA male
Inside cable
Green
Connected to:
Interface 2 no 18
Black
Orange
Yellow
Brown
Red
Orange
Yellow
Green
Blue
Violet
Grey
Black
G (5V)
Interface 2 no 14
MUX1H
nc
CR1000 RS232 Pin
CR1000 RS232 Pin
CR1000 RS232 Pin
CR1000 RS232 Pin
CR1000 RS232 Pin
CR1000 RS232 Pin
CR1000 RS232 Pin
nc
Interface 3 no 7
Interface 1 no 12
Antenna cable
GPS in enclosure
+
GND
Iridium antenna
GPS antenna
RG58: RS Comp 638-9472
PG11: RS Comp 444-2622
RS Comp 295-8226
RS Comp 5120115
3
2
6
5
4
8
7
Antenna
Modem SMA Gold
Interface 1
Power measurement
MUX9H
Modem G Black
MUX7H
Fan G Plug 5 pin 2
MUX5L
Solar Panel G Plug 2 pin 
MUX3L
Battery G Plug 1 pin 
nc
2 Black
4 Black
6 Yellow
8 Black
10 Green
12 Black
14 White
16 Black
18 Green/Yellow
Interface 2
Resistors for thermistorstring measurement, SW12 V
Twisted pairs ? Next time !
CR1000 SE15
nc
CR1000 SE16
nc
SW12V (from CR1000)
MUX 12V
SR50 Abl Plug 6 pin 2
SR50 Snow Plug 8 pin 2
nc
1 Blue
3
5 Yellow
7
9 Red
11 Orange
13 Black
15 Black
17
MUX EVEN H
nc
G16
MUX EVEN L
Tasp1 12V Plug 4 pin 1
Tasp2 12V Plug 13 pin 1
Barometer Pin 4 (12V)
Incl. Plug 7 pin 1
Barometer Pin 1 (Ext. Trigger)
Interface 3
Fan Supply, Modem supply
GND (12V) (Black)
12V B IN Plug 1 pin 2 (Red)
C8 (Yellow)
GND To 2 (Black)
12V B IN To 4 (Orange)
C6 (Blue)
NC
NC
NC
Internal connections:
5 mohm
5 mohm
5 mohm
5 mohm
249 kohm
1 kohm
1 kohm
249 kohm
1 Orange
3
5 Black
7
9 Brown
11
13 Yellow
15
17 Black
MUX9L
nc
MUX7L
nc
MUX5H
nc
MUX3H
nc
POWER IN G
2 Orange
4
6 Black
8 Orange
10 Orange
12 Orange
14 Orange
16 Orange
18 Green
2 IP521 Fan Supply
4
6
8 IP521 Modem supply
10
12
14
16
18
1
3
5
7
9
11
13
15
17
12V B OUT Fan Plug 5 pin 1 (Orange)
NC
NC
12V B OUT Modem SYN-DC + (Red)
NC
NC
NC
NC
NC
CR1000
SE13
SE14
G14
G (SW12V)
C1
C2
Colour
Orange
Yellow
Black
Black
Blue
Brown
MUX
ODD H
ODD L
G COMMON
GND
MUX RES
MUX CLK
Function
Signals to CR1000
do.
do.
POWER IN G
POWER IN 12V
Black 1 mm²
Red 1mm²
Interface 1 no 17
Plug 1 pin 1
Cathode (Short leg)
G (C5)
Diode RS Comp 564009
C5
Main Ground:
Enclosure Ground Lug - CR1000 Ground Lug - AM16/32 Ground Lug
All connections 2,5 mm² green/yellow
Reset
Clock
Anode (Most metal)
35
Internal ZAK_S1
Function
Power 12 V
Power ground
Remote On/off
Port 1 data in
Port 1 data out
PPS
Port 2 data in
Port 2 data out
Shield
Internal
Garmin GPS
Red
Black
Yellow
Blue
White
Grey
Green
Violet
Drain
Interface 1
Power measurement
SE13 Yellow
Fan G Plug 5 pin 2 (Black)
SE12 Green
Solar Panel G Plug 2 pin 
SE10 White
Battery G Plug 1 pin 
nc
H.Clip Plug 4 pin 1 Orange
SR50 Abl Plug 6 pin 2 Black
2
4
6
8
10
12
14
16
18
Interface 2: Fan, GPS supply:
GND (12V) (Black)
12V B IN Plug 1 pin 2 (Red)
C8 (Yellow)
GND To 2 (Black)
12V B IN To 4 (Orange)
C6 (Blue)
NC
NC
NC
2 IP521 Fan Supply
4
6
8 IP521 Modem supply
10
12
14
16
18
Cathode (Short leg)
Connected to:
Relay 2 no 14
G (12V)
G (12V)
nc
C4
nc
nc
nc
G (12V)
5 mohm
5 mohm
5 mohm
POWER IN G
POWER IN Red 1mm²
nc
Plug 1 pin 1
G (C5)
C5
Diode RS Comp 564009
1
3
5
7
9
11
13
15
17
SE14 White
nc
SE11 Blue
nc
SE9 Yellow
CR1000 GROUND LUG
G BOLT Enclosure
nc
SW12v from CR1000 (Red 1 mm²)
1
3
5
7
9
11
13
15
17
12V B OUT Fan Plug 5 pin 1 (Orange)
NC
NC
12V B OUT GARMIN (Red)
NC
NC
NC
NC
NC
Anode (Most metal)
36
Appendix D – Datalogger program
(Michele Citterio, GEUS)
37
'CR1000 Program for the GlacioBasis GEUS AWSs rev. 1.4M (23/03/2008).
'Written by Michele Citterio, GEUS, Copenhagen.
SequentialMode
'*******************************************************************************
'******** WHEN CONFIGURING A NEW ZACK-STYLE AWS, YOU DON'T NEED TO EDIT ANYTHING
'*******************************************************************************
Const AppendInstantaneous = True
Const HoursInstantaneous = 3' in hours 3
Const RemoteReconfig = False'unfinished, don't set True
Const BeginOfSummer = 90' in days
Const BeginOfWinter = 305' in days
Const ScanRate = 600'600 ' in sec (can't be shorter than 15 + 2*TxTimeout + 60)
Const MemSaveRate = 1'2 'in numebr of scans. This is both the averaging and the
Const SummerTxRate = 6'1 'in numebr of scans. This is both the averaging and the
Const WinterTxRate = 18'4 'in numebr of scans (=1440). This is both the averagin
Const SummerGPSrate = 3'1 'in number of scans (in this revision it must be an in
Const WinterGPSrate = 18'1 'in number of scans (in this revision it must be an i
Const SummerTableBuffer = 72
Const WinterTableBuffer = 24
Const DiagnosticsRate = 24'(=36) in hours
Const TermStringSz = 8' no. of thermistors in the thermistor sting
Const LoBattThre = 11.5' the threshold in V for Low_Batt to be set (entering pow
Const LoBattResHyst = 0.5 'the hysteresis in V above LoBattThre for resetting Lo
Const FastScanReps = 10 'how many times to run Measure routine in fastscan mode
Const FastScanRate = 20 'how often to run the Measure routine when in fastscan m
Const GPSType = "N" 'use 'G' for Garmin, 'N' for the one integrated in the NAL I
Const AdvanceFanStart = 2 'in number of FastScans. How much in advance of the sc
Const AdvanceGPSstart = 120'20'in sec. Increase!!
Const TxStringMaxLen = 420 'may be increased with future releases of the Iridium
Const TxMaxInitAttempts = 3' max 3, more doesn't make any sense and the wasted t
Const TxTimeout = 30 ' in sec, before the Tx sub times out. If service becomes a
Const SnowheightSR50address = 1' SDI12 address
Const AblationSR50address = 0' SDI12 address
Const GarminWarmup = 3' in seconds (doesn't mean it will then output a fix, but
Const SR50Warmup = 3' in seconds
Const HygroClipWarmup = 4' warm-up time needed by the HygroClip module after pow
Const NT1400Warmup = 5' time required for the pressure transmitter before it is
Const GarminBaudRate = 1200' Damn Garmin!!!!! Some units come preset at 1200 bau
'*******************************************************************************
'******** WHEN CONFIGURING A NEW ZACK-STYLE AWS, YOU DON'T NEED TO EDIT ANYTHING
'*******************************************************************************
Public WinterDataTerminator As String *3
Public SummerDataTerminator As String *3
Public InstantDataTerminator As String *3
Public DiagnDataTermninator As String *3
Public TxAllowed As Boolean
Public FanPowerDueForSwOff As Boolean
Public TableInstantaneousString As String * 100
Public TxPowerDueForSwOff As Boolean
Public GarminInitOk As Boolean
Public ConfigFile_H As Long
Public ConfigArrayIT
'Public DiagInfieldWarning As Boolean'check for it not being set before field de
Public NGPSFLAG As Boolean
Public GGPSFLAG As Boolean
Public LoggerOSrev
Public TimersUnit
Public TimersUnitMult
Public Diag
38
Public SkippedScans
Public SkippedSlowScans1, SkippedSlowScans2
Public GPSinUse As String * 1
Public TimeSince12Von
Public TimeSinceVx3on
Public LastSuccessfulMOMSN
Public SendRecordBacklog
Public SendRecordIT
Public TxTimeTaken
Public TxSendAttempts
Public TxTimeoutTimer
Public TxInitilizeAttempt
Public SBDIoffset
Public SBDIsentence As String * 40
Public SBDIparsed(6) As String *10
Public SBDsession As Boolean
Public TxInitializeOk As Boolean
Public StrIndex
Public TxSendSuccess As Boolean
Public SentWithSuccess
Public TxMObuffCleared As Boolean
Public TxMOuploaded As Boolean
Public TxRSSI' As String
Public TxSvcAvail As Boolean
Public TxNotifyON As Boolean
Public RS232EchoOk As Boolean
Public TxTypeNAL960x As Boolean
Public TxModuleATok As Boolean
Public TxModuleRFon As Boolean
Public TxModuleReply As String * 41
'Public TxSerialBuffer As String * 401'set as needed
'Public TxPowerOn As Boolean
Public TxModuleGPSPowerOn As Boolean
Public TxBufferString As String * TxStringMaxLen + 1 +80'to hold the null termin
Public TxStringUnstripped As String * TxStringMaxLen + 1 +80'sorry, there's some
Public TxString As String * TxStringMaxLen + 1'to hold the null termination
Public StringStripperIT
Public StripStringStart
Public StringChar As String * 1
Public MeasCycleDone As Boolean
Public C5status' As Boolean
Public C5statusPrev' As Boolean
Public LastFastScan
Public temp
Public Currents(4)
Alias Currents(1) = BatteryCurrent
Alias Currents(2) = SolarPanelCurrent
Alias Currents(3) = FanCurrent
Alias Currents(4) = TxGPSCurrent
Public MPFLAG As Boolean
Public FastScanSwitch As Boolean
Public FastScanCount
Public FastScanMode As Boolean
Public RTime(9) 'WARNING! this is used as a temporary variable in many different
Alias rTime(1) = Year
Alias rTime(2) = Month
Alias rTime(3) = DayOfMonth
Alias rTime(4) = Hour
Alias rTime(5) = Minute
Alias rTime(6) = Second
Alias rTime(7) = uSecond
Alias rTime(8) = WeekDay
Alias rTime(9) = DayOfYear
39
Public IsSummer As Boolean
Public Batt_VoltI
Public Batt_VoltF
Public Batt_V_Drop
Public Low_Batt As Boolean
Public Asp_fan_on As Boolean
Public Aspirated_meas As Boolean
Public PTemp_C
Public SR50_SnowHeight(2)
Alias SR50_SnowHeight(1)=SnowHeight ''sr50
Alias SR50_SnowHeight(2)=SnowHeightQuality ''sr50
Public SR50_Ablation(2)
Alias SR50_Ablation(1)=Ablation ''sr50
Alias SR50_Ablation(2)=AblationQuality
Public Ablation_meter ''sr50
Public temptemp,temptemptemp
'Public WaterColumnPressure
Public WS_ms
''Young
Public WindDir
''Young
Public BP_mmHg
Public AS_T
'Air temperature, ventilated shield
Public AS_RH
'Relative humidity, ventilated shield
Public AS_Pt100'PT100 air temperature, ventilated shield
Public US_T
'Air temperature, ventilated shield
Public US_RH
'Relative humidity, ventilated shield
Public US_Pt100'PT100 air temperature, ventilated shield
Public temp1 ''remove then
Public Xtilt
Public Ytilt
Public TermStringT(8)
Public CNR1_SWin
Units CNR1_SWin = mV
Public CNR1_SWout
Public CNR1_LWin
Public CNR1_LWout
Public CNR1_Pt100
Dim SW12Von As Boolean
Public _MUXRES
Dim MUXCLK As Boolean
Dim it
'GPS stuff
'Public LatL As Long
'Public SaveGPSFix
Public BestHDPseen
Public sBestHDPseen
'Public GPGGAoffset
'Public GPSData As String * 301
Public GPGGAsentence As String * 72
Public PreParseStr(18) As String * 15
Alias PreParseStr(7) = PreQual
Alias PreParseStr(9) = PreHDP
Public PreQual_FP
Public PreHDP_FP
Public ParseStrIT
Public ParseStr(18) As String * 15
Alias ParseStr(1) = GPGGA
Alias ParseStr(2) = TIME
Alias ParseStr(3) = LAT
Alias ParseStr(4) = HEMINS
Alias ParseStr(5) = LONGI
Alias ParseStr(6) = HEMIEW
Alias ParseStr(7) = QUAL
40
Alias
Alias
Alias
Alias
Alias
Alias
Alias
Alias
Alias
Alias
Alias
ParseStr(8) = NUMSATS
ParseStr(9) = HDP
ParseStr(10) = ALTDE
ParseStr(11) = ALTUNIT
ParseStr(12) = GIODAL
ParseStr(13) = GEOUNIT
ParseStr(14) = AGE
ParseStr(15) = DIFFREF
ParseStr(16) = ASTERISK
ParseStr(17) = CHCKSUM
ParseStr(18) = CRLF
Units Batt_VoltI=Volts
Units Batt_VoltF=Volts
Units Batt_V_Drop=Volts
Units PTemp_C=Deg C
Units WS_ms=meters/second
Units WindDir=Degrees
Units BP_mmHg=mV (mmHg)
'Units WaterColumnPressure=mV/V
Units AS_T=mV
Units AS_RH=mV
Units AS_Pt100=mV?
Units US_T=mV
Units US_RH=mV
Units US_Pt100=mV?
Units Xtilt=mV
Units Ytilt=mV
Units TermStringT(8)=Deg C
Units CNR1_SWin=mV
Units CNR1_SWin =mV
Units CNR1_SWout=mV
Units CNR1_LWin=mV
Units CNR1_LWout=mV
Units CNR1_Pt100=mV
'Define Data Tables
DataTable (InstantaneousTable,True,1)
Sample(1,BP_mmHg,FP2)
Sample(1,AS_Pt100,FP2)
Sample(1,AS_T,FP2)
Sample(1,AS_RH,FP2)
WindVector (1,WS_ms,WindDir,FP2,False,0,0,0)
Sample(1,InstantDataTerminator,String)
EndTable
DataTable(TxBufferTable,True,SummerTableBuffer)
Sample(1,TxBufferString, String)
EndTable
DataTable(TableSummerTx,True,1,)'SummerTableBuffer)'then, size = 1
DataInterval(0,SummerTxRate*ScanRate,Sec,1)
Average(1,BP_mmHg,FP2,False)
' StdDev(1,BP_mmHg,FP2,False)
Average(1,AS_Pt100,FP2,False)
' StdDev(1,AS_Pt100,FP2,False)
Average(1,AS_T,FP2,False)'AS_ = Rotronics Aspirated Shield
' StdDev(1,AS_T,FP2,False)
Average(1,AS_RH,FP2,False)' This is conceptually wrong
' StdDev(1,AS_RH,FP2,false)' This is conceptually wrong
WindVector (1,WS_ms,WindDir,FP2,False,0,0,0)
FieldNames("WS_ms_S_WVT,WindDir_D1_WVT,WindDir_SD1_WVT")'From manual:"Mean hori
41
Average(1,CNR1_SWin,FP2,False)
' StdDev(1,CNR1_SWin,FP2,False)
Average(1,CNR1_SWout,FP2,False)
' StdDev(1,CNR1_SWout,FP2,False)
Average(1,CNR1_LWin,FP2,False)
' StdDev(1,CNR1_LWin,FP2,False)
Average(1,CNR1_LWout,FP2,False)
' StdDev(1,CNR1_LWout,FP2,False)
Average(1,CNR1_Pt100,FP2,False)
' StdDev(1,CNR1_Pt100,FP2,False)
Sample(1,SnowHeight,FP2)
Sample(1,SnowHeightQuality,FP2)
Sample(1,Ablation,FP2)
Sample(1,AblationQuality,FP2)
Average(1,Ablation_meter,FP2,False)
' StdDev(1,Ablation_meter,FP2,False)
Average(8,TermStringT(),FP2,False)''check if ok this way of passing arrays
FieldNames("Thermistor_1,Thermistor_2,Thermistor_3,Thermistor_4,Thermistor_5,Th
Average(1,Xtilt,FP2,False)
' StdDev(1,Xtilt,FP2,False)
Average(1,Ytilt,FP2,False)
' StdDev(1,Ytilt,FP2,False)
Sample(1,TIME,String)
Sample(1,LAT,String)
Sample(1,LONGI,String)
Sample(1,ALTDE,String)
Sample(1,NUMSATS,String)
Sample(1,HDP,String)
Average(1,currents(3),FP2,False)
Average(1,US_Pt100,FP2,False)
' StdDev(1,US_Pt100,FP2,False)
Average(1,US_T,FP2,False)'US_ = Rotronics Un-Aspirated Shield
' StdDev(1,US_T,FP2,False)
Average(1,US_RH,FP2,False)
' StdDev(1,US_RH,FP2,false)
Maximum(1,Batt_VoltI,FP2,False,False)
Minimum(1,Batt_VoltF,FP2,False,False)
Average(1,Batt_V_Drop,FP2,False)
Sample(1,SummerDataTerminator,String)
EndTable
DataTable(TableWinterTx,True,1)'WinterTableBuffer)'then, size = 1
DataInterval(0,WinterTxRate*ScanRate,Sec,1)
Average(1,BP_mmHg,FP2,False)
' StdDev(1,BP_mmHg,FP2,False)
Average(1,AS_Pt100,FP2,False)
' StdDev(1,AS_Pt100,FP2,False)
Average(1,AS_T,FP2,False)'AS_ = Rotronics Aspirated Shield
' StdDev(1,AS_T,FP2,False)
Average(1,AS_RH,FP2,False)' This is conceptually wrong
' StdDev(1,AS_RH,FP2,false)' This is conceptually wrong
WindVector (1,WS_ms,WindDir,FP2,False,0,0,0)
FieldNames("WS_ms_S_WVT,WindDir_D1_WVT,WindDir_SD1_WVT")'From manual:"Mean hori
Average(1,CNR1_SWin,FP2,False)
' StdDev(1,CNR1_SWin,FP2,False)
Average(1,CNR1_SWout,FP2,False)
' StdDev(1,CNR1_SWout,FP2,False)
Average(1,CNR1_LWin,FP2,False)
' StdDev(1,CNR1_LWin,FP2,False)
Average(1,CNR1_LWout,FP2,False)
' StdDev(1,CNR1_LWout,FP2,False)
Average(1,CNR1_Pt100,FP2,False)
' StdDev(1,CNR1_Pt100,FP2,False)
42
Sample(1,SnowHeight,FP2)
Sample(1,SnowHeightQuality,FP2)
Sample(1,Ablation,FP2)
Sample(1,AblationQuality,FP2)
Average(1,Ablation_meter,FP2,False)
' StdDev(1,Ablation_meter,FP2,False)
Average(8,TermStringT(),FP2,False)''check if ok this way of passing arrays
FieldNames("Thermistor_1,Thermistor_2,Thermistor_3,Thermistor_4,Thermistor_5,Th
Average(1,Xtilt,FP2,False)
' StdDev(1,Xtilt,FP2,False)
Average(1,Ytilt,FP2,False)
' StdDev(1,Ytilt,FP2,False)
Sample(1,TIME,String)
Sample(1,LAT,String)
Sample(1,LONGI,String)
Sample(1,ALTDE,String)
Sample(1,NUMSATS,String)
Sample(1,HDP,String)
Average(1,currents(3),FP2,False)
Average(1,US_Pt100,FP2,False)
' StdDev(1,US_Pt100,FP2,False)
Average(1,US_T,FP2,False)'US_ = Rotronics UN-Aspirated Shield
' StdDev(1,US_T,FP2,False)
Average(1,US_RH,FP2,False)
' StdDev(1,US_RH,FP2,false)
Maximum(1,Batt_VoltI,FP2,False,False)
Minimum(1,Batt_VoltF,FP2,False,False)
Average(1,Batt_V_Drop,FP2,False)
Sample(1,WinterDataTerminator,String)
EndTable
DataTable(TableMem,True,-1)
DataInterval(0,MemSaveRate*ScanRate,Sec,100)'are those many lapses needed?
CardOut(0,-1)
Average(1,BP_mmHg,IEEE4,False)
Average(1,AS_Pt100,IEEE4,False)
Average(1,AS_T,IEEE4,False)'AS_ = Rotronics Aspirated Shield
Average(1,AS_RH,IEEE4,False)
WindVector(1,WS_ms,WindDir,FP2,False,0,0,0)
FieldNames("WS_ms_S_WVT,WindDir_D1_WVT,WindDir_SD1_WVT")'From manual:"Mean hori
Average(1,CNR1_SWin,IEEE4,False)
Average(1,CNR1_SWout,IEEE4,False)
Average(1,CNR1_LWin,IEEE4,False)
Average(1,CNR1_LWout,IEEE4,False)
Average(1,CNR1_Pt100,IEEE4,False)
Sample(1,SnowHeight,FP2)
Sample(1,SnowHeightQuality,FP2)
Sample(1,Ablation,FP2)
Sample(1,AblationQuality,FP2)
Average(1,Ablation_meter,FP2,False)
Average(8,TermStringT(),IEEE4,False)''check if ok this way of passing arrays
FieldNames("Thermistor_1,Thermistor_2,Thermistor_3,Thermistor_4,Thermistor_5,Th
Average(1,Xtilt,FP2,False)
Average(1,Ytilt,FP2,False)
Sample(1,TIME,String)
Sample(1,LAT,String)
Sample(1,HEMINS,String)
Sample(1,LONGI,String)
Sample(1,HEMIEW,String)
Sample(1,ALTDE,String)
Sample(1,ALTUNIT,String)
Sample(1,GIODAL,String)
Sample(1,GEOUNIT,String)
43
Sample(1,QUAL,String)
Sample(1,NUMSATS,String)
Sample(1,HDP,String)
Average(1,US_Pt100,IEEE4,False)
Average(1,US_T,IEEE4,False)'US_ = Rotronics UN-Aspirated Shield
Average(1,US_RH,IEEE4,False)
Average(1,PTemp_C,IEEE4,False)
Maximum(1,Batt_VoltI,IEEE4,False,False)
Minimum(1,Batt_VoltF,IEEE4,False,False)
Average(4,Currents(),FP2,False)
FieldNames("Battery_current_avg,Solar_Panel_current_avg,Fan_current_avg,Tx+GPS_
EndTable
DataTable(TableDiagnostics, True, -1)
DataInterval(0,DiagnosticsRate,hr,100)
CardOut(0,-1)
Sample(1,status.StationName,String)
Sample(1,status.StartTime,NSEC)
Sample(1,status.RunSignature,uint2)
Sample(1,LoggerOSrev,String)
Sample(1,status.Low12VCount,Uint2)
Average(1,PTemp_C,FP2,False)
StdDev(1,PTemp_C,FP2,False)
Average(1,Batt_VoltI,FP2,False)
Average(1,Batt_VoltF,FP2,False)
Average(1,Batt_V_Drop,FP2,False)
Maximum(1,Batt_VoltI,FP2,False,False)
Minimum(1,Batt_VoltF,FP2,False,False)
Average(4,Currents(),FP2,False)
FieldNames("Battery_current_avg,Solar_Panel_current_avg,Fan_current_avg,Tx+GPS_
StdDev(4,Currents(),FP2,False)
FieldNames("Battery_current_std,Solar_Panel_current_std,Fan_current_std,Tx+GPS_
Totalize(1,TxInitializeOk,FP2,False)
Totalize(1,GarminInitOk,FP2,False)
Sample(1,SentWithSuccess,FP2)
Sample(1,SendRecordBacklog,FP2)
Sample(1,DiagnDataTermninator,String)
EndTable
'Declaration of subroutines
Sub TxModuleInit
If NOT (SummerTxRate OR WinterTxRate OR (GPSType="N")) Then ExitSub
TxInitializeOk = False
If NOT TxInitializeOk Then
SerialOpen(ComRS232,19200,0,0,400)
SerialOut(ComRS232,"A","",25,20)' to allow 5 secs for the Iridium Module to
For TxInitilizeAttempt = 1 To TxMaxInitAttempts
'
TxInitializeOk = False
'
ExitFor
'
EndIf'
SerialOut(ComRS232,"TE1"+CHR(13)+CHR(10),"",1,10) 'should be default but d
SerialOut(ComRS232,"ATV1"+CHR(13)+CHR(10),"",1,10)' FIXME!! Then RS232Echo
If SerialOut(ComRS232,"AT"+CHR(13)+CHR(10),"OK"+CHR(13)+CHR(10),1,10) Then
If SerialOut(ComRS232,"ATI4"+CHR(13)+CHR(10),"IRIDIUM 9600 Family"+CHR(13)
'Delay(0,1,sec)'\RREEMMOOVVEE!!!!
'SerialFlush(ComRS232)'needed to clean up the rest of the unused answer to
If TxModuleATok AND True AND TxTypeNAL960x Then 'FIXME!! RS232EchoOk
TxInitializeOk = True
ExitFor
Else
TxInitializeOk = False
44
EndIf
Next
SerialClose(ComRS232)
EndIf
EndSub
Sub IridiumTx
If NOT (SummerTxRate OR WinterTxRate OR (GPSType="N")) Then ExitSub
Call TxModuleInit
If NOT TxInitializeOk Then
SerialClose(ComRS232)
ExitSub
EndIf
SerialOpen(ComRS232,19200,0,0,400)
If SerialOut(ComRS232,"AT*S=1"+CHR(13)+CHR(10),"OK"+CHR(13)+CHR(10),1,10) Then
If SerialOut(ComRS232,"AT+SBDD0"+CHR(13)+CHR(10),"0",1,10) Then TxMObuffCleare
If SerialOut(ComRS232,"AT+SBDWT"+CHR(13)+CHR(10),"READY" + CHR(13) + CHR(10),
SerialOutBlock (ComRS232,TxString+CHR(13),Len(TxString)+10)
If SerialOut(ComRS232,"","0"+CHR(13)+CHR(10),1,100) Then TxMOuploaded = True
EndIf
If NOT (TxMObuffCleared AND TxMOuploaded AND TxModuleRFon) Then
SerialClose(ComRS232)
ExitSub
EndIf
Timer(1,sec,2)
Do
'\GPc1 = GPc1+1
TxTimeoutTimer = Timer(1,sec,4)
If TxTimeoutTimer >= TxTimeout Then 'the = is needed because the timer has a
Timer(1,sec,3)
SerialClose(ComRS232)
ExitSub
EndIf
SerialFlush(ComRS232)
If SerialOut(ComRS232,"AT+CIER=1,1,1,0"+CHR(13)+CHR(10),"OK"+CHR(13)+CHR(10)
Do
TxTimeoutTimer = Timer(1,sec,4)
If TxTimeoutTimer >= TxTimeout Then 'the = is needed because the timer has
Timer(1,sec,3)
SerialClose(ComRS232)
ExitSub
EndIf
SerialIn(TxModuleReply,ComRS232, TxTimeout*100, CHR(13)+CHR(10),15)' put h
If InStr(1,TxModuleReply,"+CIEV:0,",4) Then TxRSSI = Mid(TxModuleReply, In
If InStr(1,TxModuleReply,"+CIEV:1,",4) Then TxSvcAvail = Mid(TxModuleReply
Loop Until TxSvcAvail AND TxRSSI > 0
If SerialOut(ComRS232,"AT+CIER=0,1,1,0"+CHR(13)+CHR(10),"OK"+CHR(13)+CHR(10)
SerialFlush(ComRS232)
If NOT TxAllowed Then ExitDo
TxSendAttempts=TxSendAttempts+1
SBDsession = True'\
SerialOut(ComRS232,"AT+SBDI"+CHR(13),"",1,10)
SerialOut(ComRS232,"","+SBDI:",1,6000)' WAIT up to 1 minute for the outcome
SerialIn(TxModuleReply,ComRS232, 0, 13, 40)
SplitStr(SBDIparsed(1),TxModuleReply,CHR(44),6,0)
If SBDIparsed(1)="1" AND SBDIparsed(2) <> LastSuccessfulMOMSN Then
TxSendSuccess = True
SentWithSuccess = SentWithSuccess + 1
LastSuccessfulMOMSN = SBDIparsed(2)
45
Else
TxSendSuccess = False
TxSvcAvail = false
TxRSSI = 0
EndIf
SBDsession = False'\
Loop Until TxSendSuccess' actually, it keeps trying until TxTimeout
TxTimeTaken = TxTimeoutTimer
Timer(1,sec,3)
SerialClose(ComRS232)
EndSub
'*******************************************************************************
' The main program. On datalogger power-on and after a few seconds needed for th
' lights the LED for 3 seconds to notify that the station is up and running. The
' the only SlowSequence Scan.
'*******************************************************************************
BeginProg
'light the LED for 2 seconds ("main program started")
PortSet(5,true)
Delay(0,500,msec)
PortSet(5,false)
'SetStatus ("USRDriveSize",8192)' for use with OpenFile when implementing bina
Low_Batt = True'will be cleared after the first scan if battery is ok. Prevent
FastScanMode = False' True
FastScanCount = FastScanReps
IsSummer = False
TxAllowed = True
WinterDataTerminator="!W"
SummerDataTerminator="!S"
InstantDataTerminator="!I"
DiagnDataTermninator="!D"
LoggerOSrev = Right(Status.OSVersion,2)' it assumes that Cambell will keep num
If LoggerOSrev < 14 Then TimersUnitMult = 1000000 Else TimersUnitMult = 1'Here
Battery(Batt_VoltI)
' If Batt_VoltI > LoBattThre + LoBattResHyst Then Low_Batt = False
GPSinUse = UpperCase(GPSType)
BestHDPseen = 100
sBestHDPseen = 100
TxInitializeOk=False
PortGet(C5status,8)
SerialOpen(com2,GarminBaudRate,0,0,1000)'due to a possible bug in the CR1000 O
'*******************************************************************************
' The main Scan calls the Measure subroutine to do the actual measurement job, t
' Iridium module. Depending on which GPS receiver is being used (the Trimble or
' it can wait for the GPS of the Iridium module to return a valid position and t
' proceeds issuing the CallTable commands for the TableMem AND for the TableTxXx
' season. Then if needed it acesses the relevant TableTxXxxxxx, assembles the me
' module, uploads it, initiates the SBD transfer by sending the AT+SBDRB or AT+S
' until either it succeeds or the Max_SBD_Attempts is reached. Finally it calls
'*******************************************************************************
Scan(FastScanRate,Sec,1,0)
46
' If Batt_VoltI > LoBattThre + LoBattResHyst Then Low_Batt = False
'Initial Datalogger Battery Voltage measurement Batt_Volt (do this before turn
' If Batt_VoltI = -999 Then Battery(Batt_VoltI)
PulsePort(5,10000)
'Excites Vx3 to allow the NT1400 to thermally stabilize
If (TimeIntoInterval(0,ScanRate,sec) OR FastScanMode) Then
ExciteV(Vx3,2500,0)
Timer(3,sec,2)
TimeSinceVx3on = Timer(3,sec,4)
Else
Timer(3,sec,3)'we won't need to also switch Vx3 off explicitly: it is done
EndIf
'deals with the fastscan state
''
C5statusPrev = C5status'to deal with the hardware FastScan switch in a saf
''
'PortsConfig(&B1000,&B0000)
''
PortGet(C5status,5)'ReadIO(C5status, &B10000)'
''
If C5status AND NOT C5statusPrev Then FastScanMode = True
''
If C5statusPrev AND NOT C5status Then
''
FastScanMode = False
''
LastFastScan = True
''
EndIf
If FastScanMode AND FastScanCount = 0 Then FastScanCount = FastScanReps
If NOT FastScanMode AND FastScanCount > 0 Then FastScanCount = 0
If FastScanMode AND FastScanCount > 0 Then FastScanCount = FastScanCount - 1
If FastScanMode AND FastScanCount = 0 Then LastFastScan = True
If FastScanMode AND FastScanCount = 0 Then FastScanMode = False
'Starts the Rotronics aspirated shield fan
If (TimeIntoInterval(ScanRate-AdvanceFanStart*FastScanRate,ScanRate,sec) OR
If Batt_VoltI = -999 Then Battery(Batt_VoltI)
If NOT Low_Batt Then
PortSet(8,true)
Asp_fan_on = True
EndIf
EndIf
'if needed, it powers up the Tx module and initializes its integrated GPS re
If (GPSinUse = "G" OR GPSinUse = "N") Then
If Batt_VoltI = -999 Then Battery(Batt_VoltI)
If NOT Low_Batt Then
If IsSummer Then
If (TimeIntoInterval(SummerGPSrate*ScanRate-AdvanceGPSstart,SummerGPSr
If (GPSinUse = "G") Then
PortSet(6,True)
TxModuleGPSPowerOn = True
'\'SerialOpen(com2,4800,0,0,150)'due to a possible bug in the CR10
SerialFlush(Com2)
GPGGAsentence=""
SerialIn (GPGGAsentence,COM2,GarminWarmup * 100,-1,10)
'\'SerialClose(com2)
If Len(GPGGAsentence)>0 Then
GarminInitOk = True
Else
GarminInitOk = False
EndIf
EndIf
If (GPSinUse = "N") Then
47
temptemp=temptemp+1
PortSet(6,True)
TxModuleGPSPowerOn = True
SerialOpen(ComRS232,19200,0,0,100)
SerialFlush(ComRS232)
Call TxModuleInit
If TxInitializeOk Then
SerialOut(ComRS232,"AT*S=0"+CHR(13)+CHR(10),"",1,10)
SerialOut(ComRS232,"AT+PP=1"+CHR(13)+CHR(10),"",1,10)'should be
SerialOut(ComRS232,"AT+PNAV=1"+CHR(13)+CHR(10),"",1,10)'should b
SerialClose(ComRS232)
EndIf
EndIf
If NOT(GarminInitOk OR TxInitializeOk) Then
TxPowerDueForSwOff = True
EndIf
EndIf
Else'else it is winter
If (TimeIntoInterval(WinterGPSrate*ScanRate-AdvanceGPSstart,WinterGPSr
If (GPSinUse = "G") Then
PortSet(6,True)
TxModuleGPSPowerOn = True
'\'SerialOpen(com2,4800,0,0,150)'due to a possible bug in the CR10
SerialFlush(Com2)
GPGGAsentence=""
SerialIn (GPGGAsentence,COM2,GarminWarmup * 100,-1,10)
'\'SerialClose(com2)
If Len(GPGGAsentence)>0 Then
GarminInitOk = True
Else
GarminInitOk = False
EndIf
EndIf
If (GPSinUse = "N") Then
temptemp=temptemp+1
PortSet(6,True)
TxModuleGPSPowerOn = True
SerialOpen(ComRS232,19200,0,0,100)
SerialFlush(ComRS232)
Call TxModuleInit
If TxInitializeOk Then
SerialOut(ComRS232,"AT*S=0"+CHR(13)+CHR(10),"",1,10)
SerialOut(ComRS232,"AT+PP=1"+CHR(13)+CHR(10),"",1,10)'should be
SerialOut(ComRS232,"AT+PNAV=1"+CHR(13)+CHR(10),"",1,10)'should b
SerialClose(ComRS232)
EndIf
EndIf
If NOT(GarminInitOk OR TxInitializeOk) Then
TxPowerDueForSwOff = True
EndIf
EndIf
EndIf
EndIf
EndIf
'Executes the measurements *************************************************
'***************************************************************************
If Batt_VoltI = -999 Then Battery(Batt_VoltI)
If (FastScanMode AND FastScanCount > 0) OR TimeIntoInterval(0,ScanRate,sec)
SW12(True)'Enabling switched 12V supply
SW12Von = True
48
Timer(2,sec,2)
TimeSince12Von = Timer(2,sec,4)
'Do the measurements
'\'SerialOpen(com2,4800,0,0,150)'due to a possible bug in the CR1000 OS, i
'Wiring Panel Temperature measurement PTemp_C:
PanelTemp(PTemp_C,_50Hz)
ExciteV(Vx3,2500,0)'This MUST be right after any bridge, P107 and Pa
'get a feel of the season...
RealTime(RTime)
If DayOfYear >= BeginOfSummer AND DayOfYear < BeginOfWinter Then IsSummer = Tr
'open COM2 for the Garmin GPS (com2 gets closed when SW12 goes off, so thet
'
SerialOpen(com2,4800,0,0,2000)
'do now whatever needs the 12V switched supply to be ON but doesn't use the
'Enables the MUX by bringing its _RES input high and then explicitly resets t
PortSet(1,1) 'brings the _RES input on the MUX high (means the MUX is in ope
Delay(0,1,sec)'waits for the MUX to be fully awake after SW12V came up and _R
PulsePort(1,20000) 'pulses low the _RES input on the MUX for 20 ms
'advances to MUX differential channel 1 and measures Young Wind Direction Sens
'(optimized solution to to share the same MUX position). So, first measure Win
PulsePort(2,5000)
Delay(0,20,msec)' allows for settling time
PulseCount(WS_ms,1,1,1,1,0.098,0)
BrHalf(WindDir,1,mV2500,14,1,1,2500,True,0,_50Hz,355,0)''consider using fast
ExciteV(Vx3,2500,0)'This MUST be right after any bridge, P107 and Pa
If WindDir>=360 Then WindDir=0
'...then measure BP_mmHg from the CS100. This must never occur less than 1 se
VoltSe(BP_mmHg,1,mV2500,13,1,0,_50Hz,0.2,600.0)
BP_mmHg=BP_mmHg*0.75006
'cycles through and measures the 8 termistors in the termistor string and the
For it = 1 To TermStringSz Step 2
'first measure the thermistors
PulsePort(2,5000)' COULD THIS REPLACE THE FOLLOWING DELAY???
Delay(0,20,msec)' allows for settling time -> don't remove or measures gets
Therm107 (TermStringT(it),1,15,Vx3,20000,_50Hz,1.0,0)
Therm107 (TermStringT(it+1),1,16,Vx3,20000,_50Hz,1.0,0)
'
Delay(0,300,msec)
'then measure the current shunts located at the same MUX position
VoltDiff (Currents((it+1)/2),1,mV7_5,7,True,0,_50Hz,200,0)'200 is for a sh
Next
ExciteV(Vx3,2500,0)'This MUST be right after any bridge, P107 and Pa
'advances to MUX differential channel 11 and measures both the Xtilt and Ytilt
PulsePort(2,5000)
Delay(0,20,msec)
VoltSe(Xtilt,1,1,13,1,0,_50Hz,1,0)
VoltSe(Ytilt,1,1,14,1,0,_50Hz,1,0)
'advance the MUX to measure the 4 radiation signals from the CNR1 (can too be
PulsePort(2,5000)
49
Delay(0,20,msec)' allows for settling time ... needed??
VoltDiff (CNR1_SWin,1,mV25,7,True,0,_50Hz,1,0)' may go out of range with ver
PulsePort(2,5000)
Delay(0,20,msec)' allows for settling time ... needed??
VoltDiff (CNR1_LWin,1,mV7_5,7,True,0,_50Hz,1,0)' may go out of range with ve
PulsePort(2,5000)
Delay(0,20,msec)' allows for settling time ... needed??
VoltDiff (CNR1_SWout,1,mV25,7,True,0,_50Hz,1,0)
PulsePort(2,5000)
Delay(0,20,msec)' allows for settling time ... needed??
VoltDiff (CNR1_LWout,1,mV7_5,7,True,0,_50Hz,1,0)
BrHalf4W (temp,1,mV25,mV25,3,Vx2,1,2035,True ,True ,0,_50Hz,1.0,0)'CNR1 Pt100
ExciteV(Vx3,2500,0)'This MUST be right after any bridge, P107 and Pa
PRT (CNR1_Pt100,1,temp,1.0,0)
'SR50 Sonic Ranging Sensor (SDI-12 Output) measurements DT, TCDT, and DBTCDT:
While TimeSince12Von < SR50Warmup
TimeSince12Von = Timer(2,sec,4)
Wend
If FastScanMode OR LastFastScan OR TimeIntoInterval(0,ScanRate,sec) Then
SDI12Recorder(SR50_SnowHeight(),7,SnowHeightSR50address,"M1!",1.0,0)'Snowh
SDI12Recorder(SR50_Ablation(),7,AblationSR50address,"M1!",1.0,0)
EndIf
'Rotronics aspirated shield sensor suite measurement AS_T and AS_RH (the fan i
PulsePort(2,5000)
Delay(0,20,msec)
While TimeSince12Von < HygroClipWarmup
TimeSince12Von = Timer(2,sec,4)
Wend
VoltSe(AS_T,1,6,14,0,0,_50Hz,1,0)'autorange, no gnd offset correction
VoltSe(AS_RH,1,1,13,1,0,_50Hz,1,0)
BrHalf4W (temp,1,mV25,mV25,1,Vx2,1,2035,True ,True ,0,_50Hz,1.0,0)'Rotronic Pt
ExciteV(Vx3,2500,0)'This MUST be right after any bridge, P107 and Pa
If Asp_fan_on Then Aspirated_Meas = True Else Aspirated_Meas = False' so tha
FanPowerDueForSwOff = True'If NOT (FastScanMode) Then FanPowerDueForSwOff =
''
PortSet(8,false)
''
Asp_fan_on = False
''
EndIf
AS_T=AS_T*.1
AS_RH=AS_RH*.1
PRT (AS_Pt100,1,temp,1.0,0)
'Rotronics UN-aspirated shield sensor suite measurement US_T and US_RH
PulsePort(2,5000)
Delay(0,20,msec)
VoltSe(US_T,1,6,14,0,0,_50Hz,1,0)'autorange, no gnd offset correction
VoltSe(US_RH,1,1,13,1,0,_50Hz,1,0)
BrHalf4W (temp,1,mV25,mV25,5,Vx2,1,2035,True ,True ,0,_50Hz,1.0,0)'Rotronic Pt
ExciteV(Vx3,2500,0)'This MUST be right after any bridge, P107 and Pane
US_T=US_T*.1
US_RH=US_RH*.1
PRT (US_Pt100,1,temp,1.0,0)
'Now the NT1400 water column pressure transducer
PulsePort(2,5000)
Delay(0,20,msec)
ExciteV(Vx3,2500,0)
While TimeSinceVx3on < NT1400Warmup
TimeSinceVx3on = Timer(3,sec,4)
Wend
BrFull (ablation_meter,1,mV250,7,Vx3,1,2500,True ,True ,10000,_50Hz,1.0,0)
Timer(3,sec,3)
50
'resets the MUX (so that even if 12V switched is powered, the MUX itself shoul
PortSet(1,false)
'do now whatever needs the 12V switched supply to be ON and requires warm-up, bu
'GPS work for Garmin (G) or NAL (N) units, or both!
PreParseStr(7) = 0
PreParseStr(9) = 0
'The Garmin part finds its com2 already open and the prog closes it afterwar
'around the CR1000 bug causing higher power draw if we open/close com2 here
If GarminInitOk AND TxModuleGPSpowerOn AND (GPSinUse = "G") Then
GGPSFLAG = true
GPGGAsentence = ""
SerialFlush(com2)'added yesterday
If SerialOut(com2,"","$GPGGA",1,250) Then
SplitStr(PreParseStr(1),GPGGAsentence,CHR(44),15,5)
PreQual_FP = PreParseStr(7)'we need to do this explicit conversion to
PreHDP_FP = PreParseStr(9)'we need to do this explicit conversion to f
If PreQual_FP > 0 AND PreHDP_FP > 0 AND PreHDP_FP <= BestHDPseen Then
SplitStr(ParseStr(1),GPGGAsentence,CHR(44),15,5)
BestHDPseen = HDP
'
ElseIf NOT (BestHDPseen < 100) Then'so to avoid deleting a previously
'
For ParseStrIT=1 To 15
'
ParseStr(ParseStrIT)=""
'
Next
EndIf
If NOT (BestHDPseen < 100) Then'so to avoid deleting a previously obta
For ParseStrIT=1 To 15
ParseStr(ParseStrIT)=""
Next
EndIf
EndIf
GGPSFLAG = false
TxPowerDueForSwOff = True
EndIf
'The NAL part (it opens and closes his ComRS232 port itself)
If TxInitializeOk AND TxModuleGPSpowerOn AND (GPSinUse = "N") Then
NGPSFLAG = true
GPGGAsentence = ""
SerialOpen(ComRS232,19200,0,0,150)
SerialOut(ComRS232,"AT"+CHR(13)+CHR(10),"",1,10)'this is to let the CR1000
SerialOut(ComRS232,"AT+PA=1"+CHR(13)+CHR(10),"",1,10)
If SerialOut(ComRS232,"","$GPGGA",1,150) Then
SerialIn(GPGGAsentence,ComRS232,150,"*",150)'was 13
SplitStr(PreParseStr(1),GPGGAsentence,CHR(44),15,5)
PreQual_FP = PreParseStr(7)'we need to do this explicit conversion to
PreHDP_FP = PreParseStr(9)'we need to do this explicit conversion to f
If PreQual_FP > 0 AND PreHDP_FP > 0 AND PreHDP_FP <= BestHDPseen Then
SplitStr(ParseStr(1),GPGGAsentence,CHR(44),15,5)
BestHDPseen = HDP
EndIf
'''
If NOT (sBestHDPseen < 100) Then'so to avoid deleting a previously
'''
For sParseStrIT=1 To 15
'''
sParseStr(sParseStrIT)=""
'''
Next
'''
EndIf
Else
51
TxInitializeOk = False
EndIf
If NOT (FastScanMode OR LastFastScan) Then
SerialOut(ComRS232,"AT+PP=0"+CHR(13)+CHR(10),"",1,10)
EndIf
SerialClose(ComRS232)
NGPSFLAG = false
TxPowerDueForSwOff = True
ElseIf (FastScanMode OR LastFastScan)
Call TxModuleInit
If TxInitializeOk Then
SerialOut(ComRS232,"AT*S=0"+CHR(13)+CHR(10),"",1,10)
SerialOut(ComRS232,"AT+PP=1"+CHR(13)+CHR(10),"",1,10)'should be sent as
SerialOut(ComRS232,"AT+PNAV=1"+CHR(13)+CHR(10),"",1,10)'should be sent a
SerialClose(ComRS232)
EndIf
If NOT (BestHDPseen < 100) Then'so to avoid deleting a previously obtained
For ParseStrIT=1 To 15
ParseStr(ParseStrIT)=""
Next
EndIf
EndIf
'Final Battery Voltage measurement Batt_Volt and Low_Batt check (do this befor
Battery(Batt_VoltF)
Batt_V_Drop = Batt_VoltI - Batt_VoltF
If Batt_VoltF < LoBattThre Then Low_Batt = True
If Batt_VoltF >= LoBattThre + LoBattResHyst Then Low_Batt = False
'***************************************************************************
'***************************************************************************
'\'SerialClose(com2)
Timer(2,sec,3)
SW12(False)'Disables switched 12V supply
SW12Von=False
EndIf
If TimeIntoInterval(0,ScanRate,sec) Then
CallTable(TableDiagnostics)
CallTable(TableMem)
' If TableMem.Output(1,1) Then
'
BestHDPseen = 100
'
EndIf
If FanPowerDueForSwOff AND NOT FastScanMode
PortSet(8,false)
Asp_fan_on = False
FanPowerDueForSwOff = False
EndIf
If IsSummer Then
CallTable(TableSummerTx)
If TableSummerTx.Output(1,1) Then
BestHDPseen = 100
TxBufferString=""
TableInstantaneousString=""
TxStringUnstripped=""
TxString=""
GetRecord(TxBufferString,TableSummerTx,1)
If AppendInstantaneous AND TimeIntoInterval(0, HoursInstantaneous, hr) T
CallTable(InstantaneousTable)
GetRecord(TableInstantaneousString,InstantaneousTable,1)
52
TxBufferString=Left(TxBufferString, Len(TxBufferString)-2)+","+Mid(Tab
EndIf
CallTable(TxBufferTable)
If SendRecordBacklog < SummerTableBuffer Then SendRecordBacklog = SendRe
If TimeIntoInterval(0,DiagnosticsRate,hr) AND SendRecordBacklog < Summ
TxBufferString=""
GetRecord(TxBufferString,TableDiagnostics,1)
CallTable(TxBufferTable)
SendRecordBacklog = SendRecordBacklog + 1
EndIf
For SendRecordIT = SendRecordBacklog To 1 Step -1
TxString=""
MpFLAG=true'remove!!
Delay(0,2,sec)'remove!!
'Call AppendInstantMeas
'Cal
GetRecord(TxStringUnstripped,TxBufferTable,SendRecordIT)
StripStringStart = InStr(1,TxStringUnstripped,CHR(34)+CHR(34),4)
For StringStripperIT=StripStringStart To Len(TxStringUnstripped)-5'5 i
StringChar=Mid(TxStringUnstripped, StringStripperIT, 1)
If StringChar<>CHR(34) Then TxString=TxString+StringChar
Next StringStripperIT
TxString=TxString+",!M"'*************in summer too
'TxString=Right(TxString,Len(TxString)-InStr(1,TxString,CHR(44),4)+0)
Call IridiumTx
MPFLAG=false'remove!!
If NOT TxSendSuccess Then ExitFor
Next
If SendRecordIT = 0 Then ResetTable(TxBufferTable)
SendRecordBacklog = SendRecordIT
TxPowerDueForSwOff = True
EndIf
EndIf
If NOT IsSummer Then
CallTable(TableWinterTx)
If TableWinterTx.Output(1,1) Then
BestHDPseen = 100
TxBufferString=""
TableInstantaneousString=""
TxStringUnstripped=""
TxString=""
GetRecord(TxBufferString,TableWinterTx,1)
If AppendInstantaneous AND TimeIntoInterval(0, HoursInstantaneous, hr) T
CallTable(InstantaneousTable)
GetRecord(TableInstantaneousString,InstantaneousTable,1)
TxBufferString=Left(TxBufferString, Len(TxBufferString)-2)+","+Mid(Tab
EndIf
CallTable(TxBufferTable)
If SendRecordBacklog < WinterTableBuffer Then SendRecordBacklog = SendRe
If TimeIntoInterval(0,DiagnosticsRate,hr) AND SendRecordBacklog < Wint
TxBufferString=""
GetRecord(TxBufferString,TableDiagnostics,1)
CallTable(TxBufferTable)
SendRecordBacklog = SendRecordBacklog + 1
EndIf
For SendRecordIT = SendRecordBacklog To 1 Step -1
TxString=""
MpFLAG=true'remove!!
Delay(0,2,sec)'remove!!
'Call AppendInstantMeas
'Cal
GetRecord(TxStringUnstripped,TxBufferTable,SendRecordIT)
StripStringStart = InStr(1,TxStringUnstripped,CHR(34)+CHR(34),4)
53
For StringStripperIT=StripStringStart To Len(TxStringUnstripped)-5'5 i
StringChar=Mid(TxStringUnstripped, StringStripperIT, 1)
If StringChar<>CHR(34) Then TxString=TxString+StringChar
Next StringStripperIT
TxString=TxString+",!M"'*************in summer too
'TxString=Right(TxString,Len(TxString)-InStr(1,TxString,CHR(44),4)+0)
Call IridiumTx
MPFLAG=false'remove!!
If NOT TxSendSuccess Then ExitFor
Next
If SendRecordIT = 0 Then ResetTable(TxBufferTable)
SendRecordBacklog = SendRecordIT
TxPowerDueForSwOff = True
EndIf
EndIf
EndIf
If TxPowerDueForSwOff AND NOT (FastScanMode OR LastFastScan) Then
SerialOut(ComRS232,"AT*F"+CHR(13)+CHR(10),"OK",1,100)' to allow 5 secs f
Delay(0,1,sec)
PortSet(6,false)
TxModuleGPSPowerOn = False
TxInitializeOk = False'turn this off??
TxPowerDueForSwOff = False
EndIf
If LastFastScan Then LastFastScan = False
If FanPowerDueForSwOff AND NOT FastScanMode
PortSet(8,false)
Asp_fan_on = False
FanPowerDueForSwOff = False
EndIf
SerialClose(ComRS232)
Batt_VoltI = -999' Batt_VoltF doesn't need such a NODATA value, so it is lef
PulsePort(5,10000)
NextScan
EndProg
54
Appendix E – Telemetry data retrieval program
(Michele Citterio, GEUS)
55
#getdata 1.60f, written by Michele Citterio (mcit@geus.dk) at GEUS, Copenhagen
#coding=cp850
#
#install and use: install pyhton 2.5.2 and pywin32 212, copy this file into an
#empty folder and run it from there. Four files and a folder can be created
#for each IMEI number found when retrievig the emails from the Exchange server:
#1) IMEI#.txt readable comma-separated ascii file - AWS observations
#2) IMEI#-D.txt readable comma-separated ascii file - AWS diagnostics
#3) IMEI#-F.txt readable comma-separated ascii file - malformed msg (from 1.56)
#4) IMEI#-X.txt file with whatever else has been received from that IMEI device
#5) IMEI#/
a folder where individual received email attachments are stored
#One further file msgshash.dat is also created on the first program run and
#updated at every run to store the hashes of already processed mesages, so that
#they can be identified and skipped on later program runs.
#
#revision history:
# 1.51, 10-05-2009 + configured PROMICE 2009 binary format
#
+ configured Quadra Mining 2009 Malmbjerg binary format
#
+ added Python version 2.5.2 check and made Py3k-aware
#
+ some code cleanup of try..except blocks
# 1.52, 11-05-2009 + configured Glaciobasis 2009 Zackenberg Top binary format
# 1.53, 09-06-2009 + configured Glaciobasis 2009 Zackenberg Main binary format
#
+ much improved detection of bin format specification errors
#
+ fixed wrong format specifications 5, 7 and 12
#
+ improved the try..except blocks by setting the error types
#
+ tested for compatibility with up to Python 2.5.4
#
+ improved handling of user's infostores or folders choices
#
+ added warning for binary messages longer than specified
#
+ fixed support of Unicode pathnames, so x:\Søren works now!
# 1.54a, 19/06/2009 + attempted workaround to crash in pywin32 on some machines
# 1.55, 23/09/2009 + fixed 1 h timestamp error. Epochs handling more portable
# 1.60f, 06/10/2009 + added prompt to sort the *.txt files based on timestamps
#
+ fixed crash decoding malformed (too long/short) messages
#
+ truncated messages are decoded using ? for missing values
#
+ added option to put malformed messages in a separate file
#
+ added exceptions handling while opening the *.txt files
#
+ logoff from Exchange server even on unhandled exceptions
#
+ added check for re-delivered messages (Iridium or NAL bug)
#
+ MOMSN is also hashed when detecting duplicates
#
+ use the current user's name as default for Exchange logon
#
+ improved the printed output during the run and at the end
#
+ now uses 128 bits hashes: must retrieve all messages again
#
since -f + do not try to logoff when logon failed due to wrong userid
#
+ pickle is replaced with cPickle for speed
#
+ ctrl-break is also trapped and handled same as ctrl-c
#
56
# known issues: the stats about the processed messages and some screen output
#
while running are wrong (but the data files generated are ok).
#
Also, when user aborts a file write error, the line is still counted as added
#
Cause is known and harmless, will be fixed in 1.60 final.
#
# Updated list of format ID numbers (range of format specifications) in use:
# 1 (5-9), 2 (10-14), 3 (15-19), 4 (20-24)
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import with_statement
try:
import sys
if sys.hexversion >= 0x030000F0:
print ("ERROR: Python 3000 is not supported. Use Python 2.5.4 instead!\n")
sys.exit()
if sys.hexversion < 0x020502F0:
print "WARNING: untested on earlier versions than Python ver. 2.5.2\n"
if sys.hexversion > 0x020504F0:
print "WARNING: untested on later versions than Python ver. 2.5.4\n"
import os
import string
import time
import glob
import hashlib
import cPickle
import calendar
import signal
from bintx import *
try:
import win32api
from win32com.client import Dispatch, pywintypes
except ImportError:
print 'Error - PyWin32 is not installed.'
sys.exit()
except ImportError:
print 'ERROR: needed modules from the standard library are not available. Reinstall
Python\n'
sys.exit()
signal.signal(signal.SIGBREAK, signal.default_int_handler)#to trap ctrl-break
localtestmode = False#True
FilterMalformed = True
HashFunc = hashlib.sha1#before 1.60 hashlib.sha512() was used but this was much
overkill: even with 128 bits
57
#there's about 10^-18 chances of an error after 10^10 messages received...
FormatBytesNum = {}
FormatBytesNum['f'] = 2# value encoded as 2 bytes base-10 floating point (GFP2)
FormatBytesNum['l'] = 4# value encoded as 4 bytes two's complement integer (GLI4)
FormatBytesNum['t'] = 4# timestamp as seconds since 1990-01-01 00:00:00 +0000
encoded as GLI4
FormatBytesNum['g'] = 4# GPS time encoded as GLI4
FormatBytesNum['n'] = 4# GPS latitude encoded as GLI4
FormatBytesNum['e'] = 4# GPS latitude encoded as GLI4
FormatSpec = {}
#GlacioBasis 2009 Top
FormatSpec[10] = [49, "tfffffffffffffffffffffffffffffffffffgneffffffffff", "GlacioBasis 2009
Top 1-h summer message"]
FormatSpec[11] = [56, "tfffffffffffffffffffffffffffffffffffgnefffffffffffffffff", "GlacioBasis
2009 Top 1-h summer message (+ instant.)"]
FormatSpec[12] = [49, "tfffffffffffffffffffffffffffffffffffgneffffffffff", "GlacioBasis 2009
Top 3-h winter message"]
FormatSpec[13] = [56, "tfffffffffffffffffffffffffffffffffffgnefffffffffffffffff", "GlacioBasis
2009 Top 3-h winter message (+ instant.)"]
FormatSpec[14] = [22, "tfffffffffffffffffffff", "GlacioBasis 2009 Top diagnostic
message"]
#GlacioBasis 2009 Main
FormatSpec[20] = [41, "tfffffffffffffffffffffffffffgneffffffffff", "GlacioBasis 2009 Main 1h summer message"]
FormatSpec[21] = [50, "tfffffffffffffffffffffffffffgnefffffffffffffffffff", "GlacioBasis 2009
Main 1-h summer message (+ instant.)"]
FormatSpec[22] = [41, "tfffffffffffffffffffffffffffgneffffffffff", "GlacioBasis 2009 Main 3h winter message"]
FormatSpec[23] = [50, "tfffffffffffffffffffffffffffgnefffffffffffffffffff", "GlacioBasis 2009
Main 3-h winter message (+ instant.)"]
FormatSpec[24] = [22, "tfffffffffffffffffffff", "GlacioBasis 2009 Main diagnostic
message"]
# Win32 epoch is 1st Jan 1601 but MSC epoch is 1st Jan 1970 (MSDN gmtime docs),
same as Unix epoch.
# Neither Python nor ANSI-C explicitly specify any epoch but CPython relies on the
underlying C
# library. CRbasic instead has the SecsSince1990() function.
UnixEpochOffset = calendar.timegm((1970, 1, 1, 0, 0, 0, 0, 1, 0)) #this should always be
0 in CPython on Win32
CRbasicEpochOffset = calendar.timegm((1990, 1, 1, 0, 0, 0, 0, 1, 0))
EpochOffset = UnixEpochOffset + CRbasicEpochOffset
58
#what follows should be turned into methods of a future FormatSpecTable object
FormatSpecAreOK = True
for FormatSpecEntry in FormatSpec.iteritems():
#FormatSpecEntry[1][0]
if FormatSpecEntry[1][0] != len(FormatSpecEntry[1][1]):
print 'WARNING: bad format definition for message type %i (%s):\n format
unconsistency (%i values declared but %i specified)' %(FormatSpecEntry[0],
FormatSpecEntry[1][2],FormatSpecEntry[1][0],len(FormatSpecEntry[1][1]))
FormatSpecAreOK = False#sys.exit()
Length = 1#all messages have a trailing one-byte format ID
for ValueFormat in FormatSpecEntry[1][1]:
try:
Length += FormatBytesNum[ValueFormat]
except KeyError:#ValueFormat is not an existing key
Length = -1
print 'WARNING: Bad format definition for message type %i (%s):\n unknown
symbol "%s"' %(FormatSpecEntry[0], FormatSpecEntry[1][2],ValueFormat)
FormatSpecAreOK = False#sys.exit()
try:#if the byte length was specified in the format configuration, check it
if FormatSpec[FormatSpecEntry[0]][3] != Length:
print 'WARNING: Bad format definition for message type %i (%s):\n length
unconsistency (%i bytes declared but %i expected)' %(FormatSpecEntry[0],
FormatSpecEntry[1][2],FormatSpec[FormatSpecEntry[0]][3],Length)
FormatSpecAreOK = False#sys.exit()
except IndexError:#the byte length was not specified in the format configuration, so set
it now
FormatSpec[FormatSpecEntry[0]].append(Length)#it initializes a further element in
the table: the message length in bytes
if not FormatSpecAreOK:
print 'ERROR: the message format specifications need corrections'
sys.exit()
# return Length
UnicodeEncoding = 'cp850'
BaseDir = os.getcwd()
#BaseDir = BaseDir.encode(UnicodeEncoding)
try:
with open(BaseDir + '\\msgshash.dat', 'rb') as msgshash:
IsFirstRun = False
SeenMessageHashes = cPickle.load(msgshash)
except IOError:
IsFirstRun = True
print 'WARNING: msgshash.dat not found. Already processed messages (if any) may
be duplicated\n'
59
SeenMessageHashes = []
SeenMessageHashesPreviousRuns = SeenMessageHashes[:]#TODO learn better why this
is actually required!
AppendedSummer = 0
AppendedWinter = 0
AppendedWithInstant = 0
AppendedDiagnostics = 0
ApendedMalformed = 0
ProcessedInfostoreName = ''
ProcessedFolderName = ''
try:
cdo = Dispatch("MAPI.session")
DeafultLoginName = win32api.GetUserName()
Login_Prompt = 'Enter the login name (defaults to "%s"): ' %DeafultLoginName
LoginName = raw_input(Login_Prompt)
if not LoginName: LoginName = DeafultLoginName
try: #this is to catch all otherwise unhandleld exceptions and logoff from the server
try:
print 'Logging in as %s...' %LoginName,
cdo.Logon(LoginName) # MAPI profile name
LoggedIn = True
print ' OK'
except pywintypes.com_error, errordetails:
print 'ERROR: COM API error %s (%s) - wrong login' %(errordetails[0],
errordetails[1])
sys.exit()
InfoStores=cdo.InfoStores
InfoStoresCount = cdo.InfoStores.Count
print '\nThere are %i infostores available:' %InfoStoresCount
DefaultInfoStore = 'Postkasse - ice'
DefaultInfoStoreNum = 0
#InfoStoreNum = 0
InfoStoresList = []
for it in range(InfoStoresCount):
InfoStoreName = InfoStores[it].Name
InfoStoresList.append(InfoStoreName)
print '%i) %s' %(it+1, InfoStoreName.encode(UnicodeEncoding))
if InfoStoreName == DefaultInfoStore: DefaultInfoStoreNum = it#+1
if DefaultInfoStoreNum:
InfoStore_Prompt = 'Enter the desired infostore [1, %i] (defaults to "%s"): '
%(InfoStoresCount, DefaultInfoStore.encode(UnicodeEncoding))
else:
60
InfoStore_Prompt = 'Enter the desired infostore [1, %i]: ' %InfoStoresCount
while True:
InfoStore = raw_input(InfoStore_Prompt)
if not len(InfoStore): break
try:
InfoStore = int(InfoStore)
if InfoStore < 0: raise ValueError
if InfoStore > InfoStoresCount: raise ValueError
break
except ValueError:
print "WARNING: not in the range [1, %i]" %InfoStoresCount
if not InfoStore:
InfoStoreNum = DefaultInfoStoreNum
else:
InfoStoreNum = InfoStore - 1#needs to be 0-based to be used as an index
try:
ProcessedInfostoreName = cdo.Infostores[InfoStoreNum 0].Name.encode(UnicodeEncoding)
print 'Looking for folders in %s...' %ProcessedInfostoreName,
Folders = cdo.Infostores[InfoStoreNum - 0].RootFolder.Folders
print ' OK'
except:#TODO: restrict the error type
print 'Error - Bad infostore.'
#cdo.logoff
sys.exit()
FoldersCount = Folders.Count
print '\nThere are %i folders available:' %FoldersCount
DefaultFolder = 'Indbakke'
DefaultFolderNum = 0#remove?
FolderNum = 0
FoldersList = []
for it in range(FoldersCount):
FolderName = Folders[it].Name
FoldersList.append(FolderName)
print '%i) %s' %(it+1, FolderName.encode(UnicodeEncoding))
if FolderName == DefaultFolder: DefaultFolderNum = it#+1
if DefaultFolderNum:
Folder_Prompt = 'Enter the desired folder [1, %i] (defaults to "%s"): '
%(FoldersCount, DefaultFolder.encode(UnicodeEncoding))
else:
Folder_Prompt = 'Enter the desired folder [1, %i]: '%FoldersCount
while True:
Folder = raw_input(Folder_Prompt)
if not len(Folder): break
61
try:
Folder = int(Folder)
if Folder < 0: raise ValueError
if Folder > FoldersCount: raise ValueError
break
except ValueError:
print "WARNING: not in the range [1, %i]" %FoldersCount
if not Folder:
FolderNum = DefaultFolderNum
else:
FolderNum = Folder - 1#needs to be 0-based to be used as an index
try:
ProcessedFolderName = Folders[FolderNum 0].Name.encode(UnicodeEncoding)
print 'Looking for messages in %s...' %ProcessedFolderName,
Messages = Folders[FolderNum - 0].Messages
print ' OK'
except:
print 'Error - Bad folder.'
#cdo.logoff
sys.exit()
MessagesCount = Messages.Count
print '\nThere are %i messages available... (wait!)' %MessagesCount
ProcessedMessages = 0
ProcessedAttachments = 0
AppendedLines = 0
SkippedDuplicated = 0
SkippedAlreadyParsed = 0
FoundMalformed = 0
Message = Messages.GetFirst()# ref. http://mail.python.org/pipermail/pythonlist/2004-July/270944.html
ModifiedFiles = []
while Message:# ref. http://mail.python.org/pipermail/python-list/2004July/270944.html
#for Message in Messages:# ref. http://mail.python.org/pipermail/python-list/2004July/270944.html
ProcessedMessages += 1#TODO move to lower down
if 'sbdservice@sbd.iridium.com' in Message.Sender.Name.lower() and
Message.Attachments.Count == 1:
ProcessedAttachments += 1
Attachment = Message.Attachments.Item(1)
AttachmentName = Attachment.Name.lower().encode(UnicodeEncoding)
IMEI = AttachmentName[0:AttachmentName.index('_')]
62
MOMSN =
AttachmentName[AttachmentName.index('_')+1:AttachmentName.index('.')]
ThisIMEIDir = BaseDir + '\\' + IMEI + '\\'#TODO make it more portable using
the path module
if not glob.glob(ThisIMEIDir): #this IMEI has already been seen
os.mkdir(BaseDir + '\\' + IMEI.encode(UnicodeEncoding))#TODO make it
more portable using the path module
Attachment.WriteToFile(ThisIMEIDir + AttachmentName)#TODO add
exceptions handling
with open(ThisIMEIDir + AttachmentName, 'rb') as InFile:#TODO add
exceptions handling
IsTooLong = False
IsTooShort = False
DataLine = InFile.read(420)
if len(DataLine) == 0: break
if DataLine[0].isdigit():
IsKnownBinaryFormat = False
MessageFormatNum = -9999
else:
MessageFormatNum = ord(DataLine[0])
try:
MessageFormat = FormatSpec[MessageFormatNum]
IsKnownBinaryFormat = True
except KeyError:
IsKnownBinaryFormat = False
UnknMsgFormNum = MessageFormatNum
if IsKnownBinaryFormat:#TODO bring all this "if" into the try logic
above
print '%s-%s (binary)' %(IMEI, MOMSN) , MessageFormat[2]
ExpectedMsgLen = FormatSpec[MessageFormatNum][3]
if len(DataLine) < ExpectedMsgLen:
IsTooShort = True
elif len(DataLine) > ExpectedMsgLen:
IsTooLong = True
BinaryMessage = DataLine[1:]
DataLine = '' #this is a bit crap but works... to be fixed when turning the
decoder into a func
BytePointer = 0
for ValueNum in range(0, MessageFormat[0]):#TODO - use an iterator
instead of indexes
ValueBytes = []
ValueBytesNum =
FormatBytesNum[MessageFormat[1][ValueNum]]
if MessageFormat[1][ValueNum] == 'f':
try:
for offset in range(0,ValueBytesNum):
63
ValueBytes.append(ord(BinaryMessage[BytePointer +
offset]))
BytePointer = BytePointer + ValueBytesNum
Value = GFP2toDEC(ValueBytes)
if Value == 8191:
DataLine = DataLine + "NAN"
elif Value == 8190:
DataLine = DataLine + "INF"
elif Value == -8190:
DataLine = DataLine + "-INF"
else:
DataLine = DataLine + str(Value)
#print ValueBytes, Value
except IndexError:
DataLine = DataLine + '?'
if MessageFormat[1][ValueNum] == 'l':
try:
for offset in range(0,ValueBytesNum):
ValueBytes.append(ord(BinaryMessage[BytePointer +
offset]))
BytePointer = BytePointer + ValueBytesNum
Value = GLI4toDEC(ValueBytes)
DataLine = DataLine + str(Value)
if Value == -2147483648:
DataLine = DataLine + "NAN"
else:
DataLine = DataLine + str(Value)
#print ValueBytes, Value
#print ValueBytes, Value
except IndexError:
DataLine = DataLine + '?'
elif MessageFormat[1][ValueNum] == 't':
try:
for offset in range(0,ValueBytesNum):
ValueBytes.append(ord(BinaryMessage[BytePointer +
offset]))
BytePointer = BytePointer + ValueBytesNum
Value = GLI4toDEC(ValueBytes)
DataLine = DataLine + time.strftime("%Y-%m-%d
%H:%M:%S", time.gmtime(Value + EpochOffset)) + ',' + str(Value)
#print ValueBytes, Value, time.asctime(time.gmtime(Value +
631148400))
except IndexError:
DataLine = DataLine + '?'
elif MessageFormat[1][ValueNum] == 'g':
try:
64
for offset in range(0,ValueBytesNum):
ValueBytes.append(ord(BinaryMessage[BytePointer +
offset]))
BytePointer = BytePointer + ValueBytesNum
Value = GLI4toDEC(ValueBytes)/100.0
DataLine = DataLine + str(Value)
#print ValueBytes, Value
except IndexError:
DataLine = DataLine + '?'
elif MessageFormat[1][ValueNum] == 'n':
try:
for offset in range(0,ValueBytesNum):
ValueBytes.append(ord(BinaryMessage[BytePointer +
offset]))
BytePointer = BytePointer + ValueBytesNum
Value = GLI4toDEC(ValueBytes)/100000.0
DataLine = DataLine + str(Value)
#print ValueBytes, Value
except IndexError:
DataLine = DataLine + '?'
elif MessageFormat[1][ValueNum] == 'e':
try:
for offset in range(0,ValueBytesNum):
ValueBytes.append(ord(BinaryMessage[BytePointer +
offset]))
BytePointer = BytePointer + ValueBytesNum
Value = GLI4toDEC(ValueBytes)/100000.0
DataLine = DataLine + str(Value)
#print ValueBytes, Value
except IndexError:
DataLine = DataLine + '?'
DataLine = DataLine + ','
DataLine = DataLine[:-1] # to remove the trailing comma character
IsDiagnostics = '!D' in DataLine[-5:-3] or MessageFormatNum % 5 ==
4#FIXME: the stats are wrong because we don't always go through here
IsObservations = '!M' in DataLine[-2:] or IsKnownBinaryFormat
IsSummer = ('!S' in DataLine and '!M' in DataLine[-2:]) or
MessageFormatNum % 5 in (0, 1)
IsWinter = ('!W' in DataLine and '!M' in DataLine[-2:]) or
MessageFormatNum % 5 in (2, 3)
IsWithInstant = '!I' in DataLine[-5:-3] or MessageFormatNum % 5 in (1, 3)
if not IsKnownBinaryFormat:
print '%s-%s' %(IMEI, MOMSN),
if IsDiagnostics: print '(ascii) generic diagnostic message',
elif IsObservations and IsSummer:print '(ascii) generic summer
observations message',
65
elif IsObservations and not IsSummer: print '(ascii) generic winter
observations message',
else: print 'unrecognized message format',
if IsWithInstant:
print '(+ instant.)'
else:
print ''
IsMalformed = IsTooLong or IsTooShort
if IsMalformed:
FoundMalformed += 1
print " WARNING - Message is malformed: any missing value will be
replaced by '?'"
DataLineHash = HashFunc(IMEI + MOMSN + DataLine).hexdigest()
if not DataLineHash in SeenMessageHashes:
if IsMalformed and FilterMalformed:
MalformedFilePath = BaseDir + '\\' + IMEI + '-F.txt'
while True:
try:
with open(MalformedFilePath, 'a') as OutFile:
OutFile.writelines(DataLine+'\n')
if not MalformedFilePath in ModifiedFiles:
ModifiedFiles.append(MalformedFilePath)
break
except IOError:
while True:
AbortOrRetry = raw_input('ERROR while opening %s: Abort or
Retry? [A/R]' %MalformedFilePath)
if AbortOrRetry.upper() in ('A', 'R'): break
if AbortOrRetry.upper() == 'A': break
elif IsDiagnostics:
DiagnosticFilePath = BaseDir + '\\' + IMEI + '-D.txt'
while True:
try:
with open(DiagnosticFilePath, 'a') as OutFile:
OutFile.writelines(DataLine+'\n')
if not DiagnosticFilePath in ModifiedFiles:
ModifiedFiles.append(DiagnosticFilePath)
break
except IOError:
while True:
AbortOrRetry = raw_input('ERROR while opening %s: Abort or
Retry? [A/R]' %DiagnosticFilePath)
if AbortOrRetry.upper() in ('A', 'R'): break
if AbortOrRetry.upper() == 'A': break
elif IsObservations:
ObservationFilePath = BaseDir + '\\' + IMEI + '.txt'
66
while True:
try:
with open(ObservationFilePath, 'a') as OutFile:
OutFile.writelines(DataLine+'\n')
if not ObservationFilePath in ModifiedFiles:
ModifiedFiles.append(ObservationFilePath)
break
except IOError:
while True:
AbortOrRetry = raw_input('ERROR while opening %s: Abort or
Retry? [A/R]' %ObservationFilePath)
if AbortOrRetry.upper() in ('A', 'R'): break
if AbortOrRetry.upper() == 'A': break
else: #if not diagnostics nor a properly terminated message or known
binary format, then it's garbage and gets dumped here
GarbageFilePath = BaseDir + '\\' + IMEI + '-X.txt'
while True:
try:
with open(GarbageFilePath, 'a') as OutFile:
OutFile.writelines(DataLine+'\n')
break
except IOError:
while True:
AbortOrRetry = raw_input('ERROR while opening %s: Abort or
Retry? [A/R]' %GarbageFilePath)
if AbortOrRetry.upper() in ('A', 'R'): break
if AbortOrRetry.upper() == 'A': break
#the -X.txt garbage files are not sorted since we don't know what is in
them
SeenMessageHashes.append(DataLineHash)
AppendedLines += 1
if IsSummer: AppendedSummer += 1
if IsWinter: AppendedWinter += 1
if IsWithInstant: AppendedWithInstant += 1
if IsDiagnostics: AppendedDiagnostics += 1
if IsMalformed: ApendedMalformed += 1
else:
if DataLineHash in SeenMessageHashesPreviousRuns:
SkippedAlreadyParsed += 1
print ' NOTE - Message has already been parsed: skipping'
else:#note this is not 100% accurate: on subsequent runs, repeated are just
detected as duplicated
SkippedDuplicated += 1
print ' NOTE - Message was sent more than once (an Iridium or NAL
bug): skipping'
#see emails in March 2008 with NAL engineers recognizing the issue
67
#DataLine = ''
Message = Messages.GetNext()# ref. http://mail.python.org/pipermail/pythonlist/2004-July/270944.html
try:
with open(BaseDir + '\\msgshash.dat', 'wb') as msgshash:
cPickle.dump(SeenMessageHashes, msgshash)
except IOError:
print "Warning - Couldn't save the hashes of the new messages"
except:
print 'ERROR: an unhandled exception occurred, terminating the program.'
raise
finally:
if 'LoggedIn' in locals():
try:
print '\nlogging off from the Exchange server...',
cdo.logoff
print 'ok\n'
except:
print '\nWARNING - Failed to log off from the Exchange server\n'
except pywintypes.com_error, errordetails:
print 'ERROR: COM API error %s (%s) - MAPI may not be available on this machine'
%(errordetails[0], errordetails[1])
sys.exit()
#MissingAttachments = 100 - ProcessedMessages / ProcessedAttachments * 100
if ProcessedMessages:
print 'messages processed:
%i' %ProcessedMessages, ' (from %s/%s)'
%(ProcessedInfostoreName, ProcessedFolderName)
print 'data attachments found: %i' %ProcessedAttachments
if SkippedAlreadyParsed:
print 'known messages skipped: %i (already parsed during previous program runs)'
%SkippedAlreadyParsed
if SkippedDuplicated:
print 'repeated messages skipped: %i (due to a bug on the Iridium or NAL side)'
%SkippedDuplicated
print 'new records appended:
%i' %AppendedLines
if AppendedSummer: print '
at summer rate: %i' %AppendedSummer
if AppendedWinter: print '
at winter rate: %i' %AppendedWinter
if AppendedWithInstant: print ' with instantaneous data: %i' %AppendedWithInstant
if AppendedDiagnostics: print '
diagnostic: %i' %AppendedDiagnostics
if ApendedMalformed:
print '\nWARNING: %i malformed messages parsed!' %ApendedMalformed,
if FilterMalformed:
print '(using setting: append to IMEI#-F.txt)'
else:
68
print '(using setting: append to IMEI#.txt)'
print """
Messages shorter than expected have missing values replaced with ?
* Any massage longer than expected is decoded up to the expected length
* All original files can be found in the subfolder of the relevant IMEI
* Set bool FilterMalformed to control where these data get appended"""
DoSort = ''
#print '\n'
while ModifiedFiles:#so that it only asks if any file has actually been modified
DoSort = raw_input('New lines were appended. Time-sort the %i relevant .txt files?
[Y/N]'%len(ModifiedFiles))
if DoSort.upper() in ('Y', 'N'): break
if DoSort.upper() == 'Y':#however the -X.txt garbage files are never sorted since we don't
know what is in them
for FileName in ModifiedFiles:
print '%s - reading' %FileName,
while True:
try:
with open(FileName, 'r') as InFile:
FileContent = InFile.readlines()
break
except IOError:
while True:
AbortOrRetry = raw_input('ERROR while opening %s: Abort or Retry?
[A/R]' %FileName)
if AbortOrRetry.upper() in ('A', 'R'): break
if AbortOrRetry.upper() == 'A': break
print 'ok, sorting' ,
try:
FileContent.sort()
except NameError:
continue
#os.rename(FileName, FileName + '.old')#TODO: for debug only
print 'ok, writing...' ,
while True:
try:
with open(FileName, 'w') as OutFile:
OutFile.writelines(FileContent)
break
except IOError:
while True:
AbortOrRetry = raw_input('ERROR while opening %s: Abort or Retry?
[A/R]' %FileName)
if AbortOrRetry.upper() in ('A', 'R'): break
if AbortOrRetry.upper() == 'A': break
print 'done!'
69