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); } } }
// 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); } } }
/*****************************************************************************************************/ static void InitDeviceObjects() { // create the device object with StructuredView acceptation device = new DeviceObject(deviceId, "Device test", "A test Device", true); // ANALOG_INPUT:0 uint // initial value 0 ana0 = new AnalogInput <double> ( 0, "Ana0 Sin double", "Ana0 Sin double", 0, BacnetUnitsId.UNITS_AMPERES ); ana0.m_PROP_HIGH_LIMIT = 50; ana0.m_PROP_LOW_LIMIT = -50; ana0.m_PROP_DEADBAND = 5; ana0.Enable_Reporting(true, 0); device.AddBacnetObject(ana0); // don't forget to do this // Binary Output device.AddBacnetObject(new BinaryOutput(0, "Bin Out", "An output", false)); // Create A StructuredView StructuredView s = new StructuredView(0, "Content", "A View"); // register it device.AddBacnetObject(s); // don't forget to do this BaCSharpObject b; // ANALOG_VALUE:0 double with Priority Array // b = new AnalogValue <double> ( 0, "Ana0 Double", "Ana0 Double", 5465.23, BacnetUnitsId.UNITS_BARS, true ); s.AddBacnetObject(b); // Put it in the view b.OnWriteNotify += new BaCSharpObject.WriteNotificationCallbackHandler(handler_OnWriteNotify); // ANALOG_OUTPUT:1 int with Priority Array on Present Value b = new AnalogOutput <int> ( 1, "Ana1 int", "Ana1 int", (int)56, BacnetUnitsId.UNITS_DEGREES_CELSIUS ); s.AddBacnetObject(b); // Put it in the view b.OnWriteNotify += new BaCSharpObject.WriteNotificationCallbackHandler(handler_OnWriteNotify); // MULTI_STATE_OUTPUT:4 with 6 states MultiStateOutput m = new MultiStateOutput ( 4, "MultiStates", "MultiStates", 1, 6 ); for (int i = 1; i < 7; i++) { m.m_PROP_STATE_TEXT[i - 1] = new BacnetValue("Text Level " + i.ToString()); } s.AddBacnetObject(m); // in the view StructuredView s2 = new StructuredView(1, "Complex objects", "Complex objects"); s.AddBacnetObject(s2); // TREND_LOG:0 with int values // new TrendLog can be changed by new TrendLogCustom trend0 = new TrendLog(0, "Trend signed int", "Trend signed int", 200, BacnetTrendLogValueType.TL_TYPE_SIGN); s2.AddBacnetObject(trend0); // in the second level view // fill Log with more values than the size for (int i = 0; i < 300; i++) { DateTime current = DateTime.Now.AddSeconds(-300 + i); if ((i > 200) && (i < 210)) // simulate some errors in the trend { trend0.AddValue(new BacnetError(), current, 0, BacnetTrendLogValueType.TL_TYPE_ERROR); } else { trend0.AddValue((int)(i * Math.Sin((float)i / 0.01)), current, 0); } } trend0.AddValue(new BacnetError(), DateTime.Now, 0, BacnetTrendLogValueType.TL_TYPE_ERROR); // BACFILE:0 // File access right me be allowed to the current user // for read and for write if any b = new BacnetFile ( 0, "A file", "File description", "c:\\RemoteObject.xml", false ); s2.AddBacnetObject(b); // in the second level view NotificationClass nc = new NotificationClass ( 0, "An alarm sender", "Alarm description", device.PROP_OBJECT_IDENTIFIER ); device.AddBacnetObject(nc); // Put two elements into the NC recipient List // Valid Day BacnetBitString week = new BacnetBitString(); for (int i = 0; i < 7; i++) { week.SetBit((byte)i, true); // Monday to Sunday } // transition BacnetBitString transition = new BacnetBitString(); transition.SetBit(0, true); // To OffNormal transition.SetBit(1, true); // To Fault transition.SetBit(2, true); // To Normal DeviceReportingRecipient r = new DeviceReportingRecipient ( week, // week days DateTime.MinValue.AddDays(10), // fromTime DateTime.MaxValue, // toTime new BacnetObjectId(BacnetObjectTypes.OBJECT_DEVICE, 4000), (uint)4, // processid true, // Ack required transition // transition ); nc.AddReportingRecipient(r); r = new DeviceReportingRecipient ( week, DateTime.MinValue.AddDays(10), DateTime.MaxValue, new BacnetAddress(BacnetAddressTypes.IP, 0, new Byte[6] { 255, 255, 255, 255, 0xBA, 0xC0 }), (uint)4, true, transition ); nc.AddReportingRecipient(r); // Create a Schedule Schedule sch = new Schedule(0, "Schedule", "Schedule"); // MUST be added to the device list before modification device.AddBacnetObject(sch); // a link to the internal analog output sch.AddPropertyReference(new BacnetDeviceObjectPropertyReference ( new BacnetObjectId(BacnetObjectTypes.OBJECT_ANALOG_OUTPUT, 1), BacnetPropertyIds.PROP_PRESENT_VALUE) ); // a link to analog output through the network : could be on another device than itself sch.AddPropertyReference(new BacnetDeviceObjectPropertyReference ( new BacnetObjectId(BacnetObjectTypes.OBJECT_ANALOG_OUTPUT, 1), BacnetPropertyIds.PROP_PRESENT_VALUE, new BacnetObjectId(BacnetObjectTypes.OBJECT_DEVICE, 4000)) ); sch.PROP_SCHEDULE_DEFAULT = (int)452; // Schedule a change today in 60 seconds sch.AddSchedule ( DateTime.Now.DayOfWeek == 0 ? 6 : (int)DateTime.Now.DayOfWeek - 1, // Monday=0, Sunday=6 DateTime.Now.AddSeconds(10), (int)900 ); sch.PROP_OUT_OF_SERVICE = false; // needed after all initialization to start the service // One empty Calendar, could be fullfill with yabe Calendar cal = new Calendar(0, "Test Calendar", "A Yabe calendar"); device.AddBacnetObject(cal); }