Skip to content

Commit a9380d3

Browse files
author
Nobutaka Horie
committed
Initial commit
1 parent ec3b5e1 commit a9380d3

File tree

73 files changed

+5414
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+5414
-0
lines changed

__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from qzss_dcr_lib.exception import QzssDcrDecoderException
2+
from qzss_dcr_lib.interface import decode
3+
from qzss_dcr_lib.interface import decode_stream

__main__.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from .qzss_dcr_lib.main import main
2+
3+
4+
if __name__ == '__main__':
5+
main()

build.sh

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
3+
cd `dirname "$0"`
4+
python setup.py bdist_wheel

qzss_dcr_lib/__init__.py

Whitespace-only changes.

qzss_dcr_lib/decoder/__init__.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from .hex_qzss_dcr_decoder import *
2+
from .qzss_dcr_decoder import *
3+
from .qzss_dcr_decoder_base import *
4+
from .qzss_dcr_decoder_jma import *
5+
from .qzss_dcr_decoder_jma_ash_fall import *
6+
from .qzss_dcr_decoder_jma_common import *
7+
from .qzss_dcr_decoder_jma_earthquake_early_warning import *
8+
from .qzss_dcr_decoder_jma_flood import *
9+
from .qzss_dcr_decoder_jma_hypocenter import *
10+
from .qzss_dcr_decoder_jma_marine import *
11+
from .qzss_dcr_decoder_jma_northwest_pacific_tsunami import *
12+
from .qzss_dcr_decoder_jma_seismic_intensity import *
13+
from .qzss_dcr_decoder_jma_tsunami import *
14+
from .qzss_dcr_decoder_jma_typhoon import *
15+
from .qzss_dcr_decoder_jma_volcano import *
16+
from .qzss_dcr_decoder_jma_weather import *
17+
from .qzss_dcr_decoder_other_organization import *
18+
from .spresense_qzss_dcr_decoder import *
19+
from .ublox_qzss_dcr_decoder import *
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from .qzss_dcr_decoder_base import QzssDcrDecoderBase
2+
from .qzss_dcr_decoder import QzssDcrDecoder
3+
from qzss_dcr_lib.exception import QzssDcrDecoderException
4+
from qzss_dcr_lib.report import QzssDcReportBase
5+
6+
7+
class HexQzssDcrDecoder(QzssDcrDecoderBase):
8+
schema = QzssDcReportBase
9+
10+
def decode(self):
11+
if not self.sentence:
12+
raise EOFError('Encountered EOF')
13+
14+
self.sentence = self.sentence.split()[0]
15+
16+
if len(self.sentence) < 63:
17+
raise QzssDcrDecoderException(
18+
'Too Short Sentence',
19+
self.sentence)
20+
if len(self.sentence) > 63:
21+
raise QzssDcrDecoderException(
22+
'Too Long Sentence',
23+
self.sentence)
24+
25+
# converts the message to bytes type
26+
try:
27+
self.message = bytes.fromhex(self.sentence+'0')
28+
except:
29+
raise QzssDcrDecoderException(
30+
'Invalid Message',
31+
self.sentence)
32+
33+
# stacks the next decoder
34+
return QzssDcrDecoder(**self.get_params()).decode()
+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from .qzss_dcr_decoder_base import QzssDcrDecoderBase
2+
from .qzss_dcr_decoder_jma import QzssDcrDecoderJma
3+
from .qzss_dcr_decoder_other_organization import QzssDcrDecoderOtherOrganization
4+
from qzss_dcr_lib.exception import QzssDcrDecoderException
5+
from qzss_dcr_lib.report import QzssDcReportMessagePartial
6+
from qzss_dcr_lib.definition import qzss_dcr_preamble
7+
from qzss_dcr_lib.definition import qzss_dcr_message_type
8+
from qzss_dcr_lib.definition import qzss_dcr_report_classification
9+
from qzss_dcr_lib.definition import qzss_dcr_report_classification_en
10+
11+
12+
class QzssDcrDecoder(QzssDcrDecoderBase):
13+
schema = QzssDcReportMessagePartial
14+
15+
def decode(self):
16+
# checks the preamble
17+
pab = self.extract_field(0, 8)
18+
try:
19+
self.preamble = qzss_dcr_preamble[pab]
20+
except:
21+
raise QzssDcrDecoderException(
22+
f'Invalid Preamble: {pab}',
23+
self.sentence)
24+
25+
# checks the crc
26+
crc = 0
27+
crc_remaining_len = 226
28+
data = bytearray(self.message[:29])
29+
data[-1] &= 0xc0 # clears the last 6 bits
30+
for byte in data:
31+
crc ^= (byte << 16)
32+
for _ in range(8):
33+
crc <<= 1
34+
if crc & 0x1000000:
35+
crc ^= 0x1864cfb # polynomial
36+
crc_remaining_len -= 1
37+
if crc_remaining_len == 0:
38+
break
39+
crc &= 0xffffff
40+
if crc != self.extract_field(226, 24):
41+
raise QzssDcrDecoderException(
42+
'CRC Mismatch',
43+
self.sentence)
44+
45+
# checks the message type
46+
mt = self.extract_field(8, 6) # 6 bits
47+
try:
48+
self.message_type = qzss_dcr_message_type[mt]
49+
except:
50+
raise QzssDcrDecoderException(
51+
f'Undefined Message Type: {mt}',
52+
self.sentence)
53+
54+
if mt == 43:
55+
next_decoder = QzssDcrDecoderJma
56+
elif mt == 44:
57+
next_decoder = QzssDcrDecoderOtherOrganization
58+
else:
59+
raise QzssDcrDecoderException(
60+
f'Unsupported Message Type: {mt}',
61+
self.sentence)
62+
63+
rc = self.extract_field(14, 3)
64+
try:
65+
self.report_classification = qzss_dcr_report_classification[rc]
66+
self.report_classification_en = qzss_dcr_report_classification_en[rc]
67+
except:
68+
raise QzssDcrDecoderException(
69+
f'Undefined Report Classification: {rc}',
70+
self.sentence)
71+
self.report_classification_no = rc
72+
73+
# stacks the next decoder
74+
return next_decoder(**self.get_params()).decode()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from qzss_dcr_lib.exception import QzssDcrDecoderException
2+
3+
4+
class QzssDcrDecoderBase:
5+
schema = None
6+
7+
def __init__(self, sentence, **kwargs):
8+
self.set_params(sentence=sentence,
9+
**kwargs)
10+
11+
def decode(self):
12+
raise NotImplemented()
13+
14+
def extract_field(self, slider, size):
15+
field = bytearray(self.message[slider >> 3:(slider + size >> 3) + 1])
16+
field[0] = field[0] & (2 ** (8 - (slider & 7)) - 1)
17+
return int.from_bytes(field, 'big') >> (8 - (slider + size & 7))
18+
19+
def set_params(self, **kwargs):
20+
self.__dict__.update(self.schema(**kwargs).get_params())
21+
22+
def get_params(self):
23+
return self.__dict__
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
from .qzss_dcr_decoder_base import QzssDcrDecoderBase
2+
from .qzss_dcr_decoder_jma_earthquake_early_warning import QzssDcrDecoderJmaEarthquakeEarlyWarning
3+
from .qzss_dcr_decoder_jma_seismic_intensity import QzssDcrDecoderJmaSeismicIntensity
4+
from .qzss_dcr_decoder_jma_hypocenter import QzssDcrDecoderJmaHypocenter
5+
from .qzss_dcr_decoder_jma_tsunami import QzssDcrDecoderJmaTsunami
6+
from .qzss_dcr_decoder_jma_northwest_pacific_tsunami import QzssDcrDecoderJmaNorthwestPacificTsunami
7+
from .qzss_dcr_decoder_jma_volcano import QzssDcrDecoderJmaVolcano
8+
from .qzss_dcr_decoder_jma_ash_fall import QzssDcrDecoderJmaAshFall
9+
from .qzss_dcr_decoder_jma_weather import QzssDcrDecoderJmaWeather
10+
from .qzss_dcr_decoder_jma_flood import QzssDcrDecoderJmaFlood
11+
from .qzss_dcr_decoder_jma_typhoon import QzssDcrDecoderJmaTyphoon
12+
from .qzss_dcr_decoder_jma_marine import QzssDcrDecoderJmaMarine
13+
from qzss_dcr_lib.report import QzssDcReportMessageBase
14+
from qzss_dcr_lib.exception import QzssDcrDecoderException
15+
from qzss_dcr_lib.definition import qzss_dcr_jma_disaster_category
16+
from qzss_dcr_lib.definition import qzss_dcr_jma_disaster_category_en
17+
from qzss_dcr_lib.definition import qzss_dcr_jma_information_type
18+
from qzss_dcr_lib.definition import qzss_dcr_jma_information_type_en
19+
from datetime import datetime
20+
21+
22+
class QzssDcrDecoderJma(QzssDcrDecoderBase):
23+
schema = QzssDcReportMessageBase
24+
25+
def decode(self):
26+
self.version = self.extract_field(214, 6)
27+
if self.version != 1:
28+
raise QzssDcrDecoderException(
29+
f'Unsupported JMA-DC Report Version: {self.version}',
30+
self.sentence)
31+
32+
dc = self.extract_field(17, 4)
33+
try:
34+
self.disaster_category = qzss_dcr_jma_disaster_category[dc]
35+
self.disaster_category_en = qzss_dcr_jma_disaster_category_en[dc]
36+
except:
37+
raise QzssDcrDecoderException(
38+
f'Undefined Disaster Category: {dc}',
39+
self.sentence)
40+
self.disaster_category_no = dc
41+
42+
at_mo = self.extract_field(21, 4)
43+
if at_mo < 1 or at_mo > 12:
44+
raise QzssDcrDecoderException(
45+
f'Invalid Report Time: {at_mo} as month',
46+
self.sentence)
47+
at_d = self.extract_field(25, 5)
48+
if at_d < 1 or at_d > 31:
49+
raise QzssDcrDecoderException(
50+
f'Invalid Report Time: {at_d} as day',
51+
self.sentence)
52+
at_h = self.extract_field(30, 5)
53+
if at_h > 23:
54+
raise QzssDcrDecoderException(
55+
f'Invalid Report Time: {at_h} as hour',
56+
self.sentence)
57+
at_mi = self.extract_field(35, 6)
58+
if at_mi > 59:
59+
raise QzssDcrDecoderException(
60+
f'Invalid Report Time: {at_mi} as minute',
61+
self.sentence)
62+
63+
at_y = self.now.year
64+
if at_mo - self.now.month > 6:
65+
at_y -= 1
66+
elif self.now.month - at_mo > 6:
67+
at_y += 1
68+
69+
if at_mo == 2 and at_d == 29:
70+
while at_y % 4 != 0 or (at_y % 100 == 0 and at_y % 400 != 0):
71+
at_y += 1
72+
73+
self.report_time = datetime(year=at_y,
74+
month=at_mo,
75+
day=at_d,
76+
hour=at_h,
77+
minute=at_mi)
78+
79+
it = self.extract_field(41, 2)
80+
try:
81+
self.information_type = qzss_dcr_jma_information_type[it]
82+
self.information_type_en = qzss_dcr_jma_information_type_en[it]
83+
except:
84+
raise QzssDcrDecoderException(
85+
'Undefined Information Type: {it}',
86+
self.sentence)
87+
self.information_type_no = it
88+
89+
if dc == 1:
90+
next_decoder = QzssDcrDecoderJmaEarthquakeEarlyWarning
91+
elif dc == 2:
92+
next_decoder = QzssDcrDecoderJmaHypocenter
93+
elif dc == 3:
94+
next_decoder = QzssDcrDecoderJmaSeismicIntensity
95+
elif dc == 4:
96+
raise QzssDcrDecoderException(
97+
'Decoder Not Implemented: JMA Nankai Trough Earthquake Information',
98+
self.sentence)
99+
elif dc == 5:
100+
next_decoder = QzssDcrDecoderJmaTsunami
101+
elif dc == 6:
102+
next_decoder = QzssDcrDecoderJmaNorthwestPacificTsunami
103+
elif dc == 8:
104+
next_decoder = QzssDcrDecoderJmaVolcano
105+
elif dc == 9:
106+
next_decoder = QzssDcrDecoderJmaAshFall
107+
elif dc == 10:
108+
next_decoder = QzssDcrDecoderJmaWeather
109+
elif dc == 11:
110+
next_decoder = QzssDcrDecoderJmaFlood
111+
elif dc == 12:
112+
next_decoder = QzssDcrDecoderJmaTyphoon
113+
elif dc == 14:
114+
next_decoder = QzssDcrDecoderJmaMarine
115+
else:
116+
raise QzssDcrDecoderException(
117+
f'Unsupported Disaster Category: {self.disaster_category}',
118+
self.sentence)
119+
120+
return next_decoder(**self.get_params()).decode()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from .qzss_dcr_decoder_jma_common import QzssDcrDecoderJmaCommon
2+
from qzss_dcr_lib.exception import QzssDcrDecoderException
3+
from qzss_dcr_lib.report import QzssDcReportJmaBase
4+
from qzss_dcr_lib.report import QzssDcReportJmaAshFall
5+
from qzss_dcr_lib.definition import qzss_dcr_jma_volcano_name
6+
from qzss_dcr_lib.definition import qzss_dcr_jma_ash_fall_warning_code
7+
8+
9+
class QzssDcrDecoderJmaAshFall(QzssDcrDecoderJmaCommon):
10+
schema = QzssDcReportJmaBase
11+
12+
def decode(self):
13+
self.activity_time = self.extract_day_hour_min_field(53)
14+
15+
dw1 = self.extract_field(69, 2)
16+
if dw1 == 1:
17+
self.ash_fall_warning_type = '速報'
18+
elif dw1 == 2:
19+
self.ash_fall_warning_type = '詳細'
20+
else:
21+
raise QzssDcrDecoderException(
22+
f'Undefined JMA Ash Fall Warning Type: {dw1}',
23+
self.sentence)
24+
25+
vo = self.extract_field(71, 12)
26+
try:
27+
self.volcano_name = qzss_dcr_jma_volcano_name[vo]
28+
except:
29+
raise QzssDcrDecoderException(
30+
f'Undefined JMA Volcano Name: {vo}',
31+
self.sentence)
32+
33+
self.expected_ash_fall_times = []
34+
self.ash_fall_warning_codes = []
35+
self.local_governments = []
36+
for i in range(4):
37+
offset = 83 + i * 29
38+
if self.extract_field(offset, 29) == 0:
39+
break
40+
41+
ho = self.extract_field(offset, 3)
42+
if ho < 1 and ho > 6:
43+
raise QzssDcrDecoderException(
44+
f'Invalid JMA Expected Ash Fall Time: {ho}',
45+
self.sentence)
46+
self.expected_ash_fall_times.append(ho)
47+
48+
dw2 = self.extract_field(offset+3, 3)
49+
try:
50+
self.ash_fall_warning_codes.append(qzss_dcr_jma_ash_fall_warning_code[dw2])
51+
except:
52+
raise QzssDcrDecoderException(
53+
f'Undefined JMA Ash Fall Warning Code: {dw2}',
54+
self.sentence)
55+
56+
self.local_governments.append(self.extract_local_government(offset+6))
57+
58+
return QzssDcReportJmaAshFall(**self.get_params())

0 commit comments

Comments
 (0)