自动上传APRS天气信息的python脚本

自动上传APRS天气信息的python脚本

自动上传APRS天气信息的python脚本

一、python脚本说明

1.python代码由ba7ib编写,转载请注明。

2.脚本可以在OpenWrt设备上运行,目前使用华为HG225D路由器运行正常。

3.脚本中拉取的温湿度、气压、风、雨、PM2.5、甲醛、空气质量、日出日落等天气数据来自和风天气。

4.运行脚本只需修改代码中的Callsign,Passcode,Key,City几个参数即可。

Key到http://www.heweather.com/注册申请,选择免费套餐。

自动上传APRS天气信息的python脚本

City代码:https://where.heweather.com/index.html

自动上传APRS天气信息的python脚本

二、上传python脚本

1.保存以下脚本为weather.py

2.WinSCP上传至路由器root目录

三、路由器配置

1.安装依赖环境(视不同路由器按需安装)

自动上传APRS天气信息的python脚本

2.设置启动项

 

			
  1. python2 /etc/config/weather.py &

自动上传APRS天气信息的python脚本

3.设置运行时间

①putty运行:

 

			
  1. crontab -e

②进入编辑状态,最后一行添加:

 

			
  1. */15 * * * * python2 -u weather.py (##15分钟运行一次)

或是在路由器计划任务手动添加: 自动上传APRS天气信息的python脚本

四、Putty启动脚本

 

			
  1. python2 weather.py &

自动上传APRS天气信息的python脚本

五、附:Python 脚本

 

			
  1. #!/usr/bin/python
  2.  
  3. import os
  4. import json, urllib2, string
  5. from datetime import datetime
  6. import socket
  7. import sys
  8. from time import sleep
  9. import re, ssl
  10.  
  11. ssl._create_default_https_context = ssl._create_unverified_context
  12.  
  13. Callsign = '呼号+SSID'
  14. Passcode = '验证码'
  15. Server = 's.aprs.cn:14580'
  16. Protocal = 'any'
  17. City = '填写你所在的城市CID'
  18. Key = '填写你注册申请得到的key'
  19.  
  20. def send_aprsframe(aprs_frame):
  21. sended = False
  22. Aprs_Sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  23. while not sended:
  24. Aprs_Sock.connect((Server.split(':')[0], int(Server.split(':')[1])))
  25. Aprs_Sock.send('user %s pass %s vers BA7IB Scripts (Python) ' % (Callsign, Passcode) )
  26. sReturn = Aprs_Sock.recv(4096)
  27. if sReturn.startswith("#"):
  28. print "Succesfully logged to APRS-IS! %s" % sReturn
  29. Aprs_Sock.send('%s ' % aprs_frame)
  30. sended = True
  31. sleep(1)
  32. Aprs_Sock.shutdown(0)
  33. Aprs_Sock.close()
  34.  
  35. class APRSFrame:
  36. def __init__(self):
  37. self.source = None
  38. self.dest = None
  39. self.path = []
  40. self.payload = unicode()
  41.  
  42. def export(self, encode=True):
  43. tnc2 = "%s>%s,%s:%s" % (self.source, self.dest, ','.join(self.path), self.payload)
  44. if len(tnc2) > 510:
  45. tnc2 = tnc2[:510]
  46. if encode:
  47. tnc2 = tnc2.encode('ISO-8859-1')
  48. return tnc2
  49.  
  50. def bc():
  51. bcargs_weather = {
  52. 'callsign': Callsign,
  53. 'weather': 'https://free-api.heweather.com/v5/weather?lang=en&city=%s&key=%s' % (City, Key),
  54. }
  55. while True:
  56. frame = get_weather_frame(**bcargs_weather)
  57. if frame:
  58. send_aprsframe(frame)
  59. sleep(300)
  60.  
  61. def process_ambiguity(pos, ambiguity):
  62. num = bytearray(pos)
  63. for i in range(0, ambiguity):
  64. if i > 1:
  65. i += 1
  66. i += 2
  67. num[-i] = " "
  68. return str(num)
  69.  
  70. def encode_lat(lat):
  71. lat_dir = 'N' if lat > 0 else 'S'
  72. lat_abs = abs(lat)
  73. lat_deg = int(lat_abs)
  74. lat_min = (lat_abs % 1) * 60
  75. return "%02i%05.2f%c" % (lat_deg, lat_min, lat_dir)
  76.  
  77. def encode_lng(lng):
  78. lng_dir = 'E' if lng > 0 else 'W'
  79. lng_abs = abs(lng)
  80. lng_deg = int(lng_abs)
  81. lng_min = (lng_abs % 1) * 60
  82. return "%03i%05.2f%c" % (lng_deg, lng_min, lng_dir)
  83.  
  84. def mkframe(callsign, payload):
  85. frame = APRSFrame()
  86. frame.source = callsign
  87. frame.dest = u'APRS'
  88. frame.path = [u'TCPIP*']
  89. frame.payload = payload
  90. return frame.export()
  91.  
  92. def get_weather_frame(callsign, weather):
  93. try:
  94. req = urllib2.Request(weather)
  95. wea_str = urllib2.urlopen(req).read()
  96. if wea_str == -1:
  97. print "Sorry that I can't find the weather info of this city now, please check or retry. weather string = %s " % wea_str
  98. sys.exit(-1)
  99. else:
  100. w = json.loads(wea_str, encoding='utf-8')["HeWeather5"][0]
  101. timestamp = w['basic']['update']['utc']
  102. enc_lat = process_ambiguity(encode_lat(string.atof(w['basic']['lat'])), 0)
  103. enc_lng = process_ambiguity(encode_lng(string.atof(w['basic']['lon'])), 0)
  104. wenc = "%s%s%s" % (enc_lat, '/', enc_lng)
  105. wind = w['now'].get('wind', {})
  106. wenc += "_%03d" % string.atoi(wind['deg'])
  107. wenc += "/%03d" % string.atoi(wind['spd'])
  108. wenc += "g%03d" % 0
  109. cond = w['now']
  110. wenc += "t%03d" % round(string.atof(cond['tmp']) / (float(5)/9) + 32)
  111. wenc += "r%03d" % 0
  112. wenc += "p%03d" % round(string.atof(cond['pcpn']) / 25.4)
  113. if 'hum' in cond:
  114. wenc += "h%02d" % string.atoi(cond['hum'])
  115. else:
  116. wenc += "h..."
  117. if 'pres' in cond:
  118. wenc += "b%04d" % round(string.atof(cond['pres']) * 10)
  119. else:
  120. wenc += "b..."
  121. if 'aqi' in w:
  122. aqi = w['aqi']['city']
  123. wenc += ",...,...,...,000,%03d,%03d" % (string.atoi(aqi['pm10']), string.atoi(aqi['pm25']))
  124. wenc += ",."
  125. if 'daily_forecast' in w:
  126. df = w['daily_forecast'][0]['astro']
  127. ext_info = " Air:%s SunR/S:%s/%s MoonR/S:%s/%s" % (aqi['qlty'], df['sr'], df['ss'], df['mr'], df['ms'])
  128. else:
  129. ext_info = ""
  130. payload = "=%s%s Info@UTC%s" % ( wenc, ext_info, timestamp)
  131. return mkframe(callsign, payload)
  132. except:
  133. print "Weather decode error"
  134. return None
  135. bc()

内容版权声明:本站内容由网络转载收集,如有侵权请联系微信BG2UKP进行删除。

转载注明出处:http://www.chinaham.cn/APRS/18.html