• Recent
    • Tags
    • Popular
    • Register
    • Login

    Please Note This forum exists for community support for the Mango product family and the Radix IoT Platform. Although Radix IoT employees participate in this forum from time to time, there is no guarantee of a response to anything posted here, nor can Radix IoT, LLC guarantee the accuracy of any information expressed or conveyed. Specific project questions from customers with active support contracts are asked to send requests to support@radixiot.com.

    Radix IoT Website Mango 3 Documentation Website Mango 4 Documentation Website Mango 5 Documentation Website

    A small bug in the atomicwritefilerequest

    BACnet4J general discussion
    2
    8
    4.4k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R
      robert bouwens
      last edited by

      basically it works.
      but the standard says exactly when a bacneterrorexception has to be thrown:

      • negative start
      • start exceeds the filesize

      at the same time a few internal 'things' should be checked. when the device property backupAndRestoreState
      is set to preparingForBackup or preparingForRestore the the atomic read/write requests are dangerous and could deliver
      faulty results. thus throw a device configuration in progress bacnetserviceexception as written in the standard.

      
      	@Override
      	public AcknowledgementService handle(LocalDevice localDevice, Address from, Network network) throws BACnetException
      	{
      		AtomicReadFileAck response;
      
      		BACnetObject obj;
      		FileObject file;
      		try
      		{
      			// Find the file.
      			obj = localDevice.getObjectRequired(fileIdentifier);
      			if (!(obj instanceof FileObject))
      			{
      				System.out.println("File access request on an object that is not a file");
      				throw new BACnetServiceException(ErrorClass.object, ErrorCode.rejectInconsistentParameters);
      			}
      			// check for status (backup/restore)
      			BackupState bsOld = (BackupState) localDevice.getConfiguration().getProperty(
      					PropertyIdentifier.backupAndRestoreState);
      			if (bsOld.intValue() == BackupState.preparingForBackup.intValue()
      					|| bsOld.intValue() == BackupState.preparingForRestore.intValue())
      			{
      				// send error: device configuration in progress as response
      				throw new BACnetServiceException(ErrorClass.device, ErrorCode.configurationInProgress);
      			}
      
      			file = (FileObject) obj;
      
      			// Validation.
      			FileAccessMethod fileAccessMethod = (FileAccessMethod) file.getProperty(PropertyIdentifier.fileAccessMethod);
      			if (recordAccess && fileAccessMethod.equals(FileAccessMethod.streamAccess) || !recordAccess
      					&& fileAccessMethod.equals(FileAccessMethod.recordAccess))
      				throw new BACnetErrorException(getChoiceId(), ErrorClass.object, ErrorCode.invalidFileAccessMethod);
      		}
      		catch (BACnetServiceException e)
      		{
      			throw new BACnetErrorException(getChoiceId(), e);
      		}
      
      		if (recordAccess)
      			throw new NotImplementedException();
      
      		long start = fileStartPosition.longValue();
      		long length = requestedCount.longValue();
      
      		/* 
      		 * throw an exception when the following conditions are met:
      		 * - start is a negative number
      		 * - start exceeds the length of the file object
      		 */
      		if (start > file.length() || start < 0)
      			throw new BACnetErrorException(getChoiceId(), ErrorClass.object, ErrorCode.invalidFileStartPosition);
      
      		try
      		{
      			response = new AtomicReadFileAck(new Boolean(file.length() <= start + length), fileStartPosition, file.readData(
      					start, length));
      		}
      		catch (IOException e)
      		{
      			throw new BACnetErrorException(getChoiceId(), ErrorClass.object, ErrorCode.fileAccessDenied);
      		}
      
      		return response;
      	}
      
      

      that's it - works nicely.
      robert

      1 Reply Last reply Reply Quote 0
      • M
        mlohbihler
        last edited by

        What's "recordAccess"? It isn't defined anywhere.

        Best regards,
        Matthew

        1 Reply Last reply Reply Quote 0
        • R
          robert bouwens
          last edited by

          hi matt,
          sorry for being unclear:

          public class AtomicReadFileRequest extends ConfirmedRequestService
          {
          	private static final long serialVersionUID = -279843621668191530L;
          
          	public static final byte TYPE_ID = 6;
          
          	private final ObjectIdentifier fileIdentifier;
          	private final boolean recordAccess;
          	private final SignedInteger fileStartPosition;
          	private final UnsignedInteger requestedCount;
          
          	public AtomicReadFileRequest(ObjectIdentifier fileIdentifier, boolean recordAccess, SignedInteger fileStartPosition,
          			UnsignedInteger requestedCount)
          	{
          		this.fileIdentifier = fileIdentifier;
          		this.recordAccess = recordAccess;
          		this.fileStartPosition = fileStartPosition;
          		this.requestedCount = requestedCount;
          	}
          
          

          the varaible is the standard member variable defined in the class.

          regards
          robert

          1 Reply Last reply Reply Quote 0
          • M
            mlohbihler
            last edited by

            Ah, that explains it. The title of the post threw me off.

            Best regards,
            Matthew

            1 Reply Last reply Reply Quote 0
            • M
              mlohbihler
              last edited by

              Should the fileStartPosition condition not be:

                      if (start &lt; 0 || start &gt;= file.length())
              
              

              ?

              Or do you intend that if start == file.length() that a 0 result should be returned?

              Best regards,
              Matthew

              1 Reply Last reply Reply Quote 0
              • R
                robert bouwens
                last edited by

                hello matt,

                a zero length file should be readable without error.
                and the standard says explicitly when the file size exceeds.

                if (start < 0 || start > file.length()

                is correct when reading the spec.
                and another commercial stack shows the same behaviour with the upper mod.

                regards
                robert

                1 Reply Last reply Reply Quote 0
                • M
                  mlohbihler
                  last edited by

                  Ok. I recall (but at the moment can't confirm) that there was some problem with this during testing of the original implementation, but i'll go with your version.

                  Best regards,
                  Matthew

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post