Written by James McDonald

November 4, 2015

I am having an issue with a Siemens WinCC control system that writes C struct data to files on disk under windows.

The C function in the control system (see below) reads the Tag values from the user interface into a struct and then writes it to disk with a call to fwrite and is loaded again from disk using fread.

The problem is that if I enter a value of 55504 to 55511 as the product number (prod_number) in the user interface and then run the below function the struct written to disk is corrupt. The weird thing is that values less than or greater than the above values save to disk and reload fine.

Once inputted into the user interface the prod_number is held in a Tag with the format “Floating-point number 32-bit IEEE 754”

Here is an image of the contents of the struct on disk file showing one that works and one that is corrupt (the lower one is the one that is OK – which has the garbled characters) the top one is missing the needed data because of choking on 55504 as inputted to the user interface.

struct_written_to_file

So I am posting this in the event that someone else has this problem. I’m guessing that there is something wrong with the low level C interface to the disk. I’m not sure, but having experienced this I am now not confident that writing a struct straight to disk is the best way to store and load configuration data.

C-struct and code to write it to disk

#include "apdefap.h"

// Define the recipe structure (data elements) - Edit this to fit application needs
typedef struct {
	char name[256], description[256], bar_code[16];	
	double prod_length, prod_width, prod_height, box_length, box_width, box_height, prod_weight, prod_number;
	int prod_layers, box_layers, pallet_pattern, pallet_type, prod_rows, prod_columns;
	int sleeve_req, slip_sheet_req, prod_slipsheet_req, squeeze, stretchwrap, prod_life, boxes_per_layer, box_weight, 

printing_offset;
} RECIPE_DEMO;

void raDemo_FileRecipe_Capture(char *Filename)
{
#ifdef RUN_ON_WEBNAVIGATOR
	raErrorMsg("raDemo_FileRecipe_Capture", "This is not possible from the WebNavigator client.");
#else
	FILE *f;
	char filename[1024];
	RECIPE_DEMO data;

	if (MessageBox(
		NULL, 
		"This will overwrite the recipe file with the current data.  Are you sure?", 
		"Capture Recipe", 
		MB_YESNO | MB_ICONEXCLAMATION | MB_SETFOREGROUND|MB_SYSTEMMODAL) != IDYES)
			return;

	// Build filename
	sprintf(filename, "%sRecipes\\%s", raStrRTPath(), Filename);
	printf ("Recipe: %s\r\n", filename);

	// Open/create for writing
	f = fopen(filename,"w");

	if (f != NULL) {
		// Read recipe data from WinCC tags - Edit this to fit your application needs
		strncpy(data.name, Filename, 255);		// Recipe Name/Description
		strncpy(data.description, GetTagChar("Recipe_Product_Description"), 255);
		data.prod_length = GetTagDouble("Recipe_Product_Length");
		data.prod_number = GetTagDouble("Recipe_Product_Number");
		// debug statement
		printf("Product Number: %lf\r\n", data.prod_number);
        data.prod_width = GetTagDouble("Recipe_Product_Width");
		data.prod_height = GetTagDouble("Recipe_Product_Height");
		data.prod_layers = GetTagByte("Recipe_Product_Layers");
		data.prod_rows = GetTagByte("Recipe_Product_Rows");
		data.prod_columns = GetTagByte("Recipe_Product_Columns");
		data.prod_weight = GetTagDouble("Recipe_Product_Weight");
		data.box_length = GetTagDouble("Recipe_Box_Length");
		data.box_width = GetTagDouble("Recipe_Box_Width");
		data.box_height = GetTagDouble("Recipe_Box_Height");
		data.box_layers = GetTagByte("Recipe_Box_Layers");
		data.pallet_pattern = GetTagByte("Recipe_Pallet_Pattern_Number");
		strncpy(data.bar_code, GetTagChar("Recipe_Bar_Code"),16);
		data.sleeve_req = GetTagBit("Recipe_Sleeve_Req");
		data.slip_sheet_req = GetTagBit("Recipe_Slip_Sheet_Req");
		data.prod_slipsheet_req = GetTagBit("Recipe_Product_Slipsheet_Req");
		data.stretchwrap = GetTagBit("Recipe_Stretchwrap_Req");
		data.squeeze = GetTagByte("Recipe_Additional_Squeeze");
		data.prod_life = GetTagWord("Recipe_Product_Life");
		data.boxes_per_layer = GetTagWord("Recipe_Boxes_Per_Layer");
		data.box_weight = GetTagWord("Recipe_Box_Weight");
		data.printing_offset = GetTagWord("Recipe_Printing_Offset");


		// Write recipe data to the file
		fwrite(&data,sizeof(data),1,f); 
		// Close the file
		fclose(f);
	} else {
		sprintf(filename, "Error writing to file:  '%sRecipes\\%s'\r\nMake sure the destination folder exists.",  
			raStrRTPath(), Filename);
		raErrorMsg("Capture Recipe", filename);
	}

#endif
}

0 Comments

Trackbacks/Pingbacks

  1. C Struct Loses it’s Settings | The Southern IT Observer - […] while ago I blogged about a Control system that commits a C Struct to a file on a disk…

Submit a Comment

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.

You May Also Like…

Clear HSTS Settings in CHrome

Open chrome://net-internals/#hsts enter the domain in the query field and click Query to confirm it has HSTS settings...

Ubuntu on Hyper-v

It boils town to installing linux-azure # as root or sudo apt-get update apt-get install linux-azure...