/*****************************************************************************************************/ static void handler_OnReadPropertyMultipleRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, IList <BacnetReadAccessSpecification> properties, BacnetMaxSegments max_segments) { lock (m_storage) { try { IList <BacnetPropertyValue> value; List <BacnetReadAccessResult> values = new List <BacnetReadAccessResult>(); foreach (BacnetReadAccessSpecification p in properties) { if (p.propertyReferences.Count == 1 && p.propertyReferences[0].propertyIdentifier == (uint)BacnetPropertyIds.PROP_ALL) { if (!m_storage.ReadPropertyAll(p.objectIdentifier, out value)) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROP_MULTIPLE, invoke_id, BacnetErrorClasses.ERROR_CLASS_OBJECT, BacnetErrorCodes.ERROR_CODE_UNKNOWN_OBJECT); return; } } else { m_storage.ReadPropertyMultiple(p.objectIdentifier, p.propertyReferences, out value); } values.Add(new BacnetReadAccessResult(p.objectIdentifier, value)); } sender.ReadPropertyMultipleResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), values); } catch (Exception) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROP_MULTIPLE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } }
private void handler_OnReadPropertyRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, BacnetObjectId object_id, BacnetPropertyReference property, BacnetMaxSegments max_segments) { lock (m_storage) { _logger.LogInformation($"Read property request for {property.ToString()} of {object_id.ToString()} from {adr.ToString()}."); try { IList <BacnetValue> value; DeviceStorage.ErrorCodes code = m_storage.ReadProperty(object_id, (BacnetPropertyIds)property.propertyIdentifier, property.propertyArrayIndex, out value); if (code == DeviceStorage.ErrorCodes.Good) { sender.ReadPropertyResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), object_id, property, value); } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } catch (Exception) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } }
/*****************************************************************************************************/ static void handler_OnReadPropertyRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, BacnetObjectId object_id, BacnetPropertyReference property, BacnetMaxSegments max_segments) { lock (device) { BaCSharpObject bacobj = device.FindBacnetObject(object_id); if (bacobj != null) { IList <BacnetValue> value; ErrorCodes error = bacobj.ReadPropertyValue(sender, adr, property, out value); if (error == ErrorCodes.Good) { sender.ReadPropertyResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), object_id, property, value); } else if (error == ErrorCodes.IndexNotExist) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_PROPERTY, BacnetErrorCodes.ERROR_CODE_INVALID_ARRAY_INDEX); } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_UNKNOWN_PROPERTY); } } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_OBJECT, BacnetErrorCodes.ERROR_CODE_UNKNOWN_OBJECT); } } }
/*****************************************************************************************************/ // Create & Delete Object by C. Gunter // OBJECT_ANALOG_INPUT sample void handler_OnCreateObjectRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, BacnetObjectId object_id, ICollection <BacnetPropertyValue> values, BacnetMaxSegments max_segments) { // simple not all errortypes!!!!!!!! and for now only Analog inputs if (device.FindBacnetObject(object_id) != null) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_CREATE_OBJECT, invoke_id, BacnetErrorClasses.ERROR_CLASS_OBJECT, BacnetErrorCodes.ERROR_CODE_OBJECT_IDENTIFIER_ALREADY_EXISTS); return; } // some default values string obj_name = object_id.type.ToString() + object_id.instance.ToString(); string obj_description = "Sample for you by C. Günter"; BacnetUnitsId obj_unit = BacnetUnitsId.UNITS_NO_UNITS; double obj_value = 0; // normally only needs objid, these properties values are sent or not by the client foreach (BacnetPropertyValue value in values) { switch (value.property.propertyIdentifier) { case (uint)BacnetPropertyIds.PROP_DESCRIPTION: obj_description = (string)value.value[0].Value; break; case (uint)BacnetPropertyIds.PROP_OBJECT_NAME: obj_name = (string)value.value[0].Value; break; case (uint)BacnetPropertyIds.PROP_UNITS: obj_unit = (BacnetUnitsId)value.value[0].Value; break; case (uint)BacnetPropertyIds.PROP_PRESENT_VALUE: try { obj_value = Convert.ToDouble(value.value[0].Value); // double is the simplest, quite all values convertible to it } catch { } break; } } //add to device switch (object_id.type) { case BacnetObjectTypes.OBJECT_ANALOG_INPUT: AnalogInput <double> newAI = new AnalogInput <double>(object_id, obj_name, obj_description, obj_value, obj_unit); device.AddBacnetObject(newAI); break; /* to be added by yourself according to your project requirement */ default: sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_CREATE_OBJECT, invoke_id, BacnetErrorClasses.ERROR_CLASS_OBJECT, BacnetErrorCodes.ERROR_CODE_UNSUPPORTED_OBJECT_TYPE); return; } //send ack that has been created sender.CreateObjectResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), object_id); }
private static void handler_OnAtomicReadFileRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, bool is_stream, BacnetObjectId object_id, int position, uint count, BacnetMaxSegments max_segments) { lock (device) { BaCSharpObject File = device.FindBacnetObject(object_id); if (File is BacnetFile) { try { BacnetFile f = (BacnetFile)File; int filesize = (int)f.PROP_FILE_SIZE; bool end_of_file = (position + count) >= filesize; count = (uint)Math.Min(count, filesize - position); int max_filebuffer_size = sender.GetFileBufferMaxSize(); if (count > max_filebuffer_size && max_segments > 0) { //create segmented message!!! } else { count = (uint)Math.Min(count, max_filebuffer_size); //trim } byte[] file_buffer = f.ReadFileBlock(position, (int)count); sender.ReadFileResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), position, count, end_of_file, file_buffer); } catch (Exception) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_READ_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } }
/*****************************************************************************************************/ static void handler_OnReadRange(BacnetClient sender, BacnetAddress adr, byte invoke_id, BacnetObjectId objectId, BacnetPropertyReference property, System.IO.BACnet.Serialize.BacnetReadRangeRequestTypes requestType, uint position, DateTime time, int count, BacnetMaxSegments max_segments) { lock (device) { BaCSharpObject trend = device.FindBacnetObject(objectId); if (trend is TrendLog) { BacnetResultFlags status; byte[] application_data = (trend as TrendLog).GetEncodedTrends(position, count, out status); if (application_data != null) { //send sender.ReadRangeResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), objectId, property, status, (uint)count, application_data, requestType, position); } } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_RANGE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } }
private static void OnReadPropertyRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, BacnetObjectId object_id, BacnetPropertyReference property, BacnetMaxSegments max_segments) { lock (m_lockObject) { try { IList <BacnetValue> value; DeviceStorage.ErrorCodes code = Storage.ReadProperty(object_id, (BacnetPropertyIds)property.propertyIdentifier, property.propertyArrayIndex, out value); if (code == DeviceStorage.ErrorCodes.Good) { sender.ReadPropertyResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), object_id, property, value); } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } catch (Exception) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } }
// Here something could be done to avoid a to big fill to be written on the disk private static void handler_OnAtomicWriteFileRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, bool is_stream, BacnetObjectId object_id, int position, uint block_count, byte[][] blocks, int[] counts, BacnetMaxSegments max_segments) { lock (device) { BaCSharpObject File = device.FindBacnetObject(object_id); if (File is BacnetFile) { try { BacnetFile f = (BacnetFile)File; if (f.PROP_READ_ONLY == false) { int currentposition = position; for (int i = 0; i < block_count; i++) { f.WriteFileBlock(blocks[i], currentposition, counts[i]); currentposition += counts[i]; } sender.WriteFileResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), position); } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_WRITE_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_WRITE_ACCESS_DENIED); } } catch (Exception) { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_WRITE_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_ATOMIC_WRITE_FILE, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } }
public void OnReadPropertyRequest(BacnetClient sender, BacnetAddress adr, byte invoke_id, BacnetObjectId object_id, BacnetPropertyReference property, BacnetMaxSegments max_segments) { lock (BACnetGlobalNetwork.m_storage) { try { IList <BacnetValue> value; DeviceStorage.ErrorCodes code = BACnetGlobalNetwork.m_storage.ReadProperty(object_id, (BacnetPropertyIds)property.propertyIdentifier, property.propertyArrayIndex, out value); if (code == DeviceStorage.ErrorCodes.Good) { sender.ReadPropertyResponse(adr, invoke_id, sender.GetSegmentBuffer(max_segments), object_id, property, value); } else { sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } catch (Exception ex) { Instance.hspi.Log("BACnetDevice Exception in OnReadPropertyRequest " + ex.Message, 2); sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_READ_PROPERTY, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER); } } }
private static void HandleSegmentationResponse(BacnetClient sender, BacnetAddress adr, byte invoke_id, BacnetMaxSegments max_segments, Action <BacnetClient.Segmentation> transmit) { BacnetClient.Segmentation segmentation = sender.GetSegmentBuffer(max_segments); //send first transmit(segmentation); if (segmentation == null || segmentation.buffer.result == System.IO.BACnet.Serialize.EncodeResult.Good) { return; } //start new thread to handle the segment sequence System.Threading.ThreadPool.QueueUserWorkItem((o) => { byte old_max_info_frames = sender.Transport.MaxInfoFrames; sender.Transport.MaxInfoFrames = segmentation.window_size; //increase max_info_frames, to increase throughput. This might be against 'standard' while (true) { bool more_follows = (segmentation.buffer.result & System.IO.BACnet.Serialize.EncodeResult.NotEnoughBuffer) > 0; //wait for segmentACK if ((segmentation.sequence_number - 1) % segmentation.window_size == 0 || !more_follows) { if (!sender.WaitForAllTransmits(sender.TransmitTimeout)) { Trace.TraceWarning("Transmit timeout"); break; } byte current_number = segmentation.sequence_number; if (!sender.WaitForSegmentAck(adr, invoke_id, segmentation, sender.Timeout)) { Trace.TraceWarning("Didn't get segmentACK"); break; } if (segmentation.sequence_number != current_number) { Trace.WriteLine("Oh, a retransmit", null); more_follows = true; } } else { //a negative segmentACK perhaps byte current_number = segmentation.sequence_number; sender.WaitForSegmentAck(adr, invoke_id, segmentation, 0); //don't wait if (segmentation.sequence_number != current_number) { Trace.WriteLine("Oh, a retransmit", null); more_follows = true; } } if (more_follows) { lock (m_lockObject) transmit(segmentation); } else { break; } } sender.Transport.MaxInfoFrames = old_max_info_frames; }); }