You've already forked QWeatherReporter
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a766efa8a | ||
|
|
71eb2472ce | ||
|
|
1b3d1e2875 | ||
|
|
025e0d8664 | ||
|
|
44f694f82e | ||
|
|
b41be502f2 | ||
|
|
cc8bed1890 | ||
|
|
9174e11ecd | ||
|
|
31ea638770 | ||
|
|
11244734fd | ||
|
|
9cbd3b5063 | ||
|
|
3622b094fd | ||
|
|
4c73240fe9 | ||
|
|
451aed59d0 | ||
|
|
0b41c9c1f5 | ||
|
|
b205533ae7 | ||
|
|
b493c06387 | ||
|
|
936dd14a87 | ||
|
|
21a7f9140d | ||
|
|
23f44c3f78 | ||
|
|
9477c33952 | ||
|
|
7fdd0d56a1 | ||
|
|
2117771518 | ||
|
|
ea4d04a71c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
test.py
|
||||||
*.yml
|
*.yml
|
||||||
!config.yml
|
!config.yml
|
||||||
*.log
|
*.log
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -1,7 +1,7 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/MarkusJoe/QWeather">
|
<a href="https://github.com/MarkusJoe/QWeather">
|
||||||
<img src="https://img.shields.io/badge/Python-3.10.x-blue.svg" alt="PythonVersion">
|
<img src="https://img.shields.io/badge/Python-3.10.x-blue.svg" alt="PythonVersion">
|
||||||
<img src="https://img.shields.io/badge/release-3.1.4b-green.svg" alt="QWeatherVersion">
|
<img src="https://img.shields.io/badge/release-3.2.3-green.svg" alt="QWeatherVersion">
|
||||||
<img src="https://img.shields.io/badge/LINCESE-Apache2.0-orange.svg" alt="LICENSE">
|
<img src="https://img.shields.io/badge/LINCESE-Apache2.0-orange.svg" alt="LICENSE">
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@@ -15,10 +15,6 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div align="center">
|
|
||||||
<b><i>当前分支版本为重构后的版本重构前版本请在before分支中查看<br>(重构前版本不再更新,最新版本为v2.9.0)</i></b><br>
|
|
||||||
<b><i><a href="https://markusjoe.github.io/" target="_blank">点击跳转到帮助文档</a></i></b>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## 声明
|
## 声明
|
||||||
- > 程序作者: **RTAkland (markushammered@gmail.com)**
|
- > 程序作者: **RTAkland (markushammered@gmail.com)**
|
||||||
@@ -32,15 +28,16 @@
|
|||||||
- 你可以在**注明来源版权信息**的情况下对源代码进行任意分发和修改以及衍生
|
- 你可以在**注明来源版权信息**的情况下对源代码进行任意分发和修改以及衍生
|
||||||
|
|
||||||
### 已实现功能
|
### 已实现功能
|
||||||
- [x] 发送免费版&开发板右键
|
- [x] 发送免费版&开发版天气预报功能
|
||||||
- [x] 间隔10分钟请求一次自然灾害预警信息
|
- [x] 间隔10分钟请求一次自然灾害预警信息
|
||||||
- [x] 在网页上快速查看天气
|
- [x] 在网页上快速查看天气
|
||||||
|
- [x] 在邮件html内附带一句一言
|
||||||
- [ ] ~~推送到QQ(咕咕咕)~~
|
- [ ] ~~推送到QQ(咕咕咕)~~
|
||||||
|
|
||||||
### 问题汇总
|
### 问题汇总
|
||||||
#### Python 版本:
|
#### Python 版本:
|
||||||
> 程序使用了Python3.10中的match-case语句
|
> 程序使用了*Python3.10.x*中的match-case语句
|
||||||
> 请使用Python3.10版本运行
|
> 请使用*Python3.10.x*版本运行
|
||||||
#### 主题选择:
|
#### 主题选择:
|
||||||
> 在2.9.0之后的版本不支持自定义天气图标 只能使用最新的图标
|
> 在2.9.0之后的版本不支持自定义天气图标 只能使用最新的图标
|
||||||
#### 配置填写问题:
|
#### 配置填写问题:
|
||||||
@@ -54,7 +51,7 @@
|
|||||||
|
|
||||||
### 网页上查看天气
|
### 网页上查看天气
|
||||||
- 将所有准备工作完成(能正常运行QWeather.py)
|
- 将所有准备工作完成(能正常运行QWeather.py)
|
||||||
- 运行QWeather.py
|
- 运行`QWeather.py`
|
||||||
- 打开浏览器输入**127.0.0.1:7898**
|
- 打开浏览器输入**127.0.0.1:7898**
|
||||||
>127.0.0.1可以更改为部署本项目的服务器ip, 7898端口不能被其他程序占用或不开放此端口
|
>127.0.0.1可以更改为部署本项目的服务器ip, 7898端口不能被其他程序占用或不开放此端口
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,11 @@ from core.language import Language
|
|||||||
from core.settings import change_settings
|
from core.settings import change_settings
|
||||||
from core.read_config import read_config
|
from core.read_config import read_config
|
||||||
from core.sendmail import Mail
|
from core.sendmail import Mail
|
||||||
from lib.get_host_ip import get_host_ip
|
from lib.webservice import accept_requests
|
||||||
from lib import webservice
|
|
||||||
|
language = Language()
|
||||||
|
settings = read_config()
|
||||||
|
processes = ProcessPoolExecutor(max_workers=3)
|
||||||
|
|
||||||
|
|
||||||
def check_time():
|
def check_time():
|
||||||
@@ -84,6 +87,12 @@ def main():
|
|||||||
主程序
|
主程序
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Logger.info(f'{language["statement_1"]}')
|
||||||
|
Logger.info(f'{language["statement_2"]}')
|
||||||
|
Logger.info(f'{language["statement_3"]}')
|
||||||
|
Logger.info(f'{language["statement_4"]}')
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
arg_keywords = ['free', 'dev', 'warning', 'setting']
|
arg_keywords = ['free', 'dev', 'warning', 'setting']
|
||||||
parser.add_argument('-t',
|
parser.add_argument('-t',
|
||||||
@@ -116,8 +125,8 @@ def main():
|
|||||||
|
|
||||||
processes.submit(check_time)
|
processes.submit(check_time)
|
||||||
if settings[2]['webservice']:
|
if settings[2]['webservice']:
|
||||||
Logger.info(f'{language["webservice_ip"]}:{get_host_ip()}:7898')
|
Logger.info(f'{language["webservice_ip"]}:127.0.0.1:7898')
|
||||||
processes.submit(webservice.process_request())
|
processes.submit(accept_requests())
|
||||||
|
|
||||||
time_count = 0
|
time_count = 0
|
||||||
while True:
|
while True:
|
||||||
@@ -126,14 +135,3 @@ def main():
|
|||||||
if time_count == 600:
|
if time_count == 600:
|
||||||
Mail().warning_()
|
Mail().warning_()
|
||||||
time_count = 0
|
time_count = 0
|
||||||
|
|
||||||
|
|
||||||
if __name__ != '__main__':
|
|
||||||
language = Language()
|
|
||||||
settings = read_config()
|
|
||||||
processes = ProcessPoolExecutor(max_workers=3)
|
|
||||||
|
|
||||||
Logger.info(f'{language["statement_1"]}')
|
|
||||||
Logger.info(f'{language["statement_2"]}')
|
|
||||||
Logger.info(f'{language["statement_3"]}')
|
|
||||||
Logger.info(f'{language["statement_4"]}')
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ def read_config():
|
|||||||
:return: mail-settings, request-settings, client-settings, only-view-settings --> 0, 1, 2, 3
|
:return: mail-settings, request-settings, client-settings, only-view-settings --> 0, 1, 2, 3
|
||||||
"""
|
"""
|
||||||
config_file = 'config.yml'
|
config_file = 'config.yml'
|
||||||
with open(f'./{config_file}', 'r') as conf:
|
with open(f'./{config_file}', 'r', encoding='utf-8') as conf:
|
||||||
config = YAML().load(conf.read())
|
config = YAML().load(conf.read())
|
||||||
mail_settings = config['mail-settings']
|
mail_settings = config['mail-settings']
|
||||||
request_settings = config['request-settings']
|
request_settings = config['request-settings']
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
# -- coding:utf-8 --
|
|
||||||
# @Author: markushammered@gmail.com
|
|
||||||
# @Development Tool: PyCharm
|
|
||||||
# @Create Time: 2021/12/21
|
|
||||||
# @File Name: get_host_ip.py
|
|
||||||
|
|
||||||
import socket
|
|
||||||
|
|
||||||
|
|
||||||
def get_host_ip():
|
|
||||||
"""
|
|
||||||
查询本机ip地址
|
|
||||||
:return: ip
|
|
||||||
"""
|
|
||||||
ip_s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
ip_s.connect(('8.8.8.8', 80))
|
|
||||||
ip = ip_s.getsockname()[0]
|
|
||||||
ip_s.close()
|
|
||||||
|
|
||||||
return ip
|
|
||||||
@@ -3,3 +3,21 @@
|
|||||||
# @Development Tool: PyCharm
|
# @Development Tool: PyCharm
|
||||||
# @Create Time: 2021/12/24
|
# @Create Time: 2021/12/24
|
||||||
# @File Name: hitokoto.py
|
# @File Name: hitokoto.py
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from core.language import Language
|
||||||
|
from core.logger import Logger
|
||||||
|
|
||||||
|
|
||||||
|
def hitokoto():
|
||||||
|
language = Language()
|
||||||
|
url = 'https://v1.hitokoto.cn/'
|
||||||
|
Logger.info(f'{language["hitokoto"]}')
|
||||||
|
res = requests.get(url).json()
|
||||||
|
speaker = res['from_who']
|
||||||
|
text = res['hitokoto']
|
||||||
|
if not speaker:
|
||||||
|
speaker = language['noname']
|
||||||
|
full_text = f'{text} --{speaker}'
|
||||||
|
|
||||||
|
return full_text
|
||||||
|
|||||||
@@ -7,16 +7,19 @@
|
|||||||
|
|
||||||
|
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import threading
|
||||||
from core.logger import Logger
|
from core.logger import Logger
|
||||||
from core.read_config import read_config
|
from core.read_config import read_config
|
||||||
from core.information import WeatherInfo
|
from core.information import WeatherInfo
|
||||||
from core.language import Language
|
from core.language import Language
|
||||||
|
|
||||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
try:
|
||||||
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
server.bind(('localhost', 7898))
|
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
server.listen(5)
|
server.bind(('0.0.0.0', 7898))
|
||||||
|
server.listen(5)
|
||||||
|
except OSError as e:
|
||||||
|
Logger.critical(e)
|
||||||
|
|
||||||
language = Language()
|
language = Language()
|
||||||
|
|
||||||
@@ -295,32 +298,40 @@ def build_html():
|
|||||||
return "You hadn't selected a mode"
|
return "You hadn't selected a mode"
|
||||||
|
|
||||||
|
|
||||||
def process_request():
|
def process_requests(c, a):
|
||||||
"""
|
"""
|
||||||
处理请求
|
处理请求
|
||||||
|
:param c: connection
|
||||||
|
:param a: address
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
while True:
|
data = str(c.recv(1024)).split(':')[0][6:][:-17]
|
||||||
c, a = server.accept()
|
html = build_html()
|
||||||
data = str(c.recv(1024)).split(':')[0][6:][:-17]
|
if data == '/': # 判断用户请求的目标是否为根目录, 如果是则返回html; 如果不是则继续判断
|
||||||
html = build_html()
|
c.send('HTTP/1.1 200 OK\r\n\r\n'.encode('utf-8'))
|
||||||
if data == '/': # 判断用户请求的目标是否为根目录, 如果是则返回html; 如果不是则继续判断
|
c.send(html.encode('utf-8'))
|
||||||
c.send('HTTP1.1/ 200 OK\r\n\r\n'.encode('utf-8'))
|
Logger.info(f'{language["get_resource"]} {data} {language["get_resource_from"]} {a[0]}:{a[1]}')
|
||||||
c.send(html.encode('utf-8'))
|
try:
|
||||||
|
with open(f'./{data}', 'rb') as f:
|
||||||
|
c.send('HTTP/1.1 200 OK\r\n\r\n'.encode('utf-8'))
|
||||||
|
c.send(f.read())
|
||||||
Logger.info(f'{language["get_resource"]} {data} {language["get_resource_from"]} {a[0]}:{a[1]}')
|
Logger.info(f'{language["get_resource"]} {data} {language["get_resource_from"]} {a[0]}:{a[1]}')
|
||||||
else: # 继续判断用户请求的文件是否存在
|
except FileNotFoundError:
|
||||||
try:
|
with open('./res/basic-resources/404.html', 'r') as not_found:
|
||||||
with open(f'.{data}', 'rb') as f:
|
c.send(f'HTTP/1.1 404 Not Found\r\n\r\n{not_found.read()}'.encode('utf-8'))
|
||||||
c.send('HTTP1.1/ 200 OK\r\n\r\n'.encode('utf-8'))
|
|
||||||
c.send(f.read())
|
|
||||||
Logger.info(f'{language["get_resource"]} {data} {language["get_resource_from"]} {a[0]}:{a[1]}')
|
|
||||||
except FileNotFoundError:
|
|
||||||
c.send(f'HTTP1.1/ 404 Not Found\r\n\r\n{html}'.encode('utf-8'))
|
|
||||||
c.close()
|
|
||||||
except BrokenPipeError:
|
except BrokenPipeError:
|
||||||
Logger.critical(f'{language["connection_speed_too_fast"]}')
|
Logger.error(f'{language["connection_speed_too_fast"]}')
|
||||||
sys.exit(1)
|
finally:
|
||||||
except IOError:
|
c.close()
|
||||||
Logger.critical(f'{language["an_io_error"]}')
|
return
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
def accept_requests():
|
||||||
|
"""
|
||||||
|
接受请求
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
while True:
|
||||||
|
c, a = server.accept()
|
||||||
|
threading.Thread(target=process_requests, args=(c, a,)).start()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
requests>=2.26.0
|
requests>=2.26.0
|
||||||
ruamel.yaml>=0.17.17
|
ruamel.yaml>=0.17.17
|
||||||
pandas>=1.3.4
|
pandas==1.3.4
|
||||||
colorlog>=6.5.0
|
colorlog>=6.5.0
|
||||||
openpyxl>=3.0.9
|
openpyxl>=3.0.9
|
||||||
|
|||||||
10
res/basic-resources/404.html
Normal file
10
res/basic-resources/404.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>QWeather|网页查看天气服务</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<i><b><p style="text-align: center; color: red">404 File Not Found</p></b></i>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -33,8 +33,7 @@
|
|||||||
"change_setting": "You are changing setting.",
|
"change_setting": "You are changing setting.",
|
||||||
"exit": "Exited.",
|
"exit": "Exited.",
|
||||||
"webservice_ip": "Local webservice ip",
|
"webservice_ip": "Local webservice ip",
|
||||||
"connection_speed_too_fast": "Connection speed is too fast, subprocess: webservice has exited.",
|
"connection_speed_too_fast": "Connection speed is too fast",
|
||||||
"an_io_error": "An IO error.",
|
|
||||||
"noname": "No name.",
|
"noname": "No name.",
|
||||||
"hitokoto": "Get hitokoto successfully.",
|
"hitokoto": "Get hitokoto successfully.",
|
||||||
"get_resource": "Get resource",
|
"get_resource": "Get resource",
|
||||||
|
|||||||
@@ -32,8 +32,7 @@
|
|||||||
"change_setting": "更改设置",
|
"change_setting": "更改设置",
|
||||||
"exit": "已退出",
|
"exit": "已退出",
|
||||||
"webservice_ip": "webservice地址",
|
"webservice_ip": "webservice地址",
|
||||||
"connection_speed_too_fast": "连接速度过快, 子进程:webservice.py 已退出",
|
"connection_speed_too_fast": "连接速度过快",
|
||||||
"an_io_error": "一个IO错误",
|
|
||||||
"noname": "佚名",
|
"noname": "佚名",
|
||||||
"hitokoto": "一言获取成功",
|
"hitokoto": "一言获取成功",
|
||||||
"get_resource": "获取资源",
|
"get_resource": "获取资源",
|
||||||
|
|||||||
Reference in New Issue
Block a user