I ran into another similar issue when trying to read the device clock for a Schneider Masterpact breaker (Micrologic 6.0 P controller). It uses 3 16 bit registers to hold the date/Time where each byte of the three registers holds a different datetime component (Year, Month, Day, Hour, Minute, Second)
From documentation [Link]:
3-register date/time format:
register 1: month (byte 1) = 1–12; day (byte 2) = 1–31;
register 2: year (byte 1) = 0–199 (add to 1900 to determine the actual year); hour (byte 2) = 0–23;
register 3: minutes (byte 1) = 0–59; seconds (byte 2) = 0–59
Note: Bits 14 and 15 of the month/day register must be masked.
I ended up reading the three registers as integers (DT_REG1, DT_REG2, DT_REG3) then using the following convoluted expression in an datetime expression tag. It works, I just have the feeling that there must be a better way.
I commented out most of the bits that I knew were not relevant (e.g. 12 being the max for the month, etc.) .
// 23-register date/time format:
// register 1: month (byte 1) = 1–12; day (byte 2) = 1–31;
// register 2: year (byte 1) = 0–199 (add to 1900 to determine the actual year); hour (byte 2) = 0–23;
// register 3: minutes (byte 1) = 0–59; seconds (byte 2) = 0–59
// Note: Bits 14 and 15 of the month/day register must be masked.
setTime(
getDate(
binenc( // Device DateTime Register 2 Byte 1, Year (add to 1900)
{[.]DT_REG2[8]}
,{[.]DT_REG2[9]}
,{[.]DT_REG2[10]}
,{[.]DT_REG2[11]}
,{[.]DT_REG2[12]}
,{[.]DT_REG2[13]}
,{[.]DT_REG2[14]}
,{[.]DT_REG2[15]}
)+1900,
binenc( // Device DateTime Register 1 Byte 1, Month (max 12)
{[.]DT_REG1[8]}
,{[.]DT_REG1[9]}
,{[.]DT_REG1[10]}
,{[.]DT_REG1[11]}
// ,{[.]DT_REG1[12]}
// ,{[.]DT_REG1[13]}
// ,{[.]DT_REG1[14]}
// ,{[.]DT_REG1[15]}
)-1, // Adjust to January as Month 0 for getDate()
binenc( // Device DateTime Register 1 Byte 2, Day (max 31)
{[.]DT_REG1[0]}
,{[.]DT_REG1[1]}
,{[.]DT_REG1[2]}
,{[.]DT_REG1[3]}
,{[.]DT_REG1[4]}
// ,{[.]DT_REG1[5]}
// ,{[.]DT_REG1[6]}
// ,{[.]DT_REG1[7]}
)
),
binenc( // Device DateTime Register 2 Byte 2, Hour (max 24)
{[.]DT_REG2[0]}
,{[.]DT_REG2[1]}
,{[.]DT_REG2[2]}
,{[.]DT_REG2[3]}
,{[.]DT_REG2[4]}
// ,{[.]DT_REG2[5]}
// ,{[.]DT_REG2[6]}
// ,{[.]DT_REG2[7]}
),
binenc( // Device DateTime Register 3 Byte 1, Minute (max 59)
{[.]DT_REG3[8]}
,{[.]DT_REG3[9]}
,{[.]DT_REG3[10]}
,{[.]DT_REG3[11]}
,{[.]DT_REG3[12]}
,{[.]DT_REG3[13]}
// ,{[.]DT_REG3[14]}
// ,{[.]DT_REG3[15]}
),
binenc( // Device DateTime Register 3 Byte 2, Second (max 59)
{[.]DT_REG3[0]}
,{[.]DT_REG3[1]}
,{[.]DT_REG3[2]}
,{[.]DT_REG3[3]}
,{[.]DT_REG3[4]}
,{[.]DT_REG3[5]}
// ,{[.]DT_REG3[6]}
// ,{[.]DT_REG3[7]}
)
)
I did enjoy that the array notation for accessing the bits of an integer worked, even when the source register was not actually a BooleanArray. Much nicer than using getBit().