嵌入式系统的外设日志记录着串口发给主机的报文信息,报文内容是16进制,监控状态和问题的时候往往需要人去对照协议或者记住16进制报文的含义,所以写了这个脚本来翻译日志,让其更为直观易读。
协议对照文本
将报文协议写在一个ini文件内,便于查找翻译,根据协议特点按行写、按字节写、甚至按不同的位写。比如:
[PROTOCOL]
[Modes status]
[gate configuration]0,0=| Entry End |=END
[gate configuration]0,1=| Exit End |=END
[gate configuration]1,0=| Reversible |=END
[gate mode]0,0,0=| Out of service |=END
[gate mode]0,0,1=| Entry mode|=END
[gate mode]0,1,0=| Exit mode|=END
[gate mode]0,1,1=| Free Exit mode|=END
[gate mode]1,0,0=| Bi-directional mode|=END
[gate mode]1,0,1=| Fully free mode|=END
[gate mode]1,1,0=| Maintenance mode|=END
[gate mode]1,1,1=| Emergency mode|=END
[aisle mode]0=| Normally closed |=END
[aisle mode]1=| Normally opened |=END
[NormalByte]
[General status]:bits=0 2 4 6 7=END
[General status]:bit0_0=\033[1;35m | Flap OK |\033[0m =END
[General status]:bit0_1=\033[1;31m**Flap failure**\033[0m =END
[General status]:bit2_0=\033[1;35m | Repair Door Closed |\033[0m =END
[General status]:bit2_1=\033[1;31m**Repair Door Opened**\033[0m=END
[General status]:bit4_0=\033[1;35m | No Passage Cancellation |\033[0m =END
[General status]:bit4_1=\033[1;31m**Cancellation on Time-out**\033[0m=END
[General status]:bit6_0=\033[1;35m | No Emergency |\033[0m =END
[General status]:bit6_1=\033[1;31m**Emergency Mode**\033[0m=END
[General status]:bit7_0=\033[1;31m| LCM Not Configured |\033[0m =END
[General status]:bit7_1=\033[1;35m **LCM Well Configured**\033[0m =END
[Zone status]:bits=0 1 2 3 4 5 6 7=END
[Zone status]:bit0_0=\033[1;35m | zone 1 clear |\033[0m =END
[Zone status]:bit0_1=\033[1;31m**zone 1 occupied**\033[0m =END
[Zone status]:bit1_0=\033[1;35m | zone 2 clear |\033[0m =END
[Zone status]:bit1_1=\033[1;31m**zone 2 occupied**\033[0m =END
[Zone status]:bit2_0=\033[1;35m | zone 3 clear |\033[0m =END
[Zone status]:bit2_1=\033[1;31m**zone 3 occupied**\033[0m =END
[Zone status]:bit3_0=\033[1;35m | zone 4 clear |\033[0m =END
[Zone status]:bit3_1=\033[1;31m**zone 4 occupied**\033[0m =END
[Zone status]:bit4_1=\033[1;31m**intrusion!**\033[0m =END
[Zone status]:bit5_1=\033[1;31m**Sensor test in progress!**\033[0m =END
[Zone status]:bit6_1=\033[1;31m**Through beam sensor!**\033[0m =END
[Zone status]:bit7_0=\033[1;35m| direction:Entry|\033[0m =END
[Zone status]:bit7_1=\033[1;35m|direction:Exit|\033[0m =END
[Fraud Status]:bits=0 5 6=END
[Fraud Status]:bit0_0=\033[1;35m | Flaps are not forced |\033[0m =END
[Fraud Status]:bit0_1=\033[1;31m**Flap forced!!**\033[0m =END
[Fraud Status]:bit5_0=\033[1;35m | No Wrong Way Fraud |\033[0m =END
[Fraud Status]:bit5_1=\033[1;31m**1 Wrong Way Fraud!!**\033[0m =END
[Fraud Status]:bit6_0=\033[1;35m | No Tail Gating Fraud |\033[0m =END
[Fraud Status]:bit6_1=\033[1;31m**1 Tail Gating Fraud !!**\033[0m =END
[INI]
GetAllReg(读取所有寄存器)= 01 03 00 96 00 07 E4 24
SetDialogDetection(保持PLC活跃)= 01 06 00 72 00 01 E8 11
ResponseofSetMultiReg(收到配置命令)= 01 10 00 64 00 16 00 18
Normally Close and Bi_Dir mode(设置常闭双向模式)= 01 06 00 64 A4 01 73 15
Normally Close and OOS mode(设置常闭OOS模式)= 01 06 00 64 A0 01 71 D5
Normally Close and Entry mode(设置常闭单进模式)= 01 06 00 64 A1 01 73 15
Normally Close and Exit mode(设置常闭单出模式)= 01 06 00 64 A2 01 71 D5
Normally Open and Bi_Dir mode(设置常开双向模式)= 01 06 00 64 B4 01 73 15
Normally Open and OOS mode(设置常开OOS模式)= 01 06 00 64 B0 01 71 D5
Normally Open and Entry mode(设置常开单进模式)= 01 06 00 64 B1 01 73 15
Normally Open and Exit mode(设置常开单出模式)= 01 06 00 64 B2 01 71 D5
TEST_Sensor_Start= 01 06 00 6B 05 00 FB 46
TEST_Flap_Start= 01 06 00 6B 04 00 FA D6
TEST_Signage_Start= 01 06 00 6B 06 00 FB B6
TEST_StopAll= 01 06 00 6B 00 00 F8 16
主程序
ParseLog $logfilenamestr
ParseLog子程序
ParseLog()
{
fname=$1
curLine=`awk 'END{print NR}' $fname`
while true
do
NewLine=`awk 'END{print NR}' $fname` #line numb in process
if (( ${curLine} < ${NewLine} ))
then
newStr=`sed -n "${curLine}p" $fname` #line string
echo ${newStr}
newCode=`echo ${newStr} |awk -F'<<' '{print $2}'` #com code
if [ "${newCode}" ]
then
echo -e "\t 收到 ${newCode} 解析:"
findstr=${newCode}
if [[ ${findstr:1:8} == "01 03 0E" ]] #read All Register
then
portstr=`Parse_AllReg ${findstr}` #函数返回字符串
echo -e "\033[1;35m $portstr \033[0m"
else
parsedStr=`grep "${findstr}" $iniFile| awk -F'=' '{print $1}'`
if [ "$parsedStr" ]
then
echo -e "\033[1;35m $parsedStr \033[0m"
else
echo -e "\033[1;35m !!Unknown Recv!! \033[0m"
fi
fi
else
newCode=`echo ${newStr} |awk -F'>>' '{print $2}'`
echo -e "\t 发送 ${newCode} 解析:"
findstr=${newCode}
if [[ ${findstr:1:14} == "01 10 00 64 00" ]] #Send out PDU configuration
then
ConfigStr=`Parse_Config ${findstr}` #函数返回字符串
echo -e "\033[1;35m ${ConfigStr} \033[0m"
else
parsedStr=`grep "${findstr:1:14}" $iniFile| awk -F'=' '{print $1}'`
if [ "$parsedStr" ]
then
echo -e "\033[1;31m $parsedStr \033[0m"
else
echo -e "\033[1;31m !!Unknown Sendout!! \033[0m"
fi
fi
fi
curLine=`expr ${curLine} + 1`
fi
done
}
- 先读取log文件,在循环中取出最新的一行:行号NewLine,新行内容存在newStr
- 本例选了一个Modbus 串口报文的设备
- 读到新行内容后,用awk 取不同的字节,做分析
- 有些需要在协议ini文件里查找翻译的子程序如下(其实就是用grep查找文本,找到需要翻译的报文所在行,再用awk分开“=”两边,取出解释性的文本):
iniFile='/root/protocol.ini'
function GetSpecificBit()
{
_Byte=`echo "ibase=16; $1"| bc` #16进制转10机制
_Bit=$2
_ret=$[ ${_Byte} >> ${_Bit} & 1 ]
echo $_ret
}
function ParseNormalByte()
{
strRet="$1 Value $2: \n"
strFind="\[$1\]:bits"
_bits=`grep "${strFind}" $iniFile| awk -F'=' '{print $2}'`
for _ibit in $_bits
do
#echo "_ibit = ${_ibit}"
_bitVal=`GetSpecificBit ${2} ${_ibit}`
#echo "_bitVal = ${_bitVal}"
strFind="\[${1}\]:bit${_ibit}_${_bitVal}"
#echo "strFind = ${strFind}"
_bitStr=`grep "${strFind}" $iniFile| awk -F'=' '{print $2}'`
#echo "_bitStr = ${_bitStr}"
strRet="${strRet} ${_bitStr}"
#echo "strRet = ${strRet}"
done
echo ${strRet}
}
function ParseModeStatusByte()
{
strRet="$1 Value $2: \n"
strFind="\[gate configuration\]"
_bitVal=`GetSpecificBit ${2} '7'`
strFind="${strFind}${_bitVal}"
_bitVal=`GetSpecificBit ${2} '6'`
strFind="${strFind},${_bitVal}"
_bitStr=`grep "${strFind}" $iniFile| awk -F'=' '{print $2}'`
strRet="${strRet} ${_bitStr}"
strFind="\[aisle mode\]"
_bitVal=`GetSpecificBit ${2} '4'`
strFind="${strFind}${_bitVal}"
_bitStr=`grep "${strFind}" $iniFile| awk -F'=' '{print $2}'`
strRet="${strRet} ${_bitStr}"
strFind="\[gate mode\]"
_bitVal=`GetSpecificBit ${2} '2'`
strFind="${strFind}${_bitVal}"
_bitVal=`GetSpecificBit ${2} '1'`
strFind="${strFind},${_bitVal}"
_bitVal=`GetSpecificBit ${2} '0'`
strFind="${strFind},${_bitVal}"
_bitStr=`grep "${strFind}" $iniFile| awk -F'=' '{print $2}'`
strRet="${strRet} ${_bitStr}"
echo ${strRet}
}