adi.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. if __name__ == "__main__":
  2. print("This is a library not an executable.")
  3. exit(1)
  4. def cleanupXmlName(name):
  5. nameOut = ""
  6. for c in name:
  7. if c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-_.:;/()[]":
  8. nameOut += c
  9. else:
  10. nameOut += f"&#{ord(c)};"
  11. return nameOut
  12. def cleanupPathName(name):
  13. nameOut = ""
  14. for c in name:
  15. if c in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-_.":
  16. nameOut += c
  17. else:
  18. nameOut += "_"
  19. return nameOut
  20. def formatTime(text):
  21. if ":" in text:
  22. return text
  23. t = ""
  24. if len(text) >= 2:
  25. t += text[0:2]
  26. if len(text) >= 4:
  27. t += ":" + text[2:4]
  28. if len(text) >= 6:
  29. t += ":" + text[4:6]
  30. else:
  31. t += ":00"
  32. else:
  33. t = "__:__"
  34. return t
  35. def formatDate(text):
  36. if "." in text:
  37. return text
  38. y = text[0:4]
  39. m = int(text[4:6])
  40. d = text[6:8]
  41. month = ["___", "Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
  42. if m < 1 or m > 12:
  43. m = 0
  44. return f"{d}.{month[m]}.{y}"
  45. class AdiRow:
  46. def __init__(self):
  47. self.CALL = ""
  48. self.Date = ""
  49. self.Time = ""
  50. self.Band = ""
  51. self.MHz = ""
  52. self.Mode = ""
  53. self.RST = ""
  54. def fileName(self, card_name="{_CALL_}_{_Date_}_{_Time_}"):
  55. return cleanupPathName(self.fillTemplate(card_name))
  56. def subPath(self):
  57. name = cleanupPathName(f"{self.CALL}")
  58. if len(name) >= 2:
  59. return f"{name[0]}/{name[0:2]}/{name}"
  60. if len(name) == 1:
  61. return f"{name}/_/{name}"
  62. return "_/_/_"
  63. def fillTemplate(self, template):
  64. template = template.replace("{_CALL_}", cleanupXmlName(self.CALL))
  65. template = template.replace("{_Date_}", cleanupXmlName(self.Date))
  66. template = template.replace("{_Time_}", cleanupXmlName(self.Time))
  67. template = template.replace("{_Band_}", cleanupXmlName(self.Band))
  68. template = template.replace("{_MHz_}", cleanupXmlName(self.MHz))
  69. template = template.replace("{_Mode_}", cleanupXmlName(self.Mode))
  70. template = template.replace("{_RST_}", cleanupXmlName(self.RST))
  71. return template
  72. def isValid(self):
  73. return self.CALL != "" and self.Date != "" and self.Time != ""
  74. def setValue(self, k, v):
  75. k = k.upper()
  76. if k == "CALL":
  77. self.CALL = v
  78. elif k == "QSO_DATE":
  79. self.Date = formatDate(v)
  80. elif k == "TIME_ON":
  81. self.Time = formatTime(v)
  82. elif k == "BAND":
  83. self.Band = v
  84. elif k == "FREQ":
  85. self.MHz = v
  86. elif k == "MODE":
  87. self.Mode = v
  88. elif k == "RST_SENT":
  89. self.RST = v
  90. def guessBand(self, freq=None):
  91. bands = [ ("160m", 1.8, 2.0)
  92. , ( "80m", 3.5, 3.8)
  93. , ( "60m", 5.3, 5.4)
  94. , ( "40m", 7.0, 7.2)
  95. , ( "30m", 10.1, 10.2)
  96. , ( "20m", 14.0, 14.5)
  97. , ( "17m", 18.0, 18.2)
  98. , ( "15m", 21.0, 21.5)
  99. , ( "12m", 24.0, 25.0)
  100. , ( "10m", 28.0, 29.7)
  101. , ( "6m", 50.0, 52.0)
  102. , ( "4m", 70.0, 70.3)
  103. , ( "2m", 144.0, 146.0)
  104. , ("70cm", 430.0, 440.0)
  105. ]
  106. if self.Band != "":
  107. return
  108. if freq is None:
  109. freq = self.MHz
  110. try:
  111. freq = float(freq.replace(",","."))
  112. except:
  113. return
  114. for (name, lower, upper) in bands:
  115. if freq >= lower and freq <= upper:
  116. self.Band = name
  117. return
  118. def parseRow(row):
  119. state = 0
  120. key = ""
  121. value = ""
  122. adiRow = AdiRow()
  123. while row != "":
  124. c = row[0]
  125. row = row[1:]
  126. if state == 0:
  127. if c == '<':
  128. state = 1
  129. key = ""
  130. else:
  131. if c != ">":
  132. key += c
  133. else:
  134. state = 0
  135. pair = key.split(":")
  136. if len(pair) != 2:
  137. continue
  138. key = pair[0]
  139. try:
  140. size = int(pair[1])
  141. if size < 1 or size > 100:
  142. continue
  143. value = row[0:size]
  144. row = row[(size+1):]
  145. adiRow.setValue(key, value)
  146. finally:
  147. pass
  148. if adiRow.isValid():
  149. adiRow.guessBand()
  150. return adiRow
  151. return None
  152. def loadAdi(fileName):
  153. adiText = ""
  154. with open(fileName) as f:
  155. adiText = f.read()
  156. adi = adiText.split("<EOH>")
  157. if len(adi) < 2:
  158. return None
  159. adi = "<EOH>".join(adi[1:])
  160. data = []
  161. for row in adi.split("<EOR>"):
  162. row = parseRow(row)
  163. if row is not None:
  164. data.append(row)
  165. return data