#!/bin/ksh
#
# $Id: prepare_dbnet_bufr_for_gts.ksh 727 2023-05-31 11:31:30Z frna $
#
# Create WMO-compatible file names for DBNet BUFR files, and add GTS headers if they are not already present.
#
# Usage: prepare_dbnet_bufr_for_gts infile
#
# Prerequisites:
# 1) bufr_filter (from ecCodes) must be accessible via $PATH
# 2) gtsheaders_bufr.pl (part of AAPP) accessible via AAPP environment or via $PATH
#
# The originating centre, sub-centre, satellite ID, instrument, start time and orbit are taken from the input BUFR file.
# The centre and sub-centre are convereted to station names via the DBNet_Coding-summary.xlsx (see references).
#
# The aim is to create file names like:
#   W_us-noaa-ssec,iasi,DBNet+metopb+may_C_KWBC_20180326003521_iasi_M01_20180326_0021_28632_bufr.bin
#   W_XX-EUMETSAT-kha,amsua,DBNet+metopb+kha_C_EUMS_20180326010926_amsua_20180326_0047_metopb_28632_kha_l1c_bufr.bin
#
# i.e. of the general form W_productidentifier_oflag_originator_yyyyMMddhhmmss[_freeformat].type[.compression]
#
# Note that there are some differences in the "freeformat" part of the file name between EARS files and those
# generated by other centers. This script maintains the status quo.
#
# References:
#  1)  WMO DBNet web page, with links to the "Guide to DBNet" and the "DBNet Coding Summary",
#      https://community.wmo.int/en/activity-areas/wmo-space-programme-wsp/dbnet
#  2)  WMO Manual on the Global Telecommunication System: Annex III to the WMO Technical Regulations,
#      https://library.wmo.int/index.php?lvl=notice_display&id=21811
#  3)  NWP SAF "Feeds of DBNet data from GTS",
#      https://nwp-saf.eumetsat.int/site/monitoring/dbnet/feeds-of-dbnet-data-from-gts/ 
#
# COPYRIGHT
#    This software was developed within the context of the EUMETSAT Satellite
#    Application Facility on Numerical Weather Prediction (NWP SAF), under the
#    Cooperation Agreement dated 7 December 2016, between EUMETSAT and the
#    Met Office, UK, by one or more partners within the NWP SAF. The partners
#    in the NWP SAF are the Met Office, ECMWF, DWD and MeteoFrance.
#
#    Copyright 2019, EUMETSAT, All Rights Reserved. 
#
# 03/06/2019 Nigel Atkinson
# 19/08/2020 Add Aqua/AIRS
# 19/04/2021 Add South African stations
# 24/11/2021 Add dha, dhk, lim
# 13/12/2021 Add lau processed by NIWA
# 19/04/2022 Add spv
# 25/04/2022 Area code S for cpt, for IASI, ATMS, CrIS
# 08/11/2022 Different CCCC code for each EARS station. Allow user to define CCCC as environment variable.
# 24/04/2023 Add satellites noaa21 and fy3e. Add stations hyd and cay.
# 31/05/2023 Change "timenow" so that it is UTC. Modify station code IMD->NCM.
#-------------------------------------------------------------------------------------------

bufr_filter -V >/dev/null 2>&1 || { echo 'Error: bufr_filter is not in $PATH'; exit 1; }

[ $# > 0 ] || { echo 'Usage: prepare_dbnet_bufr_for_gts infile'; exit 0; }

infile=$1

filterfile='prepare_dbnet_bufr_for_gts.filter'

if [ ! -f $filterfile ]; then
  echo 'set unpack=1;' >$filterfile
  echo 'print "[bufrHeaderCentre] [bufrHeaderSubCentre] [satelliteIdentifier] [#1#satelliteInstruments] [satelliteSensorIndicator] [typicalDate] [typicalTime] [orbitNumber]";' >>$filterfile
fi

#-------------------------------------------------
# Get the necessary information from the BUFR file
#-------------------------------------------------

set $(bufr_filter $filterfile $infile | head -1)

centre=$1
subcentre=$2
satid=$3
instr=$4
[ $instr = undef ] && instr=$5
startdate=$6
starttime=$7
orbit=$8

#----------------------------------------------------------------
# Convert numbers to names (instrument, satellite, station, etc.)
#----------------------------------------------------------------

case $instr in
    0) instrname=hirs;  instr_letter=H; level=l1c ;;   #BUFR code table 002048
    3) instrname=amsua; instr_letter=A; level=l1c ;;
   11) instrname=mhs;   instr_letter=M; level=l1c ;;
  221) instrname=iasi;  instr_letter=Q; level=l1c ;;   #Common Code Table C-8
  420) instrname=airs;  instr_letter=R; level=l1c ;;
  620) instrname=cris;  instr_letter=C; level=l1c ;;
  621) instrname=atms;  instr_letter=S; level=l1c ;;
  933) instrname=iras;  instr_letter=I; level=l1b ;;
  953) instrname=mwhs;  instr_letter=K; level=l1b ;;
  954) instrname=mwts;  instr_letter=T; level=l1b ;;
    *) echo "unknown instrument $instr"; exit 1 ;;
esac

case $satid in
  3)   satname1=metopb; satname2=M01 ;;
  4)   satname1=metopa; satname2=M02 ;;
  5)   satname1=metopc; satname2=M03 ;;
  206) satname1=noaa15; satname2=noaa15 ;;
  209) satname1=noaa18; satname2=noaa18 ;;
  223) satname1=noaa19; satname2=noaa19 ;;
  224) satname1=snpp;   satname2=snpp ;;
  225) satname1=noaa20; satname2=noaa20 ;;
  226) satname1=noaa21; satname2=noaa21 ;;
  522) satname1=fy3c;   satname2=fy3c ;;
  523) satname1=fy3d;   satname2=fy3d ;;
  524) satname1=fy3e;   satname2=fy3e ;;
  784) satname1=aqua;   satname2=aqua ;;
  *)   echo "unknown satellite $satid"; exit 1 ;;
esac

# Station codes

CCCC_save=${CCCC}    #allow user to set a specific CCCC code rather than the ones listed below

case ${centre}_${subcentre} in
  28_10  ) originator=in-NCM-del;      CCCC=DEMS; centre_letters=del ;;
  28_20  ) originator=in-NCM-guw;      CCCC=DEMS; centre_letters=guw ;;
  28_30  ) originator=in-NCM-che;      CCCC=DEMS; centre_letters=che ;;
  28_40  ) originator=in-NCM-hyd;      CCCC=DEMS; centre_letters=hyd ;;
  34_240 ) originator=jp-jma-msc;      CCCC=RJTD; centre_letters=kiy ;;
  34_207 ) originator=jp-jma-msc;      CCCC=RJTD; centre_letters=syo ;;
  39_225 ) originator=cn-cma-pek;      CCCC=BAWX; centre_letters=pek ;;
  40_245 ) originator=kr-kma-jin;      CCCC=RKSL; centre_letters=jin ;;
  110_229) originator=cn-hko-hkg;      CCCC=VHHH; centre_letters=hkg ;;
  2_201  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=csy ;;
  2_203  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=dvs ;;
  2_211  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=mel ;;
  2_214  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=dar ;;
  2_216  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=lea ;;
  2_217  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=pth ;;
  2_219  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=tvl ;;
  2_232  ) originator=au-BOM-mel;      CCCC=AMMC; centre_letters=fij ;;
  191_1  ) originator=fr-meteofrance-toulouse; CCCC=LFPW; centre_letters=pap ;;
  145_1  ) originator=fr-meteofrance-toulouse; CCCC=LFPW; centre_letters=cay ;;
  72_249 ) originator=sg-NEA-sgp;      CCCC=WSSS; centre_letters=sgp ;;
  204_101) originator=nz-NIWA-gpt;     CCCC=NZGP; centre_letters=mau ;;
  204_102) originator=nz-NIWA-gpt;     CCCC=NZGP; centre_letters=lau ;;
  254_20 ) originator=XX-EUMETSAT-mas; CCCC=EUMM; centre_letters=mas ;;
  254_30 ) originator=XX-EUMETSAT-kan; CCCC=EUMK; centre_letters=kan ;;
  254_40 ) originator=XX-EUMETSAT-edm; CCCC=EUME; centre_letters=edm ;;
  254_60 ) originator=XX-EUMETSAT-gan; CCCC=EUMG; centre_letters=gan ;;
  254_100) originator=XX-EUMETSAT-ath; CCCC=EUMB; centre_letters=ath ;;
  254_140) originator=XX-EUMETSAT-lan; CCCC=EUML; centre_letters=lan ;;
  254_150) originator=XX-EUMETSAT-sva; CCCC=EUMV; centre_letters=sva ;;
  254_170) originator=XX-EUMETSAT-std; CCCC=EUMD; centre_letters=std ;;
  254_180) originator=XX-EUMETSAT-mos; CCCC=EUMO; centre_letters=mos ;;
  254_190) originator=XX-EUMETSAT-mus; CCCC=EUMU; centre_letters=mus ;;
  254_200) originator=XX-EUMETSAT-kha; CCCC=EUMH; centre_letters=kha ;;
  254_210) originator=XX-EUMETSAT-nov; CCCC=EUMI; centre_letters=nov ;;
  254_220) originator=XX-EUMETSAT-sod; CCCC=EUMY; centre_letters=sod ;;
  254_70 ) originator=XX-EUMETSAT-mon; CCCC=EUMS; centre_letters=mon ;;
  254_80 ) originator=XX-EUMETSAT-wal; CCCC=EUMS; centre_letters=wal ;;
  254_90 ) originator=XX-EUMETSAT-gil; CCCC=EUMS; centre_letters=gil ;;
  254_120) originator=XX-EUMETSAT-ewa; CCCC=EUMS; centre_letters=ewa ;;
  254_130) originator=XX-EUMETSAT-mia; CCCC=EUMS; centre_letters=mia ;;
  254_211) originator=XX-EUMETSAT-res; CCCC=EUMS; centre_letters=res ;;
  46_10)   originator=br-inpe-cpt;     CCCC=SBBR; centre_letters=cpt ;;
  46_11)   originator=br-inpe-cba;     CCCC=SBBR; centre_letters=cba ;;
  46_12)   originator=br-inpe-inm;     CCCC=SBBR; centre_letters=inm ;;
  46_13)   originator=br-inpe-fcm;     CCCC=SBBR; centre_letters=fcm ;;
  46_15)   originator=br-inpe-svm;     CCCC=SBBR; centre_letters=svm ;;
  46_16)   originator=br-inpe-nat;     CCCC=SBBR; centre_letters=nat ;;
  46_18)   originator=br-inpe-spv;     CCCC=SBBR; centre_letters=spv ;;
  46_19)   originator=br-inpe-sbl;     CCCC=SBBR; centre_letters=sbl ;;
  147_10)  originator=ar-conae-etc;    CCCC=SABM; centre_letters=etc ;;
  147_20)  originator=ar-conae-ebm;    CCCC=SABM; centre_letters=ebm ;;
  147_30)  originator=ch-conae-ets;    CCCC=SABM; centre_letters=ets ;;
  176_20 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=hon ;;
  176_21 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=gil ;;
  176_22 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=mad ;;
  176_23 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=mia ;;
  176_24 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=may ;;
  176_25 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=mon ;;
  176_26 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=gua ;;
  176_27 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=cor ;;
  176_28 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=ham ;;
  176_29 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=new ;;
  176_30 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=kwa ;;
  176_31 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=edm ;;
  176_32 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=pre ;;
  176_33 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=eas ;;
  176_34 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=kiy ;;
  176_35 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=syo ;;
  176_36 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=asc ;;
  176_37 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=cho ;;
  176_38 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=lau ;;
  176_39 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=ets ;;
  176_40 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=dha ;;
  176_41 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=dhk ;;
  176_42 ) originator=us-noaa-ssec;    CCCC=KWBC; centre_letters=lim ;;
  24_10  ) originator=ZA-SANSA-hbk;    CCCC=FAPR; centre_letters=hbk ;;
  24_20  ) originator=NE-ACMAD-nim;    CCCC=FAPR; centre_letters=nim ;;
  24_30  ) originator=GA-AGEOS-lbv;    CCCC=FAPR; centre_letters=lbv ;;
  24_40  ) originator=KE-ICPAC-nbo;    CCCC=FAPR; centre_letters=nbo ;;
        *) echo "unknown centre_subcentre combination ${centre}_${subcentre}"; exit 1 ;;
esac

[ -z $CCCC_save ] || CCCC=$CCCC_save

# Area code is normally X unless otherwise specified in DBNet_Coding-summary.xlsx
# See Table C3 of the WMO manual on the GTS

case $centre_letters in
  kiy) A2=C ;;
  syo) A2=S ;;
  csy) A2=S ;;
  dvs) A2=S ;;
  pap) A2=J ;;
  etc) A2=I ;;
  ebm) A2=S ;;
  ets) A2=I ;;
  cay) A2=D ;;    #E would be more consistent with the location
    *) A2=X ;;
esac

[ $centre_letters = cpt ] && [[ $instrname =~ iasi|atms|cris ]] && A2=S

[ $centre = 204 ] && A2=S                 #Use S for products generated by NIWA
[ $centre = 176 ] && A2=T                 #Use T for products generated by SSEC

case ${centre}_${instr} in
  254_iasi ) extra=_ear_o_pcs ;;          #EUMETSAT IASI files have this extra field
         * ) extra= ;;
esac

if [ $instrname != iasi ] || [ ${centre} == 254 ]; then    #EUMETSAT always use names like metopa/b/c; other centres use M02/1/3 for IASI only
  satname2=$satname1
fi

if [ $instrname != iasi ] || [ ${centre} != 254 ]; then    #EUMETSAT give IASI times to 1 second precision, otherwise to 1 minute
  starttime=${starttime:0:4}
fi

# --------------------------
# Assemble the new file name
# --------------------------

timenow=$(date -u +%Y%m%d%H%M%S)

part1=W_${originator},${instrname},DBNet+${satname1}+${centre_letters}_C_${CCCC}_${timenow}

if [ ${centre} = 254 ]; then        #EUMETSAT convention
  newname=${part1}_${instrname}_${startdate}_${starttime}_${satname2}_${orbit}${extra}_${centre_letters}_${level}_bufr.bin
else
  newname=${part1}_${instrname}_${satname2}_${startdate}_${starttime}_${orbit}_bufr.bin
fi

# ----------------------------------------------------------------------------------------
# Add GTS headers if they are not already present, otherwise create a link to the new name
# ----------------------------------------------------------------------------------------

if [ $infile != $newname ]; then
  header=$(head -3 $infile)
  if [[ "$header" != *${CCCC}* ]]; then
    gtsheaders_bufr.pl $infile $newname IN${instr_letter}${A2} ${CCCC} && \
        echo "Created $newname" || { echo "Error in gtsheaders_bufr.pl"; exit 1; }
  else
    ln -sf $infile $newname && echo "Created link to $newname"
  fi
else
  echo "No change to file name"
fi
