static err_code parse_point_definition()

in IndustrialDeviceController/Software/HighLevelApp/drivers/modbus/modbus.c [654:748]


static err_code parse_point_definition(const char *ptr, int16_t len, data_point_t *p)
{
    if (!ptr || len <= 0 || !p) {
        return DEVICE_E_CONFIG;
    }

    char buf[MAX_FIELD_LENGTH + 1];

    modbus_point_t *mp = &(p->d.modbus);
    // set default value
    mp->value_offset = 0;
    mp->scale = 1;
    mp->bit_offset = 0;

    int16_t field_num = 0;

    for (int16_t b = 0, e = 0; b < len; b = e + 1, e = b) {
        while (e < len && ptr[e] != ':') {
            e++;
        }

        if (e - b > MAX_FIELD_LENGTH) {
            return DEVICE_E_CONFIG;
        }

        switch (field_num) {
        case MODBUS_SCHEMA_FIELD_KEY:
            strncpy_s(p->key, e - b + 1, ptr + b, e - b);
            break;

        case MODBUS_SCHEMA_FIELD_NUMBER: {
            strncpy_s(buf, sizeof(buf), ptr + b, e - b);
            errno = 0;
            uint32_t number = strtol(buf, NULL, 10);
            mp->reg_type = number / 100000;
            mp->addr = number % 100000 - 1; // number start from 1, but address is from 0

            if (errno || (mp->reg_type != 0 && mp->reg_type != 1 && mp->reg_type != 3 && mp->reg_type != 4)) {
                return DEVICE_E_CONFIG;
            };
            break;
        }

        case MODBUS_SCHEMA_FIELD_TYPE: {
            strncpy_s(buf, sizeof(buf), ptr + b, e - b);
            errno = 0;
            mp->data_type = strtol(buf, NULL, 10);

            if (errno || mp->data_type == TYPE_INVALID || mp->data_type > TYPE_INT64_LE) {
                return DEVICE_E_CONFIG;
            }
            break;
        }
        case MODBUS_SCHEMA_FIELD_BIT: {
            strncpy_s(buf, sizeof(buf), ptr + b, e - b);
            errno = 0;
            mp->bit_offset = strtol(buf, NULL, 10);

            if (errno || mp->bit_offset > 15) {
                return DEVICE_E_CONFIG;
            }
            break;
        }
        case MODBUS_SCHEMA_FIELD_MULTIPLIER: {
            strncpy_s(buf, sizeof(buf), ptr + b, e - b);
            errno = 0;
            double multiplier = strtod(buf, NULL);
            if (errno || multiplier == 0) {
                return DEVICE_E_CONFIG;
            }
            mp->scale = 1 / multiplier;
            break;
        }

        case MODBUS_SCHEMA_FIELD_OFFSET: {
            strncpy_s(buf, sizeof(buf), ptr + b, e - b);
            errno = 0;
            mp->value_offset = strtol(buf, NULL, 10);
            if (errno) {
                return DEVICE_E_CONFIG;
            }
            break;
        }
        }

        field_num++;
    }

    // minimum is key, number, type
    if (field_num < 3) {
        return DEVICE_E_CONFIG;;
    } else {
        return DEVICE_OK;
    }
}