Skip to content

Commit 4f6f69c

Browse files
committed
upgrade for firmware >= 4.08, incompatible with older firmwares
1 parent 1f650cf commit 4f6f69c

File tree

6 files changed

+72
-71
lines changed

6 files changed

+72
-71
lines changed

radiacode-examples/narodmon.py

+26-31
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,38 @@
44

55
import aiohttp
66

7-
from radiacode import CountRate, DoseRate, RadiaCode
7+
from radiacode import RealTimeData, RadiaCode
88

99

1010
def sensors_data(rc_conn):
1111
databuf = rc_conn.data_buf()
1212

13-
last_countrate, last_doserate = None, None
13+
last = None
1414
for v in databuf:
15-
if isinstance(v, CountRate):
16-
if last_countrate is None or last_countrate.dt < v.dt:
17-
last_countrate = v
18-
elif isinstance(v, DoseRate):
19-
if last_doserate is None or last_doserate.dt < v.dt:
20-
last_doserate = v
21-
22-
ret = []
23-
if last_countrate is not None:
24-
ret.append(
25-
{
26-
'id': 'S1',
27-
'name': 'CountRate',
28-
'value': last_countrate.count_rate,
29-
'unit': 'CPS',
30-
'time': int(last_countrate.dt.timestamp()),
31-
}
32-
)
33-
if last_doserate is not None:
34-
ret.append(
35-
{
36-
'id': 'S2',
37-
'name': 'R_DoseRate',
38-
'value': 1000000 * last_doserate.dose_rate,
39-
'unit': 'μR/h',
40-
'time': int(last_doserate.dt.timestamp()),
41-
}
42-
)
43-
return ret
15+
if isinstance(v, RealTimeData):
16+
if last is None or last.dt < v.dt:
17+
last = v
18+
19+
if last is None:
20+
return []
21+
22+
ts = int(last.dt.timestamp())
23+
return [
24+
{
25+
'id': 'S1',
26+
'name': 'CountRate',
27+
'value': last.count_rate,
28+
'unit': 'CPS',
29+
'time': ts,
30+
},
31+
{
32+
'id': 'S2',
33+
'name': 'R_DoseRate',
34+
'value': 1000000 * last.dose_rate,
35+
'unit': 'μR/h',
36+
'time': ts,
37+
},
38+
]
4439

4540

4641
async def send_data(d):

radiacode-examples/radiacode-exporter.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import prometheus_client
55

6-
from radiacode import CountRate, DoseRate, RadiaCode
6+
from radiacode import RealTimeData, RadiaCode
77

88

99
def main():
@@ -33,10 +33,9 @@ def main():
3333

3434
while True:
3535
for v in rc.data_buf():
36-
if isinstance(v, CountRate):
36+
if isinstance(v, RealTimeData):
3737
metric_count_rate.set(v.count_rate)
3838
metric_count_rate_error.set(v.count_rate_err)
39-
elif isinstance(v, DoseRate):
4039
metric_dose_rate.set(10000 * v.dose_rate) # convert to μSv/h
4140
metric_dose_rate_error.set(v.dose_rate_err)
4241

radiacode-examples/webserver.py

+9-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from aiohttp import web
77

8-
from radiacode import CountRate, DoseRate, RadiaCode
8+
from radiacode import RadiaCode, RealTimeData
99

1010

1111
async def handle_index(request):
@@ -47,29 +47,25 @@ async def handle_spectrum_reset(request):
4747

4848
async def process(app):
4949
max_history_size = 128
50-
countrate_history, doserate_history = [], []
50+
history = []
5151
while True:
5252
databuf = app.rc_conn.data_buf()
5353
for v in databuf:
54-
if isinstance(v, CountRate):
55-
countrate_history.append(v)
56-
elif isinstance(v, DoseRate):
57-
doserate_history.append(v)
58-
59-
countrate_history.sort(key=lambda x: x.dt)
60-
countrate_history = countrate_history[-max_history_size:]
61-
doserate_history.sort(key=lambda x: x.dt)
62-
doserate_history = doserate_history[-max_history_size:]
54+
if isinstance(v, RealTimeData):
55+
history.append(v)
56+
57+
history.sort(key=lambda x: x.dt)
58+
history = history[-max_history_size:]
6359
jdata = json.dumps(
6460
{
6561
'series': [
6662
{
6763
'name': 'countrate',
68-
'data': [(int(1000 * x.dt.timestamp()), x.count_rate) for x in countrate_history],
64+
'data': [(int(1000 * x.dt.timestamp()), x.count_rate) for x in history],
6965
},
7066
{
7167
'name': 'doserate',
72-
'data': [(int(1000 * x.dt.timestamp()), 10000 * x.dose_rate) for x in doserate_history],
68+
'data': [(int(1000 * x.dt.timestamp()), 10000 * x.dose_rate) for x in history],
7369
},
7470
],
7571
},

radiacode/decoders/databuf.py

+20-15
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
from typing import List, Union
33

44
from radiacode.bytes_buffer import BytesBuffer
5-
from radiacode.types import CountRate, DoseRate, DoseRateDB, Event, RareData
5+
from radiacode.types import DoseRateDB, Event, RareData, RawData, RealTimeData
66

77

88
def decode_VS_DATA_BUF(
99
br: BytesBuffer,
1010
base_time: datetime.datetime,
11-
) -> List[Union[CountRate, DoseRate, DoseRateDB, RareData, Event]]:
12-
ret: List[Union[CountRate, DoseRate, DoseRateDB, RareData, Event]] = []
11+
) -> List[Union[RealTimeData, DoseRateDB, RareData, RawData, Event]]:
12+
ret: List[Union[RealTimeData, DoseRateDB, RareData, RawData, Event]] = []
1313
next_seq = None
1414
while br.size() > 0:
1515
seq, eid, gid, ts_offset = br.unpack('<BBBi')
@@ -18,24 +18,26 @@ def decode_VS_DATA_BUF(
1818
raise Exception(f'seq jump, expect:{next_seq}, got:{seq}')
1919

2020
next_seq = (seq + 1) % 256
21-
if eid == 0 and gid == 0: # GRP_CountRate
22-
count_rate, count_rate_err, flags = br.unpack('<fHH')
21+
if eid == 0 and gid == 0: # GRP_RealTimeData
22+
count_rate, dose_rate, count_rate_err, dose_rate_err, flags, rt_flags = br.unpack('<ffHHHB')
2323
ret.append(
24-
CountRate(
24+
RealTimeData(
2525
dt=dt,
2626
count_rate=count_rate,
27-
count_rate_err=count_rate_err * 0.1,
27+
count_rate_err=count_rate_err / 10,
28+
dose_rate=dose_rate,
29+
dose_rate_err=dose_rate_err / 10,
2830
flags=flags,
31+
real_time_flags=rt_flags,
2932
)
3033
)
31-
elif eid == 0 and gid == 1: # GRP_DoseRate
32-
dose_rate, dose_rate_err, flags = br.unpack('<fHH')
34+
elif eid == 0 and gid == 1: # GRP_RawData
35+
count_rate, dose_rate = br.unpack('<ff')
3336
ret.append(
34-
DoseRate(
37+
RawData(
3538
dt=dt,
39+
count_rate=count_rate,
3640
dose_rate=dose_rate,
37-
dose_rate_err=dose_rate_err * 0.1,
38-
flags=flags,
3941
)
4042
)
4143
elif eid == 0 and gid == 2: # GRP_DoseRateDB
@@ -46,7 +48,7 @@ def decode_VS_DATA_BUF(
4648
count=count,
4749
count_rate=count_rate,
4850
dose_rate=dose_rate,
49-
dose_rate_err=dose_rate_err * 0.1,
51+
dose_rate_err=dose_rate_err / 10,
5052
flags=flags,
5153
)
5254
)
@@ -57,8 +59,8 @@ def decode_VS_DATA_BUF(
5759
dt=dt,
5860
duration=duration,
5961
dose=dose,
60-
temperature=temperature * 0.01 - 20,
61-
charge_level=charge_level * 0.01,
62+
temperature=(temperature - 2000) / 100,
63+
charge_level=charge_level / 100,
6264
flags=flags,
6365
)
6466
)
@@ -85,6 +87,9 @@ def decode_VS_DATA_BUF(
8587
count_rate, flags = br.unpack('<fH')
8688
elif eid == 0 and gid == 9: # GRP_RawDoseRate
8789
dose_rate, flags = br.unpack('<fH')
90+
elif eid == 1 and gid == 1: # ???
91+
samples_num, smpl_time_ms = br.unpack('<HI')
92+
br.unpack(f'<{8*samples_num}x') # skip
8893
elif eid == 1 and gid == 2:
8994
samples_num, smpl_time_ms = br.unpack('<HI')
9095
br.unpack(f'<{16*samples_num}x') # skip

radiacode/radiacode.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from radiacode.decoders.spectrum import decode_RC_VS_SPECTRUM
88
from radiacode.transports.bluetooth import Bluetooth
99
from radiacode.transports.usb import Usb
10-
from radiacode.types import CTRL, VS, VSFR, CountRate, DisplayDirection, DoseRate, DoseRateDB, Event, RareData, Spectrum
10+
from radiacode.types import CTRL, VS, VSFR, DisplayDirection, DoseRateDB, Event, RareData, RawData, RealTimeData, Spectrum
1111

1212

1313
# channel number -> kEv
@@ -57,8 +57,12 @@ def execute(self, reqtype: bytes, args: Optional[bytes] = None) -> BytesBuffer:
5757
def read_request(self, command_id: Union[int, VS, VSFR]) -> BytesBuffer:
5858
r = self.execute(b'\x26\x08', struct.pack('<I', int(command_id)))
5959
retcode, flen = r.unpack('<II')
60-
assert retcode == 1
61-
assert r.size() == flen
60+
assert retcode == 1, f'{command_id}: got retcode {retcode}'
61+
# HACK: workaround for new firmware bug(?)
62+
if r.size() == flen + 1 and r._data[-1] == 0x00:
63+
r._data = r._data[:-1]
64+
# END OF HACK
65+
assert r.size() == flen, f'{command_id}: got size {r.size()}, expect {flen}'
6266
return r
6367

6468
def write_request(self, command_id: Union[int, VSFR], data: Optional[bytes] = None) -> None:
@@ -128,7 +132,7 @@ def commands(self) -> str:
128132
def device_time(self, v: int) -> None:
129133
self.write_request(VSFR.DEVICE_TIME, struct.pack('<I', v))
130134

131-
def data_buf(self) -> List[Union[CountRate, DoseRate, DoseRateDB, RareData, Event]]:
135+
def data_buf(self) -> List[Union[DoseRateDB, RareData, RealTimeData, RawData, Event]]:
132136
r = self.read_request(VS.DATA_BUF)
133137
return decode_VS_DATA_BUF(r, self._base_time)
134138

radiacode/types.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@
55

66

77
@dataclass
8-
class CountRate:
8+
class RealTimeData:
99
dt: datetime.datetime
1010
count_rate: float
1111
count_rate_err: float # %
12+
dose_rate: int
13+
dose_rate_err: int
1214
flags: int
15+
real_time_flags: int
1316

1417

1518
@dataclass
16-
class DoseRate:
19+
class RawData:
1720
dt: datetime.datetime
18-
dose_rate: int
19-
dose_rate_err: int
20-
flags: int
21+
count_rate: float
22+
dose_rate: float
2123

2224

2325
@dataclass

0 commit comments

Comments
 (0)