Home AMX User Forum NetLinx Studio

Writing a Structure to Flash

Greetings,

I have never been able to sucessfully write a structure to flash and then be able to read it back into the same structure format.

Let's say:
STRUCTURE _sData
{
INTEGER nData[10]
CHAR cData[10][10]
}
.....
DEFINE_VARIABLE
VOLATILE _sData sData[50]
Any examples would be appreciated.

Thanks.

Comments

  • viningvining Posts: 4,368
    If you go to the ModPedia section there's a ViewStat scheduling module that reads/writes a structure to flash. At least I'm pretty sure it does.
  • Below are two functions I wrote (or maybe stole from someone :)). The comments pretty much tell the story about what's happening. Also, I had issues with XML_to_variable so I had to switch to string_to_variable. Supposedly the xml_to_variable bug was fixed, but to this day I just don't use it. The XML_to_variable is still in my code but commented out.
    DEFINE_FUNCTION fnWritetoFile(_sRoomInfo _StructureToSave[], CHAR cFileName[25])
    {
      STACK_VAR LONG 	lPosition
      STACK_VAR SLONG	slReturn
      STACK_VAR SLONG	slFileHandle
      STACK_VAR SLONG	slResult
      STACK_VAR CHAR	sXMLString[50000]
    
      //Step 1, Convert the item to be saved to a single string
    
      slReturn = VARIABLE_TO_STRING(_StructureToSave, sXMLString,1)
      //slReturn = VARIABLE_TO_XML(_StructureToSave, sXMLString,1,0)
      IF(slReturn == 0)
    		SEND_STRING 0, "__FILE__,':: <Line ',ITOA(__LINE__),'>  VARIABLE_TO_XML successful'"
    
      //Test for errors during the VARIABLE_TO_XML process
      IF(slReturn == 3)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  XML Decode data type mismatch'"
      IF(slReturn == 2)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  XML Decode data too small, more members in structure'"
      IF(slReturn == 1)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Structure too small, more members in XML decode string'"
      IF(slReturn == -1)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Decode variable type mismatch'"
      IF(slReturn == -2)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Decode data too small, decoder ran out of data. Most likely poorly formed XML'"
      IF(slReturn == -3)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Output character buffer was too small'"
    
      IF(slReturn<>0)	//Break if error
    	 RETURN;
    
      //Step 2, Open the file on disk
      slFileHandle		=	FILE_OPEN('_RoomInfo.xml',FILE_RW_NEW) // R/W New is a pre-defined constant:  The file is opened with read/write status.  If the file exists, its contents are erased.
    
      //Test for errors during the FILE_OPEN process
      IF(slFileHandle == -2)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Invalid file path or name'"
      IF(slFileHandle == -5)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Disk I/O error'"
      IF(slFileHandle == -3)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Invalid value supplied for I/O Flag:  Must be 1,2, or 3'"
    
      //Step 3, if the FILE_OPEN was successful, then WRITE the file to disk
      IF(slFileHandle > 0)
      {
    	 SEND_STRING 0, "__FILE__,':: <Line ',ITOA(__LINE__),'>  FILE_OPEN Successful'"
    	 slResult = FILE_WRITE(slFileHandle,sXMLString,LENGTH_STRING(sXMLString))
    	 FILE_CLOSE(slFileHandle)
      }
    
      //Test for errors during the FILE_WRITE process
      IF(slResult > 0)
    	 SEND_STRING 0, "__FILE__,':: <Line ',ITOA(__LINE__),'>  FILE_WRITE successful. ',ITOA(slResult),' bytes written'"
      IF(slResult == -1)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  slFileHandle not a valid value'"
      IF(slResult == -11)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Disk full'"
      IF(slResult == -5)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Disk I/O error'"
      IF(slResult == -6)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Invalid buffer length, must be greater than 0'"
    
    }
    
    DEFINE_FUNCTION fnReadfromFile(CHAR cFileName[])
    {
      STACK_VAR LONG 	lPosition
      STACK_VAR SLONG	slReturn
      STACK_VAR SLONG	slFileHandle
      STACK_VAR SLONG	slResult
      CHAR				sXMLString[10000]
    
      //Step 1, Open the file on disk
      slFileHandle		=	FILE_OPEN('_RoomInfo.xml',FILE_READ_ONLY) // FILE_READ_ONLY is a pre-defined constant:  The file is opened with read only status.
    
      //Test for errors in the FILE_OPEN process
      IF(slFileHandle == -2)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Invalid file path or name'"
      IF(slFileHandle == -5)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Disk I/O error'"
      IF(slFileHandle == -3)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Invalid value supplied for I/O Flag:  Must be 1,2, or 3'"
    
    
      //STEP 2, Read the file back into Memory
      IF(slFileHandle > 0)
      {
    	 slResult = FILE_READ(slFileHandle,sXMLString,MAX_LENGTH_STRING(sXMLString))
    	 FILE_CLOSE(slFileHandle)
      }
    
      //Test for errors during the FILE_READ process
      IF(slResult == -1)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  slFileHandle not a valid value'"
      IF(slResult == -9)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  End of file reached'"
      IF(slResult == -5)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Disk I/O error'"
      IF(slResult == -6)
    	 SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Invalid parameter'"
    
      //Step 3, Decode the XML back to a variable
      slReturn = STRING_TO_VARIABLE(_RoomInfo,sXMLString,1)
      //slReturn = XML_TO_VARIABLE(_RoomInfo,sXMLString,1,0)
    
      //Test for errors in the conversion process
      IF(slReturn == 3)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  XML Decode data type mismatch'"
      IF(slReturn == 2)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  XML Decode data too small, more members in structure'"
      IF(slReturn == 1)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Structure too small, more members in XML decode string'"
      IF(slReturn == -1)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Decode variable type mismatch'"
      IF(slReturn == -2)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Decode data too small, decoder ran out of data. Most likely poorly formed XML'"
      IF(slReturn == -3)
    		SEND_STRING 0, "__FILE__,':: ERROR at line <',ITOA(__LINE__),'>  Output character buffer was too small'"
    }
    
    
    

    --John
  • viningvining Posts: 4,368
    Anoter thing to keep in mind is that there's been reported issues using XML_TO_STRING/STRING_TO_XML with structures (if I recall correctly). I thnk SpireJeff has had numerous post about this problem so you may consider using VAR_TO_STRING/STRING_TO_VAR instead. Of course if you want to be able to manual read and edit your XML, well then you need the XML otherwise the VAR thing works the same but you just can't read it or manually edit it. If your only trying create persistance in your module then VAR is probably the way to go. Now I've never seen this issue using XML but then again I've never really look for it either.
  • DHawthorneDHawthorne Posts: 4,584
    What if you broke out the elements of the structures and saved them as individual intrinsic types? It would be a great pain with a complex structure, but my bet is that is where the problem is.
  • AMXJeffAMXJeff Posts: 450
    I use VARIABLE_TO_STRING/STRING_TO_VARIABLE all the time with very complicated structures with in structures with in structures with in structures... The only thing I make sure is that the interger arrays have length... other then this I have no problems.

    SET_LENGTH_ARRAY(somestruct.someintegerarray,MAX_LENGTH_ARRAY(somestruct.someintegerarray));
  • Supposedly, the XML_to_variable bug was fixed as of master firmware update 3.41.422. Here's one of the posts where the bug was discussed: "XML_to_variable has a bug!".

    I still just use String_to_variable because it has always worked fine for me.

    --John
  • TurnipTruckTurnipTruck Posts: 1,485
    Thanks guys! Great information!
  • viningvining Posts: 4,368
    AMXJeff wrote: »
    I use VARIABLE_TO_STRING/STRING_TO_VARIABLE all the time with very complicated structures with in structures with in structures with in structures... The only thing I make sure is that the interger arrays have length... other then this I have no problems.

    SET_LENGTH_ARRAY(somestruct.someintegerarray,MAX_LENGTH_ARRAY(somestruct.someintegerarray));
    You would think the functions would use the "MAX_LENGTH" when converting, otherwsie if any changes occur to arrays with in the structure that change the working "LENGTH" of that structure array you affectively have different structures from what was previosly coverted to XML/VAR which would surely cause issues upon reload if these function weren't using "MAX_LENGTHS" to dertmine the conversion in the first place wouldn't it?
Sign In or Register to comment.