@@ -1075,23 +1075,54 @@ impl Sun2000 {
1075
1075
let mut params: Vec < Parameter > = vec ! [ ] ;
1076
1076
let mut disconnected = false ;
1077
1077
let now = Instant :: now ( ) ;
1078
- for p in parameters. into_iter ( ) . filter ( |s| {
1078
+ let mut params_wanted : Vec < _ > = parameters. into_iter ( ) . filter ( |s| {
1079
1079
( initial_read && s. initial_read )
1080
1080
|| ( !initial_read
1081
1081
&& ( s. save_to_influx
1082
1082
|| s. name . starts_with ( "state_" )
1083
1083
|| s. name . starts_with ( "alarm_" )
1084
1084
|| s. name . ends_with ( "_status" )
1085
1085
|| s. name . ends_with ( "_code" ) ) )
1086
- } ) {
1086
+ } ) . collect ( ) ;
1087
+
1088
+ //sort by register address
1089
+ params_wanted. sort_by ( |a, b| a. reg_address . cmp ( & b. reg_address ) ) ;
1090
+
1091
+ //group to 64-bytes register blocks
1092
+ let mut reg_block = vec ! [ ] ;
1093
+ let mut all_blocks = vec ! [ ] ;
1094
+ let mut start_addr = None ;
1095
+ let mut pe = params_wanted. into_iter ( ) . peekable ( ) ;
1096
+ while pe. peek ( ) . is_some ( ) {
1097
+ let p = pe. next ( ) . unwrap ( ) ;
1098
+ if start_addr. is_none ( ) {
1099
+ start_addr = Some ( p. reg_address ) ;
1100
+ } else {
1101
+ if p. reg_address + p. len - start_addr. unwrap ( ) > 64 {
1102
+ start_addr = Some ( p. reg_address ) ;
1103
+ all_blocks. push ( reg_block) ;
1104
+ reg_block = vec ! [ ] ;
1105
+ }
1106
+ }
1107
+ reg_block. push ( p) ;
1108
+ }
1109
+ //add remainder
1110
+ all_blocks. push ( reg_block) ;
1111
+
1112
+ for ( i, reg_block) in all_blocks. iter ( ) . enumerate ( ) {
1087
1113
if disconnected {
1088
1114
break ;
1089
1115
}
1116
+
1117
+ let last = reg_block. last ( ) . unwrap ( ) ;
1118
+ let start_addr = reg_block[ 0 ] . reg_address ;
1119
+ let len = last. reg_address + last. len - start_addr;
1120
+
1090
1121
let mut attempts = 0 ;
1091
1122
while attempts < SUN2000_ATTEMPTS_PER_PARAM {
1092
1123
attempts = attempts + 1 ;
1093
- debug ! ( "-> obtaining {} ({:?})... " , p . name , p . desc ) ;
1094
- let retval = ctx. read_holding_registers ( p . reg_address , p . len ) ;
1124
+ debug ! ( "-> obtaining register block # {} start={:#x}, len={}, attempt={} " , i , start_addr , len , attempts ) ;
1125
+ let retval = ctx. read_holding_registers ( start_addr , len) ;
1095
1126
let read_res;
1096
1127
let start = Instant :: now ( ) ;
1097
1128
let read_time;
@@ -1102,8 +1133,8 @@ impl Sun2000 {
1102
1133
}
1103
1134
Err ( e) => {
1104
1135
let msg = format ! (
1105
- "<i>{}</i>: read timeout (attempt #{} of {}), register: <green><i>{}</>, error: <b>{}</>" ,
1106
- self . name, attempts, SUN2000_ATTEMPTS_PER_PARAM , p . name , e
1136
+ "<i>{}</i>: read timeout (attempt #{} of {}), register: <green><i>{:#x}+{ }</>, error: <b>{}</>" ,
1137
+ self . name, attempts, SUN2000_ATTEMPTS_PER_PARAM , start_addr , len , e
1107
1138
) ;
1108
1139
if attempts == SUN2000_ATTEMPTS_PER_PARAM {
1109
1140
error ! ( "{}" , msg) ;
@@ -1118,11 +1149,15 @@ impl Sun2000 {
1118
1149
Ok ( data) => {
1119
1150
if read_time > Duration :: from_secs_f32 ( 3.5 ) {
1120
1151
warn ! (
1121
- "<i>{}</i>: inverter has lagged during read, register: <green><i>{}</>, read time: <b>{:?}</>" ,
1122
- self . name, p . name , read_time
1152
+ "<i>{}</i>: inverter has lagged during read, register: <green><i>{:#x}+{ }</>, read time: <b>{:?}</>" ,
1153
+ self . name, start_addr , len , read_time
1123
1154
) ;
1124
1155
}
1125
1156
1157
+ for p in reg_block {
1158
+ let offset = ( p. reg_address - start_addr) as usize ;
1159
+ let data = & data[ offset..offset + ( p. len as usize ) ] ;
1160
+ debug ! ( "-> parsing {} ({:?}) @ {:#x} offset={:#x} len={}..." , p. name, p. desc, p. reg_address, offset, p. len) ;
1126
1161
let mut val;
1127
1162
match & p. value {
1128
1163
ParamKind :: Text ( _) => {
@@ -1181,13 +1216,15 @@ impl Sun2000 {
1181
1216
let _ = Sun2000 :: save_to_influxdb ( c, & self . name , param) . await ;
1182
1217
}
1183
1218
}
1184
-
1185
- break ; //read next parameter
1219
+ }
1220
+ //we parsed all parameters in this block,
1221
+ //break the attempt loop and try next register block
1222
+ break ;
1186
1223
}
1187
1224
Err ( e) => {
1188
1225
let msg = format ! (
1189
- "<i>{}</i>: read error (attempt #{} of {}), register: <green><i>{}</>, error: <b>{}</>, read time: <b>{:?}</>" ,
1190
- self . name, attempts, SUN2000_ATTEMPTS_PER_PARAM , p . name , e, read_time
1226
+ "<i>{}</i>: read error (attempt #{} of {}), register: <green><i>{:#x}+{ }</>, error: <b>{}</>, read time: <b>{:?}</>" ,
1227
+ self . name, attempts, SUN2000_ATTEMPTS_PER_PARAM , start_addr , len , e, read_time
1191
1228
) ;
1192
1229
match e. kind ( ) {
1193
1230
ErrorKind :: BrokenPipe | ErrorKind :: ConnectionReset => {
0 commit comments