奇怪的日期/时间协议,需要帮助解决。

huangapple go评论58阅读模式
英文:

Strange date/time protocol, need help solving

问题

I'm trying to reverse engineer the data sent from a very old temperature/humidity device and decode the date/time and other data from serial communication.

This are some of the older registers of the device:

1997 table
奇怪的日期/时间协议,需要帮助解决。

and this are more recent registers, device is out of date:

2022 table
奇怪的日期/时间协议,需要帮助解决。

At the moment I've discovered a very weird format for the hour:
In the last byte of the registers is where the hour stands in the following manner:
For example, in one of the last registers of the 2022 table:
0000 0000 001D B360 0A10 6343
0x43 is the hour 13:00:00
In binary: 01000011
If you take the bits 7 and 6 (01) and insert them to the right of the bit 0: 00001101
Which is 13 in decimal.
This, in my opinion, extremely weird format checks for all hours.
This took me a few days, it's amazing.

What I'm asking to anyone who will take the challenge is if you could help me figuring out the rest of the date format.

I really appreciate if you could help.

I tried epoch from year 2000, both endianness, float format, messing around with bits, and xor-ing some bytes in a drowned attempt to figure it out but to no positive results.

Today I discovered the hour and I got really excited!

EDIT: Here is the excel file with the entire device data base: meter database

英文:

I'm trying to reverse engineer the data sent from a very old temperature/humidity device and decode the date/time and other data from serial communication.

This are some of the older registers of the device:

1997 table
奇怪的日期/时间协议,需要帮助解决。

and this are more recent registers, device is out of date:

2022 table
奇怪的日期/时间协议,需要帮助解决。

At the moment I've discovered a very weird format for the hour:
In the last byte of the registers is where the hour stands in the following manner:
For example, in one of the lasts registers of the 2022 table:
0000 0000 001D B360 0A10 6343
0x43 is the hour 13:00:00
In binary: 01000011
If you take the bits 7 and 6 (01) and insert them to the right of the bit 0: 00001101
Which is 13 in decimal.
This, in my opinion, extremely weird format checks for all hours.
This took me a few days, it's amazing.

What I'm asking to anyone who will take the challenge is if you could help me figuring out the rest of the date format.

I really appreciate if you could help.

I tried epoch from year 2000, both endianness, float format, messing around with bits, and xor-ing some bytes in a drowned attempt to figure it out but to no positive results.

Today I discovered the hour and I got really excited!

EDIT: Here is the excel file with the entire device data base: meter database

答案1

得分: 1

最终,我弄清楚了!
原来关键在于字节序,但要考虑到半字节。

在寄存器0000 0000 001D B360 0A10 6343中:
如果我们按照以下的位置来看待它:abcd efgh ijkl mnop qrst uvwx
那么这是:
温度:mlk,以开尔文 * 10 表示
压力:qpon,以百分之一巴表示
日期:vutsr,以十进制表示(日期10/12/2022用221210十进制或3601A十六进制表示)
小时:wx,这部分的位数排列有点奇怪:0123456723456701表示小时。

以下是我编写的代码,将寄存器的值解析为每个数值:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

uint8_t registro[12] = {0x18, 0x00, 0x75, 0x10, 0x00, 0x91, 0xB8, 0x01, 0x06, 0x3E, 0x53, 0x41};
/*
寄存器数据:
修正后消耗:     12.9
未修正消耗:     34.3
温度:           10.9
压力:           2.64
日期:           2022年7月26日
时间:           05:00:00
*/

int main()
{
    printf("寄存器信息\n");

    //时间
    uint8_t hora_parte_1 = registro[11] & 0xC0;
    uint8_t hora_parte_2 = registro[11] & 0x3F;
    hora_parte_1 = hora_parte_1 >> 6;
    hora_parte_2 = hora_parte_2 << 2;
    uint8_t hora = hora_parte_1 + hora_parte_2;
    printf("寄存器时间:%d\n", hora);

    //日期
    uint32_t fecha_parte_1 = registro[8] & 0x0F;
    uint32_t fecha_parte_2 = registro[9] & 0xF0;
    uint32_t fecha_parte_3 = registro[9] & 0x0F;
    uint32_t fecha_parte_4 = registro[10] & 0xF0;
    uint32_t fecha_parte_5 = registro[10] & 0x0F;
    fecha_parte_3 = fecha_parte_3 << 8;
    fecha_parte_4 = fecha_parte_4 << 8;
    fecha_parte_5 = fecha_parte_5 << 16;
    uint32_t fecha = fecha_parte_1 + fecha_parte_2 + fecha_parte_3 + fecha_parte_4 + fecha_parte_5;
    printf("日期(十进制):%d\n", fecha);
    uint8_t day = fecha % 100;
    fecha /= 100;
    uint8_t month = fecha % 100;
    fecha /= 100;
    uint8_t year = fecha;
    printf("寄存器日期:%02d-%02d-%02d\n", day, month, year);

    //压力
    uint8_t presion_parte_1 = registro[6] & 0x0F;
    uint8_t presion_parte_2 = registro[7] & 0xF0;
    uint16_t presion_parte_3 = registro[7] & 0x0F;
    presion_parte_3 = presion_parte_3 << 8;
    float presion = (presion_parte_1 + presion_parte_2 + presion_parte_3);
    presion /= 100;
    printf("寄存器压力:%.2f\n", presion);

    //温度
    uint8_t temperatura_parte_1 = registro[5] & 0x0F;
    uint8_t temperatura_parte_2 = registro[5] & 0xF0;
    uint16_t temperatura_parte_3 = registro[6] & 0xF0;
    temperatura_parte_1 = temperatura_parte_1 << 4;
    temperatura_parte_2 = temperatura_parte_2 >> 4;
    temperatura_parte_3 = temperatura_parte_3 << 4;
    float temperatura = (temperatura_parte_1 + temperatura_parte_2 + temperatura_parte_3);
    temperatura /= 10;
    temperatura -= 273.2;
    printf("寄存器温度:%.1f\n", temperatura);

    //未修正消耗
    uint8_t no_corregido_parte_1 = registro[0] & 0x0F;
    uint8_t no_corregido_parte_2 = registro[0] & 0xF0;
    uint16_t no_corregido_parte_3 = registro[1] & 0x0F;
    uint16_t no_corregido_parte_4 = registro[1] & 0xF0;
    no_corregido_parte_1 = no_corregido_parte_1 << 4;
    no_corregido_parte_2 = no_corregido_parte_2 >> 4;
    no_corregido_parte_3 = no_corregido_parte_3 << 12;
    no_corregido_parte_4 = no_corregido_parte_4 << 4;
    float no_corregido = (no_corregido_parte_1 + no_corregido_parte_2 + no_corregido_parte_3 + no_corregido_parte_4);
    no_corregido /= 10;
    printf("未修正消耗:%.2f\n", no_corregido);

    //修正消耗
    uint8_t corregido_parte_1 = registro[2] & 0x0F;
    uint8_t corregido_parte_2 = registro[2] & 0xF0;
    uint16_t corregido_parte_3 = registro[3] & 0x0F;
    uint16_t corregido_parte_4 = registro[3] & 0xF0;
    corregido_parte_1 = corregido_parte_1 << 4;
    corregido_parte_2 = corregido_parte_2 >> 4;
    corregido_parte_3 = corregido_parte_3 << 12;
    corregido_parte_4 = correg

<details>
<summary>英文:</summary>

So finally I figured it out!!&lt;br&gt;
Turns out that the key was in the endianness, but taking nibbles in account.&lt;br&gt;
In register `0000 0000 001D B360 0A10 6343`&lt;br&gt; 
If we think of it in positions like this : `abcd efgh ijkl mnop qrst uvwx`&lt;br&gt;
So this is:&lt;br&gt;
Temperature : `mlk` , in Kelvin * 10&lt;br&gt;
Pressure : `qpon`, in Bar * 100&lt;br&gt;
Date : `vutsr`, in decimal (date 10/12/2022 is 221210 decimal or `3601A` hexadecimal)&lt;br&gt;
Hour : `wx` , this has a weird arrange of bits: `01234567` to `23456701` this is the hour.&lt;br&gt;
&lt;br&gt;
This is the code I made to decifer the register into each value:

    #include &lt;stdio.h&gt;
    #include &lt;stdlib.h&gt;
    #include &lt;stdint.h&gt;
    
    uint8_t registro[12] = {0x18, 0x00, 0x75, 0x10, 0x00, 0x91, 0xB8, 0x01, 0x06, 0x3E, 0x53, 0x41};
    /*
    Datos del registro:
    Consumo Corregido :     12.9
    Consumo sin Corregir :  34.3
    Temperatura :           10.9
    Presion :               2.64
    Fecha :                 26/07/2022
    Hora :                  05:00:00
    */
    
    int main()
    {
        printf(&quot;Registro flashero\r\n&quot;);

        //HORA
        uint8_t hora_parte_1 = registro[11] &amp; 0xC0;
        uint8_t hora_parte_2 = registro[11] &amp; 0x3F;
        hora_parte_1 = hora_parte_1 &gt;&gt; 6;
        hora_parte_2 = hora_parte_2 &lt;&lt; 2;
        uint8_t hora = hora_parte_1 + hora_parte_2;
        printf(&quot;Hora de Registro : %d\r\n&quot;, hora);

        //FECHA
        uint32_t fecha_parte_1 = registro[8] &amp; 0x0F;
        uint32_t fecha_parte_2 = registro[9] &amp; 0xF0;
        uint32_t fecha_parte_3 = registro[9] &amp; 0x0F;
        uint32_t fecha_parte_4 = registro[10] &amp; 0xF0;
        uint32_t fecha_parte_5 = registro[10] &amp; 0x0F;
        fecha_parte_3 = fecha_parte_3 &lt;&lt; 8;
        fecha_parte_4 = fecha_parte_4 &lt;&lt; 8;
        fecha_parte_5 = fecha_parte_5 &lt;&lt; 16;
        uint32_t fecha = fecha_parte_1 + fecha_parte_2 + fecha_parte_3 + fecha_parte_4 + fecha_parte_5;
        printf(&quot;Fecha en decimal : %d\r\n&quot;, fecha);
        uint8_t dia = fecha % 100;
        fecha /= 100;
        uint8_t mes = fecha % 100;
        fecha /= 100;
        uint8_t anio = fecha;
        printf(&quot;Fecha de Registro : %02d-%02d-%02d\r\n&quot;, dia, mes, anio);

        //PRESION
        uint8_t presion_parte_1 = registro[6] &amp; 0x0F;
        uint8_t presion_parte_2 = registro[7] &amp; 0xF0;
        uint16_t presion_parte_3 = registro[7] &amp; 0x0F;
        presion_parte_3 = presion_parte_3 &lt;&lt; 8;
        float presion = (presion_parte_1 + presion_parte_2 + presion_parte_3);
        presion /= 100;
        printf(&quot;Presion de Registro : %.2f\r\n&quot;, presion);

        //TEMPERATURA
        uint8_t temperatura_parte_1 = registro[5] &amp;0x0F;
        uint8_t temperatura_parte_2 = registro[5] &amp;0xF0;
        uint16_t temperatura_parte_3 = registro[6] &amp;0xF0;
        temperatura_parte_1 = temperatura_parte_1 &lt;&lt; 4;
        temperatura_parte_2 = temperatura_parte_2 &gt;&gt; 4;
        temperatura_parte_3 = temperatura_parte_3 &lt;&lt; 4;
        float temperatura = (temperatura_parte_1 + temperatura_parte_2 + temperatura_parte_3);
        temperatura /= 10;
        temperatura -= 273.2;
        printf(&quot;Temperatura de Registro : %.1f\r\n&quot;, temperatura);

        //CONSUMO SIN CORREGIR
        uint8_t no_corregido_parte_1 = registro[0] &amp;0x0F;
        uint8_t no_corregido_parte_2 = registro[0] &amp;0xF0;
        uint16_t no_corregido_parte_3 = registro[1] &amp;0x0F;
        uint16_t no_corregido_parte_4 = registro[1] &amp;0xF0;
        no_corregido_parte_1 = no_corregido_parte_1 &lt;&lt; 4;
        no_corregido_parte_2 = no_corregido_parte_2 &gt;&gt; 4;
        no_corregido_parte_3 = no_corregido_parte_3 &lt;&lt; 12;
        no_corregido_parte_4 = no_corregido_parte_4 &lt;&lt; 4;
        float no_corregido = (no_corregido_parte_1 + no_corregido_parte_2 + no_corregido_parte_3 + no_corregido_parte_4);
        no_corregido /= 10;
        printf(&quot;Consumo no corregido : %.2f\r\n&quot;, no_corregido);

        //CONSUMO CORREGIDO
        uint8_t corregido_parte_1 = registro[2] &amp;0x0F;
        uint8_t corregido_parte_2 = registro[2] &amp;0xF0;
        uint16_t corregido_parte_3 = registro[3] &amp;0x0F;
        uint16_t corregido_parte_4 = registro[3] &amp;0xF0;
        corregido_parte_1 = corregido_parte_1 &lt;&lt; 4;
        corregido_parte_2 = corregido_parte_2 &gt;&gt; 4;
        corregido_parte_3 = corregido_parte_3 &lt;&lt; 12;
        corregido_parte_4 = corregido_parte_4 &lt;&lt; 4;
        float corregido = (corregido_parte_1 + corregido_parte_2 + corregido_parte_3 + corregido_parte_4);
        corregido /= 10;
        printf(&quot;Consumo corregido : %.2f\r\n&quot;, corregido);

        return 0;
    }

Result: 

    Registro flashero
    Hora de Registro : 5
    Fecha en decimal : 220726
    Fecha de Registro : 26-07-22
    Presion de Registro : 2.64
    Temperatura de Registro : 10.9
    Consumo no corregido : 12.90
    Consumo corregido : 34.30
    
    Process returned 0 (0x0)   execution time : 0.037 s
    Press any key to continue.

Sorry, I code in spanish.&lt;br&gt;
Thank you for you help everyone!&lt;br&gt;


</details>



huangapple
  • 本文由 发表于 2023年3月4日 04:20:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75631553.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定