first commit
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(chmod +x *)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+154
@@ -0,0 +1,154 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#===============================================================================
|
||||||
|
# 气象站串口数据接收脚本 (Shell 版本)
|
||||||
|
# 功能等价于原 Python 脚本,读取串口数据 -> CRC 校验 -> 解析 -> 上传
|
||||||
|
#===============================================================================
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 配置(修改这里即可,不需要 TOML 文件)
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
URL="http://127.0.0.1:7763/v1/upload"
|
||||||
|
TTY="/dev/ttyUSB0"
|
||||||
|
BAUD=9600
|
||||||
|
WHOLE_LEN=11
|
||||||
|
DATA_LEN=7
|
||||||
|
CRC_LEN=4
|
||||||
|
|
||||||
|
echo "========================================"
|
||||||
|
echo " 气象站串口接收器 (Shell)"
|
||||||
|
echo "========================================"
|
||||||
|
echo "串口: $TTY"
|
||||||
|
echo "波特率: $BAUD"
|
||||||
|
echo "数据长度: $WHOLE_LEN 字节 (payload=$DATA_LEN, crc=$CRC_LEN)"
|
||||||
|
echo "服务器: $URL"
|
||||||
|
echo "========================================"
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# CRC32 计算(调用 python3 单行 —— 与 binascii.crc32 完全一致)
|
||||||
|
# 输入: 通过管道传入原始二进制字节
|
||||||
|
# 输出: 十进制无符号 CRC32 值
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
crc32() {
|
||||||
|
python3 -c "import binascii,sys; print(binascii.crc32(sys.stdin.buffer.read()) & 0xFFFFFFFF)"
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 符号扩展:把 16 位无符号值转为有符号
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
sign_extend16() {
|
||||||
|
local v=$1
|
||||||
|
if (( v >= 32768 )); then
|
||||||
|
echo $(( v - 65536 ))
|
||||||
|
else
|
||||||
|
echo $v
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 刷新串口输入缓冲区(等价于 Python 的 ser.reset_input_buffer())
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
flush_serial() {
|
||||||
|
# 临时切换到非阻塞模式,排空所有已缓冲数据
|
||||||
|
stty -F "$TTY" -icanon min 0 time 0 2>/dev/null || true
|
||||||
|
dd if="$TTY" bs=4096 count=1 of=/dev/null 2>/dev/null || true
|
||||||
|
# 恢复阻塞模式
|
||||||
|
stty -F "$TTY" -icanon min 1 time 0 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 配置串口
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
stty -F "$TTY" "$BAUD" cs8 -cstopb -parenb raw -echo
|
||||||
|
echo "串口已配置,开始监听..."
|
||||||
|
|
||||||
|
# 初始清空缓冲区
|
||||||
|
flush_serial
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 主循环:读帧 → 校验 → 解析 → 上传
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
pkt_count=0
|
||||||
|
err_count=0
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
# --- 1. 从串口读取完整一帧(阻塞直到凑齐 WHOLE_LEN 字节)---
|
||||||
|
tmpfile=$(mktemp)
|
||||||
|
# dd bs=1 逐字节读取,确保不提前返回(raw 模式下 min=1, time=0)
|
||||||
|
dd if="$TTY" bs=1 count="$WHOLE_LEN" of="$tmpfile" 2>/dev/null
|
||||||
|
|
||||||
|
# 校验实际读到的字节数
|
||||||
|
actual_len=$(stat -c%s "$tmpfile" 2>/dev/null || echo 0)
|
||||||
|
if (( actual_len != WHOLE_LEN )); then
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 2. 转为十六进制便于解析 ---
|
||||||
|
hex=$(od -An -tx1 -v "$tmpfile" | tr -d ' \n')
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
|
||||||
|
# 安全检查:hex 长度应该等于 WHOLE_LEN * 2
|
||||||
|
if (( ${#hex} != WHOLE_LEN * 2 )); then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 3. 拆分 payload 和 CRC ---
|
||||||
|
payload_hex="${hex:0:$((DATA_LEN * 2))}"
|
||||||
|
remote_crc_hex="${hex:$((DATA_LEN * 2)):$((CRC_LEN * 2))}"
|
||||||
|
remote_crc=$((16#$remote_crc_hex))
|
||||||
|
|
||||||
|
# --- 4. 计算本地 CRC32 并与远端比对 ---
|
||||||
|
local_crc=$(echo "$payload_hex" | xxd -r -p 2>/dev/null | crc32)
|
||||||
|
|
||||||
|
if (( remote_crc != local_crc )); then
|
||||||
|
((err_count++))
|
||||||
|
echo "[错误] CRC 校验失败 #${err_count} — 刷新缓冲区..."
|
||||||
|
flush_serial
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 5. 解析 payload: >Bhhh (大端: uint8, int16, int16, int16) ---
|
||||||
|
station_id=$((16#${payload_hex:0:2}))
|
||||||
|
t_raw=$(( 16#${payload_hex:2:4}))
|
||||||
|
p_raw=$(( 16#${payload_hex:6:4}))
|
||||||
|
rh_raw=$(( 16#${payload_hex:10:4}))
|
||||||
|
|
||||||
|
t=$(sign_extend16 $t_raw)
|
||||||
|
p=$(sign_extend16 $p_raw)
|
||||||
|
rh=$(sign_extend16 $rh_raw)
|
||||||
|
|
||||||
|
# 定点小数转换(原始值 / 10,保留 1 位小数)
|
||||||
|
t_val=$(awk "BEGIN {printf \"%.1f\", $t/10}")
|
||||||
|
p_val=$(awk "BEGIN {printf \"%.1f\", $p/10}")
|
||||||
|
rh_val=$(awk "BEGIN {printf \"%.1f\", $rh/10}")
|
||||||
|
|
||||||
|
# --- 6. 站台名称 ---
|
||||||
|
if (( station_id == 1 )); then
|
||||||
|
station_name="AAU"
|
||||||
|
else
|
||||||
|
station_name="unknown"
|
||||||
|
fi
|
||||||
|
|
||||||
|
((pkt_count++))
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo "[数据包 #${pkt_count}] station_id=$station_id ($station_name)"
|
||||||
|
echo " 温度: $t_val °C | 气压: $p_val hPa | 湿度: $rh_val %"
|
||||||
|
|
||||||
|
# --- 7. HTTP POST 上传 ---
|
||||||
|
json=$(printf '{"station_name":"%s","temperature":%s,"pressure":%s,"relative_humidity":%s}' \
|
||||||
|
"$station_name" "$t_val" "$p_val" "$rh_val")
|
||||||
|
|
||||||
|
http_code=$(curl -s -o /dev/null -w "%{http_code}" \
|
||||||
|
-X POST "$URL" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$json" 2>/dev/null || echo "000")
|
||||||
|
|
||||||
|
if [[ "$http_code" == "200" ]] || [[ "$http_code" == "201" ]]; then
|
||||||
|
echo " 上传成功 (HTTP $http_code)"
|
||||||
|
else
|
||||||
|
echo " 上传失败 (HTTP $http_code)"
|
||||||
|
echo " 数据: $json"
|
||||||
|
echo " 等待服务器连接..."
|
||||||
|
fi
|
||||||
|
done
|
||||||
Reference in New Issue
Block a user