Project

General

Profile

Feature #4263 » mhw2.py

Python MHW2 table parser script - Adam W, 2020-11-03 14:34

 
1
import sys, datetime, json
2

    
3
dict_chs = {}
4
dict_pr = {}
5
dict_des = {}
6

    
7
dict_output = {}
8

    
9
chans_read = False
10

    
11
packet = sys.stdin.buffer.read(3)
12

    
13
while sys.stdin.buffer.read !="":
14

    
15
    if len(packet) > 2 :
16
        tid = packet[0]
17
        ssi = packet[1] & 0x80
18
        tlen = (packet[1] & 0xF) << 8 | packet[2]
19

    
20
        packet = sys.stdin.buffer.read(tlen)
21
        if tid == 0xc8 and not chans_read :
22
            t_ext = packet[1]
23
            chans = packet[117]
24

    
25
            sid_pointer = 118
26
            ch_pointer = 118 + (chans*8)
27
            chan_count = 0
28

    
29
            if t_ext == 0 :
30
                if len(packet) > ch_pointer :
31
                    while chan_count < chans :
32
                        nid = packet[sid_pointer] << 8 | packet[sid_pointer+1]
33
                        tsid = packet[sid_pointer+2] << 8 | packet[sid_pointer+3]
34
                        sid = packet[sid_pointer+4] << 8 | packet[sid_pointer+5]
35
                        name_len = packet[ch_pointer] & 0x3f
36
                        name = packet[ch_pointer+1:ch_pointer+1+name_len].decode('iso8859-9')
37
                        dict_chs[chan_count+1] = {}
38
                        dict_chs[chan_count+1]['nid'] = nid
39
                        dict_chs[chan_count+1]['tsid'] = tsid
40
                        dict_chs[chan_count+1]['sid'] = sid
41
                        dict_chs[chan_count+1]['name'] = name
42
                        chan_count += 1
43
                        sid_pointer += 8
44
                        ch_pointer = ch_pointer+1+name_len
45
                    chans_read = True
46
        elif tid == 0xdc :
47
            pos = 5
48
            while pos+19 < len(packet) :
49
                ch_id = packet[4]+1
50
                mhw2_mjd_hi = packet[pos+11]
51
                mhw2_mjd_lo = packet[pos+12]
52
                mhw2_hours = (((packet[pos+13] & 0xf0) >> 4) * 10) + (packet[pos+13] & 0x0f)
53
                mhw2_minutes = (((packet[pos+14] & 0xf0) >> 4) * 10) + (packet[pos+14] & 0x0f)
54
                mhw2_seconds = (((packet[pos+15] & 0xf0) >> 4) * 10) + (packet[pos+15] & 0x0f)
55

    
56
                mhw2_epoch = (((mhw2_mjd_hi << 8 | mhw2_mjd_lo) - 40587) * 86400) + (mhw2_hours * 3600) + (mhw2_minutes * 60) + mhw2_seconds
57

    
58
                duration = ((packet[pos+16] << 8)|packet[pos+17]) >> 4
59
                mhw2_duration_hi = (duration&0xFF00) >> 8
60
                mhw2_duration_lo = duration&0xFF
61

    
62
                title_id = (packet[pos+7] << 24) | (packet[pos+8] << 16) | (packet[pos+9] << 8) | packet[pos+10]
63
                summary_id = (packet[pos+4] << 16) | (packet[pos+5] << 8) | packet[pos+6]
64
                slen = packet[pos+18] & 0x7f
65

    
66
                pr_title = packet[pos+19:pos+19+slen].decode('iso8859-9')
67

    
68
                if title_id not in dict_pr :
69
                    dict_pr[title_id] = {}
70

    
71
                dict_pr[title_id]['channel'] = ch_id
72
                dict_pr[title_id]['start'] = datetime.datetime.fromtimestamp(mhw2_epoch).strftime('%d/%m/%Y %H:%M:%S')
73
                dict_pr[title_id]['end'] = datetime.datetime.fromtimestamp(mhw2_epoch+(duration*60)).strftime('%d/%m/%Y %H:%M:%S')
74
                dict_pr[title_id]['title'] = pr_title
75
                dict_pr[title_id]['desc_id'] = summary_id
76

    
77
                pos = pos+19+slen+1
78
        elif tid == 0x96 :
79
            if ssi == 0x80 :
80
                #PID 644 TID 150 Short descriptions
81
                summary_id = (packet[6] << 16) | (packet[7] << 8) | packet[8]
82
                subt_len = packet[11]
83

    
84
                if not (len(packet) < (14+subt_len)):
85
                    subt_text = packet[12:12+subt_len].decode('iso8859-9')
86
                    desc_len = packet[12+subt_len+1]
87
                    if not (len(packet) < (26+subt_len+desc_len)) :
88
                        desc_text = packet[14+subt_len:14+subt_len+desc_len].decode('iso8859-9')
89
                        title_id = (packet[14+subt_len+desc_len+9] << 24) | (packet[14+subt_len+desc_len+10] << 16) | (packet[14+subt_len+desc_len+11] << 8) | packet[14+subt_len+desc_len+12]
90

    
91
                        if summary_id not in dict_des :
92
                            dict_des[summary_id] = {}
93

    
94
                        dict_des[summary_id]['title_id'] = title_id
95
                        dict_des[summary_id]['subtitle'] = subt_text
96
                        dict_des[summary_id]['summary'] = desc_text
97
            elif ssi == 0 :
98
                #PID 642 TID 150 Long descriptions
99
                summary_id = (packet[3] << 16) | (packet[4] << 8) | packet[5]
100
                subt_len = packet[16]
101

    
102
                if not (len(packet) < (19+subt_len)):
103
                    subt_text = packet[17:17+subt_len].decode('iso8859-9')
104
                    desc_len = ((packet[17+subt_len] & 0xf) << 8) | packet[17+subt_len+1]
105
                    if not (len(packet) < (30+subt_len+desc_len)) :
106
                        desc_text = packet[19+subt_len:19+subt_len+desc_len].decode('iso8859-9')
107
                        title_id = (packet[18+subt_len+desc_len+9] << 24) | (packet[18+subt_len+desc_len+10] << 16) | (packet[18+subt_len+desc_len+11] << 8) | packet[18+subt_len+desc_len+12]
108

    
109
                        if summary_id not in dict_des :
110
                            dict_des[summary_id] = {}
111

    
112
                        dict_des[summary_id]['title_id'] = title_id
113
                        dict_des[summary_id]['subtitle'] = subt_text
114
                        dict_des[summary_id]['summary'] = desc_text
115

    
116
        packet = sys.stdin.buffer.read(3)
117
    else :
118
        break
119

    
120
#Parse data together
121
for key in dict_des.keys() :
122
    for prog in dict_pr.copy() :
123
        if (dict_des[key]['title_id'] == prog) or (key == dict_pr[prog]['desc_id']) :
124
            dict_output[prog] = dict_pr[prog]
125
            dict_output[prog]['channel'] = dict_chs[dict_pr[prog]['channel']]
126
            dict_output[prog]['subtitle'] = dict_des[key]['subtitle']
127
            dict_output[prog]['summary'] = dict_des[key]['summary']
128
            dict_pr.pop(prog)
129
            dict_output[prog].pop('desc_id')
130

    
131
for prog in dict_pr.copy() :
132
    dict_output[prog] = dict_pr[prog]
133
    dict_output[prog]['channel'] = dict_chs[dict_pr[prog]['channel']]
134
    dict_pr.pop(prog)
135

    
136
print(json.dumps(dict_output, ensure_ascii=False))
(3-3/5)