@@ -25,7 +25,7 @@ for further processing by an Application layer (outside this program).
25
25
// Convert two BCD encoded nibbles to an integer
26
26
static unsigned bcd2int (uint8_t bcd )
27
27
{
28
- return 10 * (bcd >> 4 ) + (bcd & 0xF );
28
+ return 10 * (bcd >> 4 ) + (bcd & 0xf );
29
29
}
30
30
31
31
// Mapping from 6 bits to 4 bits. "3of6" coding used for Mode T
@@ -155,6 +155,8 @@ typedef struct {
155
155
uint8_t l_npci ;
156
156
uint8_t tpci ;
157
157
uint8_t apci ;
158
+ /* Q-walk_by */
159
+ int q_mode ;
158
160
} m_bus_block2_t ;
159
161
160
162
// Data structure for block 1
@@ -666,6 +668,58 @@ static int m_bus_decode_records(data_t **inout_data, const uint8_t *b, uint8_t d
666
668
667
669
static void parse_payload (data_t * data , const m_bus_block1_t * block1 , const m_bus_data_t * out )
668
670
{
671
+ // check for vendor specific non-standard payload
672
+
673
+ /* Q-walk_by */
674
+ /* 000: CI:0x78 Vendor spec (not used for OMS) */
675
+ /* 000: 0x780dff5f Magic for QUNDIS walk_by */
676
+ /* 004: 0x35 L:53 Length of walk_by field? */
677
+ /* 005: 0x00 ST:0 Status 0= No Error */
678
+ /* 006: 0x82 unknown */
679
+ /* 007: AC AccessNumber, inc by 1 each message */
680
+ /* 008: 0x0000 CW:0 no encryption */
681
+ /* 015: 0xffff V:total_follows */
682
+ /* 017: 0x67452301 V:total - BCD LSB first -> 01234567 */
683
+ /* 021: 0xff2c V:lastyear 31.12 follows */
684
+ /* 023: 0x00000000 V:lastyear - BCD LSB first */
685
+ /* 027: e.g. 0x1e36 V:lastmonth 30.6 follows */
686
+ /* 029: 0x00000000 V:lastmonth - BCD LSB first */
687
+ /* timestamps follow */
688
+ /* 068: 046d dif (32 Bit Integer/Binary Instantaneous value) vif (Date and time type) */
689
+ /* 070: 02090F37 ("meter_datetime":"2024-07-15 09:02") */
690
+ if (block1 -> block2 .q_mode ) {
691
+ uint8_t const * b = out -> data + BLOCK1A_SIZE - 2 ; // start of block2
692
+
693
+ int q_total = bcd2int (b [20 ]) * 1000000 + bcd2int (b [19 ]) * 10000 + bcd2int (b [18 ]) * 100 + bcd2int (b [17 ]);
694
+ int q_lastyear = bcd2int (b [26 ]) * 1000000 + bcd2int (b [25 ]) * 10000 + bcd2int (b [24 ]) * 100 + bcd2int (b [23 ]);
695
+ int q_lastmonth = bcd2int (b [32 ]) * 1000000 + bcd2int (b [31 ]) * 10000 + bcd2int (b [30 ]) * 100 + bcd2int (b [29 ]);
696
+
697
+ if (block1 -> A_DevType == 6 ) {
698
+ /* WarmWater */
699
+ // Value factor is 0.001, e.g. 123.456 m3
700
+
701
+ /* clang-format off */
702
+ data = data_dbl (data , "Q_total_m3" , "Q_total_m3" , "%.3f m3" , q_total * 0.001f );
703
+ data = data_dbl (data , "Q_lastyear_m3" , "Q_lastyear_m3" , "%.3f m3" , q_lastyear * 0.001f );
704
+ data = data_dbl (data , "Q_lastmonth_m3" , "Q_lastmonth_m3" , "%.3f m3" , q_lastmonth * 0.001f );
705
+ /* clang-format on */
706
+ }
707
+ if (block1 -> A_DevType == 8 ) {
708
+ /* Heat Cost Allocator */
709
+ // Value factor is K (from an invoice), e.g. 123456*K kWh
710
+
711
+ /* clang-format off */
712
+ data = data_dbl (data , "Q_total" , "Q_total" , NULL , q_total );
713
+ data = data_dbl (data , "Q_lastyear" , "Q_lastyear" , NULL , q_lastyear );
714
+ data = data_dbl (data , "Q_lastmonth" , "Q_lastmonth" , NULL , q_lastmonth );
715
+ /* clang-format on */
716
+ }
717
+
718
+ return ; // do not process the payload any further
719
+ }
720
+
721
+ // standard payload
722
+
669
723
uint8_t off = block1 -> block2 .pl_offset ;
670
724
const uint8_t * b = out -> data ;
671
725
@@ -760,14 +814,25 @@ static int parse_block2(const m_bus_data_t *in, m_bus_block1_t *block1)
760
814
b2 -> CW = b [4 ]<<8 | b [3 ];
761
815
b2 -> pl_offset = BLOCK1A_SIZE - 2 + 5 ;
762
816
}
817
+
818
+ /* Q-walk_by */
819
+ /* 000: CI:0x78 Vendor spec (not used for OMS) */
820
+ /* 000: 0x780dff5f Magic for QUNDIS walk_by */
821
+ uint32_t ci_magic = ((uint32_t )b [0 ] << 24 ) | (b [1 ] << 16 ) | (b [2 ] << 8 ) | (b [3 ]);
822
+ if (ci_magic == 0x780dff5f ) {
823
+ b2 -> AC = b [7 ];
824
+ b2 -> ST = b [5 ];
825
+ b2 -> CW = (b [9 ] << 8 ) | (b [8 ]);
826
+ b2 -> pl_offset = BLOCK1A_SIZE - 2 + 8 ;
827
+ b2 -> q_mode = 1 ;
828
+ }
763
829
// fprintf(stderr, "Instantaneous Value: %02x%02x : %f\n",b[9],b[10],((b[10]<<8)|b[9])*0.01);
764
830
}
765
831
return 0 ;
766
832
}
767
833
768
834
static int m_bus_decode_format_a (r_device * decoder , const m_bus_data_t * in , m_bus_data_t * out , m_bus_block1_t * block1 )
769
835
{
770
-
771
836
// Get Block 1
772
837
block1 -> L = in -> data [0 ];
773
838
block1 -> C = in -> data [1 ];
@@ -883,7 +948,6 @@ static int m_bus_output_data(r_device *decoder, bitbuffer_t *bitbuffer, const m_
883
948
"apci" , "APCI" , DATA_FORMAT , "0x%02X" , DATA_INT , block1 -> block2 .apci ,
884
949
"data_length" ,"Data Length" ,DATA_INT , out -> length ,
885
950
"data" , "Data" , DATA_STRING , str_buf ,
886
- "mic" , "Integrity" , DATA_STRING , "CRC" ,
887
951
NULL );
888
952
/* clang-format on */
889
953
} else {
@@ -900,15 +964,14 @@ static int m_bus_output_data(r_device *decoder, bitbuffer_t *bitbuffer, const m_
900
964
// "L", "Length", DATA_INT, block1->L,
901
965
"data_length" , "Data Length" , DATA_INT , out -> length ,
902
966
"data" , "Data" , DATA_STRING , str_buf ,
903
- "mic" , "Integrity" , DATA_STRING , "CRC" ,
904
967
NULL );
905
968
/* clang-format on */
906
969
}
907
970
if (block1 -> block2 .CI ) {
908
971
/* clang-format off */
909
972
data = data_int (data , "CI" , "Control Info" , "0x%02X" , block1 -> block2 .CI );
910
973
data = data_int (data , "AC" , "Access number" , "0x%02X" , block1 -> block2 .AC );
911
- data = data_int (data , "ST" , "Device Type" , "0x%02X" , block1 -> block2 .ST );
974
+ data = data_int (data , "ST" , "Status" , "0x%02X" , block1 -> block2 .ST );
912
975
data = data_int (data , "CW" , "Configuration Word" , "0x%04X" , block1 -> block2 .CW );
913
976
/* clang-format on */
914
977
}
@@ -920,6 +983,8 @@ static int m_bus_output_data(r_device *decoder, bitbuffer_t *bitbuffer, const m_
920
983
data = data_int (data , "payload_encrypted" , "Payload Encrypted" , NULL , 1 );
921
984
/* clang-format on */
922
985
}
986
+
987
+ data = data_str (data , "mic" , "Integrity" , NULL , "CRC" );
923
988
decoder_output_data (decoder , data );
924
989
return 1 ;
925
990
}
0 commit comments