diff --git a/export/export.sh b/export/export.sh new file mode 100644 index 0000000..908e9b6 --- /dev/null +++ b/export/export.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +# 设置环境变量 +export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +export LANG=en_US.UTF-8 +export LC_ALL=en_US.UTF-8 + +# 设置PostgreSQL环境变量 +export PGPASSWORD="你的密码" # 替换为实际的密码 + +# 设置数据库连接参数 +DB_HOST="localhost" +DB_PORT="5432" +DB_NAME="weatherdb" +DB_USER="yarnom" +EXPORT_DIR="/home/yarnom/Archive/code/WeatherStation/exportData" + +# 添加日志功能 +LOG_FILE="$EXPORT_DIR/export.log" + +# 记录开始时间 +echo "=== 开始导出: $(date) ===" >> "$LOG_FILE" + +# 确保导出目录存在 +mkdir -p "$EXPORT_DIR/data" + +# 获取当前时间和10分钟前的时间 +CURRENT_DATE=$(date +"%Y-%m-%d") +END_TIME=$(date +"%Y-%m-%d %H:%M:00") +START_TIME=$(date -d "10 minutes ago" +"%Y-%m-%d %H:%M:00") + +# 记录时间范围 +echo "导出时间范围: $START_TIME 到 $END_TIME" >> "$LOG_FILE" + +# 设置当天的数据文件 +CURRENT_FILE="$EXPORT_DIR/data/weather_data_${CURRENT_DATE}.csv" +LAST_EXPORT_TIME_FILE="$EXPORT_DIR/last_export_time" + +# 检查是否需要创建新文件(新的一天) +if [ -f "$LAST_EXPORT_TIME_FILE" ]; then + LAST_DATE=$(head -n 1 "$LAST_EXPORT_TIME_FILE" | cut -d' ' -f1) + if [ "$LAST_DATE" != "$CURRENT_DATE" ]; then + # 新的一天,将昨天的文件压缩存档 + YESTERDAY=$(date -d "yesterday" +"%Y-%m-%d") + if [ -f "$EXPORT_DIR/data/weather_data_${YESTERDAY}.csv" ]; then + gzip "$EXPORT_DIR/data/weather_data_${YESTERDAY}.csv" + fi + fi +fi + +# 如果是新文件,创建表头 +if [ ! -f "$CURRENT_FILE" ]; then + echo "创建新文件: $CURRENT_FILE" >> "$LOG_FILE" + echo "latitude,longitude,station_id,station_name,date_time,elevation,pressure,temperature,dewpoint,wind_speed,wind_direction,relative_humidity,ztd,pwv" > "$CURRENT_FILE" +fi + +# 导出新数据并追加到当天的文件 +psql -h "$DB_HOST" -p "$DB_PORT" -d "$DB_NAME" -U "$DB_USER" -A -F "," -t -c " + WITH avg_data AS ( + SELECT + s.station_id, + COALESCE(s.password, s.station_id) as output_station_id, -- 如果password为空则使用station_id + '$END_TIME'::timestamp as date_time, + -- 气压、温度取平均 + ROUND(AVG(r.pressure)::numeric, 2) as pressure, + ROUND(AVG(r.temperature)::numeric, 2) as temperature, + -- 风速取平均 + ROUND(AVG(r.wind_speed)::numeric, 2) as wind_speed, + -- 风向使用矢量平均 + ROUND(DEGREES(ATAN2( + AVG(SIN(RADIANS(r.wind_direction))), + AVG(COS(RADIANS(r.wind_direction))) + ))::numeric + CASE + WHEN DEGREES(ATAN2( + AVG(SIN(RADIANS(r.wind_direction))), + AVG(COS(RADIANS(r.wind_direction))) + )) < 0 THEN 360 + ELSE 0 + END, 2) as wind_direction, + -- 湿度取平均 + ROUND(AVG(r.humidity)::numeric, 2) as relative_humidity + FROM stations s + JOIN rs485_weather_data r ON s.station_id = r.station_id + WHERE r.timestamp >= '$START_TIME' AND r.timestamp < '$END_TIME' + GROUP BY s.station_id, s.password + ) + SELECT + '0', -- latitude + '0', -- longitude + output_station_id, -- station_id (使用password字段) + '', -- station_name + date_time, -- date_time + '0', -- elevation + COALESCE(pressure::text, '0'), + COALESCE(temperature::text, '0'), + '0', -- dewpoint + COALESCE(wind_speed::text, '0'), + COALESCE(wind_direction::text, '0'), + COALESCE(relative_humidity::text, '0'), + '', -- ztd + '' -- pwv + FROM avg_data + ORDER BY output_station_id;" >> "$CURRENT_FILE" 2>> "$LOG_FILE" + +# 检查psql执行状态 +if [ $? -eq 0 ]; then + echo "数据导出成功" >> "$LOG_FILE" +else + echo "数据导出失败" >> "$LOG_FILE" +fi + +# 更新最后导出时间 +echo "$END_TIME" > "$LAST_EXPORT_TIME_FILE" + +# 记录结束时间 +echo "=== 结束导出: $(date) ===" >> "$LOG_FILE" +echo "" >> "$LOG_FILE" + +# 保持日志文件大小合理(保留最后1000行) +tail -n 1000 "$LOG_FILE" > "${LOG_FILE}.tmp" && mv "${LOG_FILE}.tmp" "$LOG_FILE" + +# 清除密码环境变量(安全考虑) +unset PGPASSWORD diff --git a/export/get.sh b/export/get.sh new file mode 100644 index 0000000..fe387a8 --- /dev/null +++ b/export/get.sh @@ -0,0 +1,60 @@ +#!/bin/bash + +# 设置远程服务器信息 +REMOTE_USER="root" +REMOTE_HOST="8.134.185.53" +REMOTE_PORT="30001" +REMOTE_PATH="/root/rain/weather-station/dataTransfer/data/" +LOCAL_PATH="/home/imdroid/Build_WRF/cycling_data" # 使用当前目录 +LOG_FILE="${LOCAL_PATH}/sync.log" + +# 确保本地目录存在 +mkdir -p "$LOCAL_PATH" + +# 记录开始时间 +echo "=== 开始同步: $(date) ===" >> "$LOG_FILE" + +# 使用rsync进行增量同步 +# -a: 归档模式,保持所有文件属性 +# -v: 详细输出 +# -z: 传输时压缩数据 +# -t: 保持时间戳 +# -P: 显示进度并允许断点续传 +# -e: 指定ssh命令和端口 +# --delete: 删除目标目录中源目录没有的文件 +# --timeout=60: 设置超时时间 +# --bwlimit=1000: 限制带宽(KB/s) +rsync -avzt \ + -P \ + -e "ssh -p ${REMOTE_PORT}" \ + --delete \ + --timeout=60 \ + --bwlimit=1000 \ + --include="*.csv" \ + --include="*.gz" \ + --exclude="*" \ + --log-file="$LOG_FILE" \ + "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}" \ + "${LOCAL_PATH}/" + +# 检查rsync退出状态 +if [ $? -eq 0 ]; then + echo "同步成功完成" >> "$LOG_FILE" + + # 检查是否有新文件同步 + NEW_FILES=$(find "${LOCAL_PATH}" -type f -mmin -10 \( -name "*.csv" -o -name "*.gz" \)) + if [ ! -z "$NEW_FILES" ]; then + echo "新同步的文件:" >> "$LOG_FILE" + echo "$NEW_FILES" >> "$LOG_FILE" + fi +else + echo "同步失败,错误代码: $?" >> "$LOG_FILE" + # 可以在这里添加告警通知(如发送邮件) +fi + +# 记录同步时间 +echo "=== 结束同步: $(date) ===" >> "$LOG_FILE" +echo "" >> "$LOG_FILE" + +# 保持日志文件大小合理(保留最后1000行) +tail -n 1000 "$LOG_FILE" > "${LOG_FILE}.tmp" && mv "${LOG_FILE}.tmp" "$LOG_FILE" diff --git a/main.go b/main.go index cff1ccc..64273a7 100644 --- a/main.go +++ b/main.go @@ -128,9 +128,8 @@ func startUDP() { asciiDump := asciiDump(rawData) log.Printf("ASCII码:\n%s", asciiDump) - // 检查数据是否为RS485格式 if len(rawData) == 25 && rawData[0] == 0x24 { - log.Println("=== 检测到RS485设备数据 ===") + log.Println("485 型气象站数据") // 生成源码字符串(用于日志记录) sourceHex := strings.ReplaceAll(strings.TrimSpace(hexDump), "\n", " ") @@ -160,7 +159,7 @@ func startUDP() { rs485Data.RawDataHex = sourceHex // 打印解析结果到日志 - log.Println("=== RS485解析结果 ===") + log.Println("=== RS485 ===") log.Printf("设备ID: RS485-%s", rs485Data.DeviceID) log.Printf("温度: %.2f°C", rs485Data.Temperature) log.Printf("湿度: %.1f%%", rs485Data.Humidity)