decoding of float and double is not working
Opened this issue · 1 comments
helle @lammertb
after some testing we noticed that libfins is seemingly broken for float
and double
In libfins at
Lines 185 to 217 in 91e9aa4
case FINS_DATA_TYPE_INT32 :
case FINS_DATA_TYPE_UINT32 :
case FINS_DATA_TYPE_BCD32 :
case FINS_DATA_TYPE_SBCD32_0 :
case FINS_DATA_TYPE_SBCD32_1 :
case FINS_DATA_TYPE_SBCD32_2 :
case FINS_DATA_TYPE_SBCD32_3 :
case FINS_DATA_TYPE_FLOAT :
if ( XX_finslib_decode_address( item[offset+a].address, & address ) ) return FINS_RETVAL_INVALID_READ_ADDRESS;
area_ptr = XX_finslib_search_area( sys, & address, 16, FI_MRD, false );
if ( area_ptr == NULL ) return FINS_RETVAL_INVALID_READ_AREA;
chunk_start = address.main_address;
chunk_start += area_ptr->low_addr >> 8;
chunk_start -= area_ptr->low_id;
fins_cmnd.body[bodylen++] = area_ptr->area;
fins_cmnd.body[bodylen++] = (chunk_start >> 8) & 0xff;
fins_cmnd.body[bodylen++] = (chunk_start ) & 0xff;
fins_cmnd.body[bodylen++] = 0x00;
chunk_start++;
fins_cmnd.body[bodylen++] = area_ptr->area;
fins_cmnd.body[bodylen++] = (chunk_start >> 8) & 0xff;
fins_cmnd.body[bodylen++] = (chunk_start ) & 0xff;
fins_cmnd.body[bodylen++] = 0x00;
recvlen += 6;
break;
the library treats FINS_DATA_TYPE_INT32, FINS_DATA_TYPE_UINT32, FINS_DATA_TYPE_BCD32, FINS_DATA_TYPE_SBCD32_0, FINS_DATA_TYPE_SBCD32_1, FINS_DATA_TYPE_SBCD32_2, FINS_DATA_TYPE_SBCD32_3, FINS_DATA_TYPE_FLOAT exactly the same when requesting data from the PLC.
However, during decoding:
(this seems correct for e.g. uint32)
case FINS_DATA_TYPE_UINT32 :
item[offset+a].uint32 = fins_cmnd.body[bodylen+3];
item[offset+a].uint32 <<= 8;
item[offset+a].uint32 += fins_cmnd.body[bodylen+4];
item[offset+a].uint32 <<= 8;
item[offset+a].uint32 += fins_cmnd.body[bodylen+0];
item[offset+a].uint32 <<= 8;
item[offset+a].uint32 += fins_cmnd.body[bodylen+1];
bodylen += 5;
break;
but broken here:
Lines 333 to 344 in 91e9aa4
case FINS_DATA_TYPE_FLOAT :
sfloat.val_raw[0] = fins_cmnd.body[0];
sfloat.val_raw[1] = fins_cmnd.body[1];
sfloat.val_raw[2] = fins_cmnd.body[3];
sfloat.val_raw[3] = fins_cmnd.body[4];
item[offset+a].sfloat = sfloat.val_float;
bodylen += 5;
break;
I cannot understand why using seemingly absolute offsets fins_cmnd.body[0]
? this should also take bodylen
into account or perhaps use pointer arithmetic to move fins_cmnd.body
?
am I missing something?
Seems like a bug TBH. The bytes should at least be aligned, not with a gap of one byte in between.