コード例 #1
0
/* Read values from modbus-register */
int modbus_read_value(modbus_t *ctx, int address, float *value)
{
    uint16_t val[2];

    /* Check if modbus is set up */
    if(ctx == NULL) {
        log_entry(APP_NAME, "Modbus: Error, No Context");
        printf("Modbus: Error, No Context..\n");
        return -1;
    }

    /* Read data from modbus */
    if(modbus_read_registers(ctx, address, 2, val) <= 0) {
        fprintf(stderr, "Modbus: Reading error: %s\n", modbus_strerror(errno));
        return -1;
    }

    /* Convert value to float */
    *value = modbus_get_float(val);

    if(value == NULL) {
        return ERROR ;
    } else {
        return SUCCESS;
    }
}
コード例 #2
0
ファイル: main.c プロジェクト: insys-icom/M3_Container
int main(void)
{

/* ######################### Variables #########################  */

    /* Variables for modbus */
    modbus_t *ctx;
    int pollingInterval;
    uint16_t valueArray[2];
    float floatValue;
    int no_register;
    uint8_t desiredBit;
    GenDataType_t dataType;
    MoBuRegType_t registerType;

    /* Variables for mosquitto */
    struct mosquitto *mosq;
    char topic[BUFFER_SIZE];
    char text[50];

    /* Variables for time */
    struct timespec last_read_time;
    struct timespec now;


/* ######################### Initialize variables #########################  */

    sprintf(topic, "/test");

    /* Read values from configfile */
    if(getStringFromFile_n(CONFIG_FILE_PATH, "mosquitto_topic", topic, BUFFER_SIZE) == -1) {
        log_entry(APP_NAME, "Error reading topic");
        printf("Error reading topic..\n");
        
        /* wait for new config */
        wait_for_new_config();
        
        return EXIT_FAILURE;
    }

    pollingInterval = getIntFromFile(CONFIG_FILE_PATH, "modbus_polling_Interval");
    no_register = getIntFromFile(CONFIG_FILE_PATH, "modbus_register");
    dataType = getIntFromFile(CONFIG_FILE_PATH, "modbus_data_type");
    registerType = getIntFromFile(CONFIG_FILE_PATH, "modbus_register_type");
    desiredBit = getIntFromFile(CONFIG_FILE_PATH, "modbus_desired_bit");

    /* Check values of variables */
    if(check_values(no_register, pollingInterval) == ERROR) {
        log_entry(APP_NAME, "Error: Invalid values");
        
        /* wait for new config */
        wait_for_new_config();
        
        return EXIT_FAILURE;
    }


/* ######################### Initialize communication #########################  */

    /* Initialize Mosquitto */
    printf(SPLIT_LINE);
    mosq = mosquitto_initialize(CONFIG_FILE_PATH);
    if(mosq == NULL) {
        log_entry(APP_NAME, "Error: Could not initialize mqtt connection");

        /* wait for new config */
        wait_for_new_config();

        return EXIT_FAILURE;
    }

    /* Initialize Modbus */
    printf(SPLIT_LINE);
    ctx = modbus_init(CONFIG_FILE_PATH);
    if(ctx == NULL) {
        log_entry(APP_NAME, "Error: Could not initialize modbus connection");

        /* wait for new config */
        wait_for_new_config();

        return EXIT_FAILURE;
    }

    /* Initialize time */
    clock_gettime(CLOCK_MONOTONIC, &last_read_time);


/* ######################### Start application #########################  */

    printf(SPLIT_LINE);
    log_entry(APP_NAME, "Start reading values..");
    printf("\nStart reading values..\n\n");

    /* Endless Loop */
    while(1)
    {
        clock_gettime(CLOCK_MONOTONIC, &now);

        /* Check if polling time is over (multiply with 1000 to calculate seconds) */
        if(diff(&last_read_time, &now) >= pollingInterval * 1000) {

            /* Read values from modbus */
            if(read_modbus(ctx, 0, no_register, dataType, registerType, desiredBit, valueArray) == ERROR) {
                /* Set last read time */
                clock_gettime(CLOCK_MONOTONIC, &last_read_time);
                continue;
            }

            switch(dataType)
            {
                case bitCoil:
                case sint16:
                case sint32:
                case uint16:
                case uint32:
                    floatValue = modbus_get_float(valueArray);
                    sprintf(text, "%.0f", floatValue);
                    break;
                case float32:
                    floatValue = modbus_get_float(valueArray);
                    sprintf(text, "%.2f", floatValue);
                    break;
            }

            /* Message for user */
            printf("Value: %s\n", text);

            /* Publish value */
            if(mosquitto_pub(mosq, topic, strlen(text), text) == SUCCESS) {
                log_entry(APP_NAME, "Published value successfully");
                printf("Published value successfully.\n\n");
            } else {
                log_entry(APP_NAME, "Error: Value could not be published.");
                printf("Error: Value could not be published.\n");
            }

            /* Set last read time */
            clock_gettime(CLOCK_MONOTONIC, &last_read_time);
        }

        /* taking care of processor and slow down the loop */
        usleep(500);
    }

    /* We should never get here */
    mosquitto_quit(mosq);
    modbus_quit(ctx);

    log_entry(APP_NAME, "Quit application");

    return EXIT_SUCCESS;
}
コード例 #3
0
ファイル: modbus.c プロジェクト: 8bitgeek/libzbxmodbus
/******************************************************************************
 *                                                                            *
 * Function: zbx_modbus_read_registers                                          *
 *                                                                            *
 * Purpose: a main entry point for processing of an item                      *
 *                                                                            *
 * Parameters:  request - structure that contains item key and parameters      *
 *              request->key - item key without parameters                    *
 *              request->nparam - number of parameters                        *
 *              request->timeout - processing should not take longer than     *
 *                                 this number of seconds                     *
 *              request->params[N-1] - pointers to item key parameters        *
 *                                                                            *
 *              result - structure that will contain result                    *
 *                                                                            *
 * Return value: SYSINFO_RET_FAIL - function failed, item will be marked      *
 *                                 as not supported by zabbix                 *
 *               SYSINFO_RET_OK - success                                     *
 *                                                                            *
 * Comment: get_rparam(request, N-1) can be used to get a pointer to the Nth  *
 *          parameter starting from 0 (first parameter). Make sure it exists  *
 *          by checking value of request->nparam.                             *
 *                                                                            *
 ******************************************************************************/
int zbx_modbus_read_registers(AGENT_REQUEST *request, AGENT_RESULT *result)
{
    char    *param1, *param2,*param3,*param4,*param5,*param6,*param7;

    if (request->nparam <4) //check if mandatory params are provided
    {
		SET_MSG_RESULT(result, strdup("Invalid number of parameters."));
		return SYSINFO_RET_FAIL;
	}

    param1 = get_rparam(request, 0);
	if(param_is_empty(param1)) {
		SET_MSG_RESULT(result, strdup("No connection address provided."));
		return SYSINFO_RET_FAIL;
	}
	param2 = get_rparam(request, 1);
    if(param_is_empty(param2)) {
		SET_MSG_RESULT(result, strdup("No slave id provided."));
		return SYSINFO_RET_FAIL;
	}
    param3 = get_rparam(request, 2);
	if(param_is_empty(param3)) {
		SET_MSG_RESULT(result, strdup("No register to read provided."));
		return SYSINFO_RET_FAIL;
	}
	param4 = get_rparam(request, 3);
    if(param_is_empty(param4)) {
		SET_MSG_RESULT(result, strdup("No Modbus function provided! Please provide either 1,2,3,4."));
		return SYSINFO_RET_FAIL;
	}

    
    modbus_t *ctx;
    int lock_required;
        
  
    
    
    create_modbus_context(param1,&ctx,&lock_required);
    if (ctx == NULL) {
            SET_MSG_RESULT(result, strdup("Unable to create the libmodbus context"));
            modbus_free(ctx);
            return SYSINFO_RET_FAIL;
    }
    
    //<slave_id> set slave id 
    char *endptr;
    errno = 0;
    int slave_id = strtol(param2,&endptr, 0);
    if (errno!=0 || *endptr != '\0') {
        SET_MSG_RESULT(result, strdup("Check slaveid parameter"));
        modbus_free(ctx);
        return SYSINFO_RET_FAIL;
    }
    modbus_set_slave(ctx, slave_id);

    //<reg> set register to start from
    errno = 0;
    int reg_start = strtol(param3,&endptr, 0);
    if (errno!=0 || *endptr != '\0') {
        SET_MSG_RESULT(result, strdup("Check register to read"));
        modbus_free(ctx);
        return SYSINFO_RET_FAIL;
    }

    //set function to use
    errno = 0;
    int function = strtol(param4,&endptr, 0);
    if (errno!=0 || *endptr != '\0') {
        SET_MSG_RESULT(result, strdup("Check function (1,2,3,4) used"));
        modbus_free(ctx);
        return SYSINFO_RET_FAIL;
    }
    
    char datatype;	
    int end = MODBUS_16BIT_LE; //<endianness> endianness LE(0) BE(1) default LE
	if (request->nparam > 4) { //optional params provided
   
        param5 = get_rparam(request, 4); //datatype
        if(!validate_datatype_param(param5)) {
            SET_MSG_RESULT(result, strdup("Check datatype provided."));
            modbus_free(ctx);
            return SYSINFO_RET_FAIL;
        }
        
        datatype = *param5; // set datatype
		param6 = get_rparam(request, 5); //16 endiannes
        if(param6) {
            //endianness to use
            errno = 0;
            end = strtol(param6,&endptr, 0);
            if ( (end != MODBUS_16BIT_LE && end != MODBUS_16BIT_BE) ||
                        (errno!=0 || *endptr != '\0') )  {
                SET_MSG_RESULT(result, strdup("Check endiannes used"));
                modbus_free(ctx);
                return SYSINFO_RET_FAIL;
            }
        }
        
        param7 = get_rparam(request, 6); //PDU
        if(param7) {//PDU <first reg> check
            //int first_reg=atoi(param7); 

            errno = 0;
            int first_reg = strtol(param7,&endptr, 0);
            if ( (first_reg != MODBUS_PROTOCOL_ADDRESS_1 && first_reg != MODBUS_PDU_ADDRESS_0) ||
                        (errno!=0 || *endptr != '\0') )  {
                SET_MSG_RESULT(result, strdup("Check addressing scheme(PDU,PROTOCOL) used"));
                modbus_free(ctx);
                return SYSINFO_RET_FAIL;
            }
        
            if (first_reg == MODBUS_PROTOCOL_ADDRESS_1){
                    reg_start=reg_start-1;
            }
        }

	}
    else {//no datatype set, place defaults
    
        if (function==MODBUS_READ_COIL_1 || function == MODBUS_READ_DINPUTS_2) {
            datatype = MODBUS_BIT;//default
        }
        if (function==MODBUS_READ_H_REGISTERS_3 || function == MODBUS_READ_I_REGISTERS_4) {
            datatype = MODBUS_INTEGER ;//default
        }
    }

    /* 3.0.3
    struct timeval response_timeout ;
    response_timeout.tv_sec = 0;
    response_timeout.tv_usec = 0;

    modbus_set_response_timeout(ctx, &response_timeout);
    */    
    //modbus_set_response_timeout(ctx, 10, 0);

    //read part
    
    uint16_t tab_reg[64];//temp vars
    uint8_t tab_reg_bits[64];
    int regs_to_read = 1;
	if (datatype == MODBUS_FLOAT || datatype == MODBUS_LONG) { regs_to_read=2;}

    if (lock_required == 1 ) LOCK_SERIAL_PORT;

    if (modbus_connect(ctx) == -1) {
        SET_MSG_RESULT(result, strdup(modbus_strerror(errno)));
        modbus_free(ctx);
        if (lock_required == 1 ) UNLOCK_SERIAL_PORT;
        return SYSINFO_RET_FAIL;
    }
    
    int rc;//modbus return_code
    switch (function) {
        case MODBUS_READ_COIL_1:
            rc = modbus_read_bits(ctx, reg_start, regs_to_read, tab_reg_bits);  
        break;
        case MODBUS_READ_DINPUTS_2:
            rc = modbus_read_input_bits(ctx, reg_start, regs_to_read, tab_reg_bits);
        break;
        case MODBUS_READ_H_REGISTERS_3:
            rc = modbus_read_registers(ctx, reg_start, regs_to_read, tab_reg);
        break;
        case MODBUS_READ_I_REGISTERS_4:
            rc = modbus_read_input_registers(ctx, reg_start, regs_to_read, tab_reg);
        break;
        default :
            SET_MSG_RESULT(result, strdup("Check function (1,2,3,4) used"));
            //close connection
            modbus_close(ctx);
            if (lock_required == 1 ) UNLOCK_SERIAL_PORT;
            modbus_free(ctx);
            return SYSINFO_RET_FAIL;
        break;
    }
    //close connection
    modbus_close(ctx);
    if (lock_required == 1 ) UNLOCK_SERIAL_PORT;
    modbus_free(ctx);

    if (rc == -1) {
        SET_MSG_RESULT(result, strdup(modbus_strerror(errno)));
        return SYSINFO_RET_FAIL;
    }
    
    //post-parsing
    uint16_t temp_arr[2];     //output based on datatype
    switch(datatype){
    
    case MODBUS_BIT:
        SET_UI64_RESULT(result, tab_reg_bits[0]);
    break;
    
    case MODBUS_INTEGER:
        SET_UI64_RESULT(result, tab_reg[0]);
    break;

    case MODBUS_FLOAT:
        if (end == MODBUS_16BIT_LE) {
            temp_arr[0] = tab_reg[0];
            temp_arr[1] = tab_reg[1];
        }
        if (end == MODBUS_16BIT_BE) {
            temp_arr[0] = tab_reg[1];
            temp_arr[1] = tab_reg[0];
        }
        SET_DBL_RESULT(result, modbus_get_float(temp_arr));
    break;

    case MODBUS_LONG:
        //MODBUS_GET_INT32_FROM_INT16 is doing BIG_ENDIAN for register pair, so inverse registers (sort of hack)
        if (end == MODBUS_16BIT_LE) {
            temp_arr[0] = tab_reg[1];
            temp_arr[1] = tab_reg[0];
        }
        if (end == MODBUS_16BIT_BE) {
            temp_arr[0] = tab_reg[0];
            temp_arr[1] = tab_reg[1];
        }
        SET_UI64_RESULT(result, MODBUS_GET_INT32_FROM_INT16(temp_arr, 0));
    break;
    
    default :
        SET_MSG_RESULT(result, strdup("Check datatype provided."));
        modbus_free(ctx);
        return SYSINFO_RET_FAIL;
    break;
    }

    return SYSINFO_RET_OK;
}