571 lines
25 KiB
Python
571 lines
25 KiB
Python
|
|
import struct
|
|||
|
|
|
|||
|
|
class VdesDemodData:
|
|||
|
|
def __init__(self):
|
|||
|
|
self.hello = "VDES/AIS解调数据解析工具类"
|
|||
|
|
|
|||
|
|
self.payload_fragments = [] # 用于存储长消息分片数据的数组
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main(self, demod_data):
|
|||
|
|
demod_data_type = self.get_data_type(demod_data)
|
|||
|
|
# print('demod_data_type:', demod_data_type)
|
|||
|
|
# 判断解调数据是什么类型,类型有卫星公告牌、消息片段等
|
|||
|
|
if demod_data_type == 30 or demod_data_type == 31 or demod_data_type == 32:
|
|||
|
|
# 解析出消息片段中的字段
|
|||
|
|
message_fragment = self.get_message_demod_data(demod_data)
|
|||
|
|
# 处理消息片段
|
|||
|
|
self.message_fragment_processing(message_fragment)
|
|||
|
|
# elif demod_data_type == 1:
|
|||
|
|
# sbb1 = self.get_sbb_fragment_data_1(demod_data)
|
|||
|
|
# print(sbb1)
|
|||
|
|
# elif demod_data_type == 2:
|
|||
|
|
# sbb2 = self.get_sbb_fragment_data_2(demod_data)
|
|||
|
|
# print(sbb2)
|
|||
|
|
# elif demod_data_type == 3:
|
|||
|
|
# sbb3 = self.get_sbb_fragment_data_3(demod_data)
|
|||
|
|
# print(sbb3)
|
|||
|
|
# elif demod_data_type == 4:
|
|||
|
|
# sbb4 = self.get_sbb_fragment_data_4(demod_data)
|
|||
|
|
# print(sbb4)
|
|||
|
|
# elif demod_data_type == 5:
|
|||
|
|
# sbb5 = self.get_sbb_fragment_data_5(demod_data)
|
|||
|
|
# print(sbb5)
|
|||
|
|
# elif demod_data_type == 6:
|
|||
|
|
# sbb6 = self.get_sbb_fragment_data_6(demod_data)
|
|||
|
|
# print(sbb6)
|
|||
|
|
# elif demod_data_type == 10:
|
|||
|
|
# sbb10 = self.get_sbb_fragment_data_10(demod_data)
|
|||
|
|
# print(sbb10)
|
|||
|
|
# elif demod_data_type == 11:
|
|||
|
|
# sbb11 = self.get_sbb_fragment_data_11(demod_data)
|
|||
|
|
# print(sbb11)
|
|||
|
|
# elif demod_data_type == 12:
|
|||
|
|
# sbb12 = self.get_sbb_fragment_data_12(demod_data)
|
|||
|
|
# print(sbb12)
|
|||
|
|
# elif demod_data_type == 18:
|
|||
|
|
# sbb18 = self.get_sbb_fragment_data_18(demod_data)
|
|||
|
|
# print(sbb18)
|
|||
|
|
# elif demod_data_type == 20:
|
|||
|
|
# sbb20 = self.get_sbb_fragment_data_20(demod_data)
|
|||
|
|
# print(sbb20)
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_data_type(self, demod_data):
|
|||
|
|
"""从二进制数据中提取第一个字节作为类型字段"""
|
|||
|
|
if demod_data:
|
|||
|
|
data_type = struct.unpack('>B', demod_data[:1])[0]
|
|||
|
|
return data_type
|
|||
|
|
else:
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_message_demod_data(self, packed_data):
|
|||
|
|
"""解码VDES解调信息字段"""
|
|||
|
|
header_size = struct.calcsize('>B H I B B I H')
|
|||
|
|
header = packed_data[:header_size]
|
|||
|
|
Type, payload_size, source_id, satellite_id, session_id, dest_id, remainder_fragment_num = \
|
|||
|
|
struct.unpack('>B H I B B I H', header)
|
|||
|
|
# 计算负载字节长度进去截取,去除帧尾
|
|||
|
|
print(header_size)
|
|||
|
|
print(payload_size)
|
|||
|
|
payload = packed_data[header_size:header_size+payload_size-12]
|
|||
|
|
print('packed_data:', packed_data.hex())
|
|||
|
|
print('payload:', payload.hex())
|
|||
|
|
# 将UTF-8编码的二进制payload解码为字符串
|
|||
|
|
try:
|
|||
|
|
decoded_payload = payload.decode('utf-8')
|
|||
|
|
except UnicodeDecodeError:
|
|||
|
|
decoded_payload = payload # 如果解码失败,保留原始二进制数据
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
'Type': Type,
|
|||
|
|
'Payload_size': payload_size,
|
|||
|
|
'Source_id': source_id,
|
|||
|
|
'Satellite_id': satellite_id,
|
|||
|
|
'Session_id': session_id,
|
|||
|
|
'Dest_id': dest_id,
|
|||
|
|
'Remainder_Fragment_num': remainder_fragment_num,
|
|||
|
|
'Payload': decoded_payload # 返回解码后的字符串
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def message_fragment_processing(self, message_fragment):
|
|||
|
|
|
|||
|
|
combined_data = self.message_fragment_splicing(message_fragment)
|
|||
|
|
# 此处需要判断接收的消息数据格式----------------------------------------
|
|||
|
|
if combined_data is not None:
|
|||
|
|
# print("完整消息:", combined_data)
|
|||
|
|
# 保存为图片文件
|
|||
|
|
import os
|
|||
|
|
from datetime import datetime
|
|||
|
|
|
|||
|
|
# 创建保存目录(如果不存在)
|
|||
|
|
save_dir = 'E:\projects\wxwx\projects_job\VDES_Projects\报文模拟解析\地检设备模拟\\tcp_data'
|
|||
|
|
os.makedirs(save_dir, exist_ok=True)
|
|||
|
|
|
|||
|
|
# 生成文件名(带时间戳)
|
|||
|
|
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
|||
|
|
filename = os.path.join(save_dir, f'received_image_{timestamp}.jpg') # 假设是JPEG格式
|
|||
|
|
|
|||
|
|
# 写入文件
|
|||
|
|
with open(filename, 'wb') as f:
|
|||
|
|
f.write(combined_data)
|
|||
|
|
print(f"图片已保存到: {filename}")
|
|||
|
|
return
|
|||
|
|
if combined_data is not None:
|
|||
|
|
MMSI = demod_data['Dest_id']
|
|||
|
|
print(f"发送者MMSI: {MMSI}")
|
|||
|
|
print(f"消息: {combined_data}")
|
|||
|
|
# 查询或创建通讯录记录
|
|||
|
|
contact, created = Contacts.objects.get_or_create(MMSI=MMSI)
|
|||
|
|
Id = contact.Id
|
|||
|
|
contact, created = HistorySession.objects.get_or_create(FormId=Id, MMSI=MMSI)
|
|||
|
|
content = Content.objects.create(
|
|||
|
|
SendId=Id,
|
|||
|
|
ReciverId=1,
|
|||
|
|
Content="<p>"+combined_data+"</p>",
|
|||
|
|
Type=0, # 0=html文本
|
|||
|
|
State=1, # 已发送
|
|||
|
|
NoCode=str(int(time.time())) , # 你可以放时间戳
|
|||
|
|
CreateDateUtc=datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
|
|||
|
|
ReadFlag=0,
|
|||
|
|
SoundStatus=0
|
|||
|
|
)
|
|||
|
|
flag = MessageFlag.objects.first()
|
|||
|
|
if flag:
|
|||
|
|
flag.has_new_message = True
|
|||
|
|
flag.save()
|
|||
|
|
def message_fragment_splicing(self, demod_data):
|
|||
|
|
"""拼接消息分片数据"""
|
|||
|
|
fragment_num = demod_data['Fragment_num']
|
|||
|
|
# print(self.payload_fragments)
|
|||
|
|
if demod_data['Type'] == 30: # 开始分片
|
|||
|
|
print("------------------开始——————————————————————————————————————————————")
|
|||
|
|
self.payload_fragments = [] # 清空数组
|
|||
|
|
self.payload_fragments.append(demod_data['Payload'])
|
|||
|
|
|
|||
|
|
elif demod_data['Type'] == 31: # 数据分片
|
|||
|
|
self.payload_fragments.append(demod_data['Payload'])
|
|||
|
|
|
|||
|
|
elif demod_data['Type'] == 32: # 结束分片
|
|||
|
|
# 拼接所有有效分片
|
|||
|
|
print("------------------结束——————————————————————————————————————————————")
|
|||
|
|
self.payload_fragments.append(demod_data['Payload'])
|
|||
|
|
combined_payload = b''.join([p for p in self.payload_fragments if p is not None])
|
|||
|
|
print(len(self.payload_fragments))
|
|||
|
|
return combined_payload
|
|||
|
|
return None # 如果不是结束分片,返回None
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_1(self, demod_data):
|
|||
|
|
"""解析类型为1的公告牌起始片段数据"""
|
|||
|
|
format_str = '>B B B B H I H B H H B H' # 总共20字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:20])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['satellite_id'] = fields[1] # 卫星ID
|
|||
|
|
res['primary_network_id'] = fields[2] # 主网络ID
|
|||
|
|
res['roaming_network_id'] = fields[3] # 漫游网络ID
|
|||
|
|
res['sbb_version'] = fields[4] # SBB版本
|
|||
|
|
res['start_time'] = fields[5] # 开始时间
|
|||
|
|
res['validity_period'] = fields[6] # 可用期限
|
|||
|
|
|
|||
|
|
# 解析服务能力字段
|
|||
|
|
capability_field = fields[7] #服务能力
|
|||
|
|
res['itu_compatibility'] = (capability_field >> 4) & 0x0F # ITU-R M.2092建议书版兼容
|
|||
|
|
res['reserved_bits'] = capability_field & 0x0F # 4个LSB保留位
|
|||
|
|
|
|||
|
|
res['sbb_spare_frequency'] = fields[8] # SBB备用频率
|
|||
|
|
res['uplink_max_length'] = fields[9] # 上行链路消息最大长度
|
|||
|
|
res['reserved'] = fields[10] # 保留字段
|
|||
|
|
res['total_message_length'] = fields[11] # 消息总长度
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_2(self, demod_data):
|
|||
|
|
"""解析类型为2的公告牌片段数据"""
|
|||
|
|
format_str = '>B H H B 6B 6B H H B 6B 6B' # 总共35字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:35])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['downlink_frequency_a'] = fields[1] # 下行链路中心频率A
|
|||
|
|
res['uplink_frequency_a'] = fields[2] # 上行链路中心频率A
|
|||
|
|
|
|||
|
|
# 解析带宽A字段
|
|||
|
|
bandwidth_a = fields[3]
|
|||
|
|
res['downlink_bandwidth_a'] = (bandwidth_a >> 4) & 0x0F # 下行链路带宽A
|
|||
|
|
res['uplink_bandwidth_a'] = bandwidth_a & 0x0F # 上行链路带宽A
|
|||
|
|
|
|||
|
|
channel_slot_lengths_a = []
|
|||
|
|
for i in range(4, 10): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的时隙长度
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_slot_lengths_a.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_slot_lengths_a'] = channel_slot_lengths_a
|
|||
|
|
|
|||
|
|
# 解析逻辑信道功能A (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_functions_a = []
|
|||
|
|
for i in range(10, 16): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的功能
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_functions_a.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_functions_a'] = channel_functions_a
|
|||
|
|
|
|||
|
|
res['downlink_frequency_b'] = fields[16] # 下行链路中心频率B
|
|||
|
|
res['uplink_frequency_b'] = fields[17] # 上行链路中心频率B
|
|||
|
|
|
|||
|
|
# 解析带宽B字段
|
|||
|
|
bandwidth_b = fields[18]
|
|||
|
|
res['downlink_bandwidth_b'] = (bandwidth_b >> 4) & 0x0F # 下行链路带宽B
|
|||
|
|
res['uplink_bandwidth_b'] = bandwidth_b & 0x0F # 上行链路带宽B
|
|||
|
|
|
|||
|
|
# 解析逻辑信道时隙长度B (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_slot_lengths_b = []
|
|||
|
|
for i in range(19, 25): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的时隙长度
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_slot_lengths_b.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_slot_lengths_b'] = channel_slot_lengths_b
|
|||
|
|
|
|||
|
|
# 解析逻辑信道功能B (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_functions_b = []
|
|||
|
|
for i in range(25, 31): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的功能
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_functions_b.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_functions_b'] = channel_functions_b
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_3(self, demod_data):
|
|||
|
|
"""解析类型为3的公告牌片段数据(逻辑信道24-47定义,频率对C和D)"""
|
|||
|
|
format_str = '>B H H B 6B 6B H H B 6B 6B' # 总共35字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:35])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['downlink_frequency_c'] = fields[1] # 下行链路中心频率C
|
|||
|
|
res['uplink_frequency_c'] = fields[2] # 上行链路中心频率C
|
|||
|
|
|
|||
|
|
# 解析带宽C字段
|
|||
|
|
bandwidth_c = fields[3]
|
|||
|
|
res['downlink_bandwidth_c'] = (bandwidth_c >> 4) & 0x0F # 下行链路带宽C
|
|||
|
|
res['uplink_bandwidth_c'] = bandwidth_c & 0x0F # 上行链路带宽C
|
|||
|
|
|
|||
|
|
# 解析逻辑信道时隙长度C (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_slot_lengths_c = []
|
|||
|
|
for i in range(4, 10): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的时隙长度
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_slot_lengths_c.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_slot_lengths_c'] = channel_slot_lengths_c
|
|||
|
|
|
|||
|
|
# 解析逻辑信道功能C (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_functions_c = []
|
|||
|
|
for i in range(10, 16): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的功能
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_functions_c.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_functions_c'] = channel_functions_c
|
|||
|
|
|
|||
|
|
res['downlink_frequency_d'] = fields[16] # 下行链路中心频率D
|
|||
|
|
res['uplink_frequency_d'] = fields[17] # 上行链路中心频率D
|
|||
|
|
|
|||
|
|
# 解析带宽D字段
|
|||
|
|
bandwidth_d = fields[18]
|
|||
|
|
res['downlink_bandwidth_d'] = (bandwidth_d >> 4) & 0x0F # 下行链路带宽D
|
|||
|
|
res['uplink_bandwidth_d'] = bandwidth_d & 0x0F # 上行链路带宽D
|
|||
|
|
|
|||
|
|
# 解析逻辑信道时隙长度D (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_slot_lengths_d = []
|
|||
|
|
for i in range(19, 25): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的时隙长度
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_slot_lengths_d.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_slot_lengths_d'] = channel_slot_lengths_d
|
|||
|
|
|
|||
|
|
# 解析逻辑信道功能D (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_functions_d = []
|
|||
|
|
for i in range(25, 31): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的功能
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_functions_d.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_functions_d'] = channel_functions_d
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_4(self, demod_data):
|
|||
|
|
"""解析类型为4的公告牌片段数据(逻辑信道48-71定义,频率对E和F)"""
|
|||
|
|
format_str = '>B H H B 6B 6B H H B 6B 6B' # 总共35字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:35])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['downlink_frequency_e'] = fields[1] # 下行链路中心频率E
|
|||
|
|
res['uplink_frequency_e'] = fields[2] # 上行链路中心频率E
|
|||
|
|
|
|||
|
|
# 解析带宽E字段
|
|||
|
|
bandwidth_e = fields[3]
|
|||
|
|
res['downlink_bandwidth_e'] = (bandwidth_e >> 4) & 0x0F # 下行链路带宽E
|
|||
|
|
res['uplink_bandwidth_e'] = bandwidth_e & 0x0F # 上行链路带宽E
|
|||
|
|
|
|||
|
|
# 解析逻辑信道时隙长度E (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_slot_lengths_e = []
|
|||
|
|
for i in range(4, 10): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的时隙长度
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_slot_lengths_e.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_slot_lengths_e'] = channel_slot_lengths_e
|
|||
|
|
|
|||
|
|
# 解析逻辑信道功能E (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_functions_e = []
|
|||
|
|
for i in range(10, 16): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的功能
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_functions_e.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_functions_e'] = channel_functions_e
|
|||
|
|
|
|||
|
|
res['downlink_frequency_f'] = fields[16] # 下行链路中心频率F
|
|||
|
|
res['uplink_frequency_f'] = fields[17] # 上行链路中心频率F
|
|||
|
|
|
|||
|
|
# 解析带宽F字段
|
|||
|
|
bandwidth_f = fields[18]
|
|||
|
|
res['downlink_bandwidth_f'] = (bandwidth_f >> 4) & 0x0F # 下行链路带宽F
|
|||
|
|
res['uplink_bandwidth_f'] = bandwidth_f & 0x0F # 上行链路带宽F
|
|||
|
|
|
|||
|
|
# 解析逻辑信道时隙长度F (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_slot_lengths_f = []
|
|||
|
|
for i in range(19, 25): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的时隙长度
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_slot_lengths_f.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_slot_lengths_f'] = channel_slot_lengths_f
|
|||
|
|
|
|||
|
|
# 解析逻辑信道功能F (6字节,表示12个信道,每个信道4比特)
|
|||
|
|
channel_functions_f = []
|
|||
|
|
for i in range(25, 31): # 6个字节
|
|||
|
|
byte_val = fields[i]
|
|||
|
|
# 高4位和低4位分别代表两个信道的功能
|
|||
|
|
high_nibble = (byte_val >> 4) & 0x0F
|
|||
|
|
low_nibble = byte_val & 0x0F
|
|||
|
|
channel_functions_f.extend([high_nibble, low_nibble])
|
|||
|
|
res['channel_functions_f'] = channel_functions_f
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_5(self, demod_data):
|
|||
|
|
"""解析类型为5的公告牌片段数据(SBB数字签名第1部分)"""
|
|||
|
|
format_str = '>B 32s' # 总共33字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:33])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['digital_signature_part1'] = fields[1] # 数字签名第1部分
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_6(self, demod_data):
|
|||
|
|
"""解析类型为6的公告牌片段数据(SBB数字签名第2部分)"""
|
|||
|
|
format_str = '>B 32s' # 总共33字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:33])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['digital_signature_part1'] = fields[1] # 数字签名第2部分
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_10(self, demod_data):
|
|||
|
|
"""解析类型为10的媒体访问控制数据"""
|
|||
|
|
format_str = '>B H B B B B B B B B H' # 总共13字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:13])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['payload_size'] = fields[1] # 载荷大小
|
|||
|
|
res['satellite_id'] = fields[2] # 卫星ID
|
|||
|
|
res['primary_network_id'] = fields[3] # 主网络ID
|
|||
|
|
res['roaming_network_id'] = fields[4] # 漫游网络ID
|
|||
|
|
res['media_access_priority'] = fields[5] # 媒体接入优先级
|
|||
|
|
res['random_selection_interval'] = fields[6] # 随机选择间隔
|
|||
|
|
res['rac_message_access_limit'] = fields[7] # RAC消息接入限制
|
|||
|
|
res['network_status'] = fields[8] # 网络状态
|
|||
|
|
|
|||
|
|
# 解析自动重复请求/超时限制字段
|
|||
|
|
arq_timeout_field = fields[9]
|
|||
|
|
res['fragment_retry_count'] = (arq_timeout_field >> 4) & 0x0F # 4个MSB:片段重试次数
|
|||
|
|
res['timeout_timer_setting'] = arq_timeout_field & 0x0F # 4个LSB:超时定时器设置
|
|||
|
|
|
|||
|
|
res['announcement_version_number'] = fields[10] # 公告版本号
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_11(self, demod_data):
|
|||
|
|
"""解析寻呼数据(类型11)"""
|
|||
|
|
# 总共35字节 (1+2+4+4+4+4+4+4+4+4)
|
|||
|
|
format_str = '>B H I I I I I I I I'
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:35])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['payload_size'] = fields[1] # 载荷大小
|
|||
|
|
res['vessel_station_id_1'] = fields[2] # 1号船舶电台ID
|
|||
|
|
res['vessel_station_id_2'] = fields[3] # 2号船舶电台ID
|
|||
|
|
res['vessel_station_id_3'] = fields[4] # 3号船舶电台ID
|
|||
|
|
res['vessel_station_id_4'] = fields[5] # 4号船舶电台ID
|
|||
|
|
res['vessel_station_id_5'] = fields[6] # 5号船舶电台ID
|
|||
|
|
res['vessel_station_id_6'] = fields[7] # 6号船舶电台ID
|
|||
|
|
res['vessel_station_id_7'] = fields[8] # 7号船舶电台ID
|
|||
|
|
res['vessel_station_id_8'] = fields[9] # 8号船舶电台ID
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_12(self, demod_data):
|
|||
|
|
"""解析资源分配数据(类型12)"""
|
|||
|
|
# 总共37字节 (1+2+4+1+1+1+1 + 4+1+1+1+1 + 4+1+1+1+1 + 4+1+1+1+1)
|
|||
|
|
format_str = '>B H I B B B B I B B B B I B B B B I B B B B'
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:35])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['payload_size'] = fields[1] # 载荷大小
|
|||
|
|
res['vessel_station_id_1'] = fields[2] # 船舶电台ID 1
|
|||
|
|
res['logical_channel_1'] = fields[3] # 逻辑信道1
|
|||
|
|
res['link_id_1'] = fields[4] # 链路ID 1
|
|||
|
|
res['session_id_1'] = fields[5] # 会话ID 1
|
|||
|
|
res['uplink_cqi_1'] = fields[6] # 上行链路链路CQI 1
|
|||
|
|
res['vessel_station_id_2'] = fields[7] # 船舶电台ID 2
|
|||
|
|
res['logical_channel_2'] = fields[8] # 逻辑信道2
|
|||
|
|
res['link_id_2'] = fields[9] # 链路ID 2
|
|||
|
|
res['session_id_2'] = fields[10] # 会话ID 2
|
|||
|
|
res['uplink_cqi_2'] = fields[11] # 上行链路链路CQI 2
|
|||
|
|
res['vessel_station_id_3'] = fields[12] # 船舶电台ID 3
|
|||
|
|
res['logical_channel_3'] = fields[13] # 逻辑信道3
|
|||
|
|
res['link_id_3'] = fields[14] # 链路ID 3
|
|||
|
|
res['session_id_3'] = fields[15] # 会话ID 3
|
|||
|
|
res['uplink_cqi_3'] = fields[16] # 上行链路链路CQI 3
|
|||
|
|
res['vessel_station_id_4'] = fields[17] # 船舶电台ID 4
|
|||
|
|
res['logical_channel_4'] = fields[18] # 逻辑信道4
|
|||
|
|
res['link_id_4'] = fields[19] # 链路ID 4
|
|||
|
|
res['session_id_4'] = fields[20] # 会话ID 4
|
|||
|
|
res['uplink_cqi_4'] = fields[21] # 上行链路链路CQI 4
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_18(self, demod_data):
|
|||
|
|
"""解析送达通知数据(类型18)"""
|
|||
|
|
# 总共34字节 (1+2+1+4+1+4+1+4+1+4+1+4+1+4+1)
|
|||
|
|
format_str = '>B H B I B I B I B I B I B I B'
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:34])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['payload_size'] = fields[1] # 载荷大小
|
|||
|
|
res['satellite_id'] = fields[2] # 卫星ID
|
|||
|
|
res['vessel_station_id_1'] = fields[3] # 1号船舶电台ID
|
|||
|
|
res['session_id_1'] = fields[4] # 1号船舶会话ID
|
|||
|
|
res['vessel_station_id_2'] = fields[5] # 2号船舶电台ID
|
|||
|
|
res['session_id_2'] = fields[6] # 2号船舶会话ID
|
|||
|
|
res['vessel_station_id_3'] = fields[7] # 3号船舶电台ID
|
|||
|
|
res['session_id_3'] = fields[8] # 3号船舶会话ID
|
|||
|
|
res['vessel_station_id_4'] = fields[9] # 4号船舶电台ID
|
|||
|
|
res['session_id_4'] = fields[10] # 4号船舶会话ID
|
|||
|
|
res['vessel_station_id_5'] = fields[11] # 5号船舶电台ID
|
|||
|
|
res['session_id_5'] = fields[12] # 5号船舶会话ID
|
|||
|
|
res['vessel_station_id_6'] = fields[13] # 6号船舶电台ID
|
|||
|
|
res['session_id_6'] = fields[14] # 6号船舶会话ID
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|
|||
|
|
|
|||
|
|
def get_sbb_fragment_data_20(self, demod_data):
|
|||
|
|
"""解析资源请求数据(类型20)"""
|
|||
|
|
format_str = '>B I B B B B B' # 总共10字节
|
|||
|
|
|
|||
|
|
# 解包数据
|
|||
|
|
fields = struct.unpack(format_str, demod_data[:10])
|
|||
|
|
|
|||
|
|
# 创建结果字典
|
|||
|
|
res = {}
|
|||
|
|
res['type'] = fields[0] # 类型
|
|||
|
|
res['vessel_station_id'] = fields[1] # 船舶电台ID
|
|||
|
|
res['satellite_id'] = fields[2] # 卫星ID
|
|||
|
|
|
|||
|
|
# 解析优先级和消息长度字段
|
|||
|
|
priority_length_field = fields[3]
|
|||
|
|
res['priority'] = (priority_length_field >> 4) & 0x0F # 比特7-4,优先级
|
|||
|
|
res['message_length'] = priority_length_field & 0x0F # 比特3-0,消息长度
|
|||
|
|
|
|||
|
|
res['terminal_capability'] = fields[4] # 终端能力
|
|||
|
|
res['downlink_asc_cqi'] = fields[5] # 下行链路ASC CQI
|
|||
|
|
res['tbd'] = fields[6] # TBD
|
|||
|
|
|
|||
|
|
# 去除帧尾数据,只返回解析后的数据
|
|||
|
|
return res
|