myTreeNode findTreeNodeDevice(BACnetManager bnm, BACnetPacket pkt) { // Remember, a device is defined by a Network Number and a MAC address. Nothing else! for (int i = 0; i < this.TreeViewOnUI.Nodes.Count; i++) { myTreeNode tnNetwork = (myTreeNode)this.TreeViewOnUI.Nodes[i]; if (tnNetwork.networkNumber == pkt.srcDevice.adr.networkNumber) { // found Network.. now check if node exists for (int j = 0; j < tnNetwork.Nodes.Count; j++) { myTreeNode tnDevice = (myTreeNode)tnNetwork.Nodes[j]; if (tnDevice != null && tnDevice.device != null && tnDevice.device.Equals(pkt.srcDevice)) { // found tnDevice.lastHeardFromTime = _apm._stopWatch.ElapsedMilliseconds; return(tnDevice); } } } } return(null); }
// Returns reference to a network node, creating one if necessary myTreeNode EstablishTreeNodeNet(BACnetManager bnm, BACnetPacket pkt) { // return reference if it is found. for (int i = 0; i < this.TreeViewOnUI.Nodes.Count; i++) { myTreeNode tnNetwork = (myTreeNode)this.TreeViewOnUI.Nodes[i]; if (tnNetwork.networkNumber == pkt.srcDevice.adr.networkNumber) { tnNetwork.lastHeardFromTime = _apm._stopWatch.ElapsedMilliseconds; return(tnNetwork); } } // not found, so create it myTreeNode newNode = new myTreeNode(); if (pkt.srcDevice.adr.directlyConnected == true) { newNode.Text = "Directly Connected Network ( " + pkt.srcDevice.adr.networkNumber + " )"; } else { newNode.Text = "Network " + pkt.srcDevice.adr.networkNumber; } newNode.networkNumber = pkt.srcDevice.adr.networkNumber; newNode.lastHeardFromTime = _apm._stopWatch.ElapsedMilliseconds; this.TreeViewOnUI.Nodes.Add(newNode); return(newNode); }
// Returns reference to device node, creating one if necessary. myTreeNode EstablishTreeNodeDevice(BACnetManager bnm, BACnetPacket pkt) { // does one exist? myTreeNode mtnd = findTreeNodeDevice(bnm, pkt); if (mtnd != null) { return(mtnd); } // no, time to create it // establish the network myTreeNode mtnn = EstablishTreeNodeNet(bnm, pkt); myTreeNode newNode = new myTreeNode(); newNode.Text = "Device " + pkt.srcDevice.deviceObjectID.objectInstance; newNode.device.adr = pkt.srcDevice.adr; newNode.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.LastAccessTime, "Seconds since msg 0"); newNode.lastHeardFromTime = _apm._stopWatch.ElapsedMilliseconds; mtnn.Nodes.Add(newNode); // todo, add a few other parameters. mtnn.Expand(); return(newNode); }
// Returns reference to device node, creating one if necessary. myTreeNode EstablishTreeNodeDevice(BACnetManager bnm, BACnetPacket pkt) { // does one exist? myTreeNode mtnd = findTreeNodeDevice(bnm, pkt); if (mtnd != null) { return(mtnd); } // no, time to create it // establish the network myTreeNode mtnn = EstablishTreeNodeNet(bnm, pkt); myTreeNode newNode = new myTreeNode(); // If this is an I-Am-Router-To-Network message, then there is no deviceObject... if (pkt.messageType == BACnetPacket.MESSAGE_TYPE.NETWORK_LAYER) { if (pkt.npdu.function == BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK || pkt.npdu.function == BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_INIT_RT_TABLE_ACK) { // ignore newNode.Text = "Router"; newNode.device.type = BACnetEnums.DEVICE_TYPE.Router; newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.DeviceInstance, ""); newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.MACaddress, ""); newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.VendorID, ""); } else { _apm.MessageTodo("m0140 - What other NPDU only messages could we receive that would want us to create a device?"); } } else { newNode.Text = "Device " + pkt.srcDevice.deviceObjectID.objectInstance; } newNode.device.adr = pkt.srcDevice.adr; //newNode.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.LastAccessTime, "Seconds since msg 0"); newNode.lastHeardFromTime = _apm._stopWatch.ElapsedMilliseconds; mtnn.Nodes.Add(newNode); // todo, add a few other parameters. newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.BACnetADR, pkt.srcDevice.adr.ToString()); mtnn.Expand(); return(newNode); }
private static void SendOffPacket(AppManager apm, BACnetPacket pkt, byte[] outbuf, int optr) { // store NPDU length. InsertUint16(outbuf, ref pkt.npduLengthOffset, (uint)optr); apm.bnm.bacnet_listen_socket.SendTo(outbuf, optr, SocketFlags.None, pkt.directlyConnectedIPEndPointOfDevice); PacketLog pktlog = new PacketLog(true, pkt); apm.bnm.BACnetMessageLog.Enqueue(pktlog); }
private static void RespondReadPropertyWithUint(AppManager apm, BACnetPacket bacpkt, BACnetPacket outpkt, byte[] outbuf, uint val) { int optr; // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, bacpkt, outpkt, outbuf, bacpkt.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTag(outbuf, ref optr, BACnetEnums.BACNET_APPLICATION_TAG.BACNET_APPLICATION_TAG_UNSIGNED_INT, val); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, bacpkt, outbuf, optr); }
private static void RespondReadPropertyWithString(AppManager apm, BACnetPacket bacpkt, BACnetPacket outpkt, byte[] outbuf, string resp) { int optr; // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, bacpkt, outpkt, outbuf, bacpkt.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTagString(outbuf, ref optr, resp); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outpkt, outbuf, optr); }
public void ServerApplication() { while (true) { // check to see if we have any live Incoming messages.. while (_apm.pktQueueToApplication.Count > 0) { try { // process the incoming queue BACnetPacket bacpkt = _apm.pktQueueToApplication.Dequeue(); if (bacpkt.npdu.isNPDUmessage) { switch (bacpkt.npdu.function) { case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: // find the site, establish the device, make sure that it is marked as a router, save the information _apm.MessageTodo("I am router received"); break; case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_INIT_RT_TABLE_ACK: // find the site, establish the device, make sure that it is marked as a router, save the information _apm.MessageTodo("Init rt table ack received"); break; case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK: _apm.MessageTodo("m0053 - ----- Implementing " + bacpkt.npdu.function.ToString()); break; } } else { // todo - a certain amount of redundancy exists below, resolve. BACnetLibraryCL.RespondToAPDU(_apm, _bnm, bacpkt); } } catch (Exception ex) { _apm.MessagePanic("m0052 - Router application layer fault" + ex.ToString()); } } System.Threading.Thread.Sleep(10); } }
// Build the 'header' part of the BACnet Packet private static int InsertReadPropertyResponse(AppManager apm, BACnetPacket requestBACpkt, BACnetPacket responseCRP, byte[] outbuf, BACnetEnums.BACNET_PROPERTY_ID pID) { int optr; optr = responseCRP.apdu_offset; // build APDU to provide services supported. responseCRP.EncodeNPDU(outbuf, ref optr); BACnetLibraryCL.InsertPDU(outbuf, ref optr, BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_COMPLEX_ACK, requestBACpkt.invokeID, requestBACpkt.confirmedServiceChoice); requestBACpkt.objectID.EncodeContextTag(outbuf, ref optr, 0); BACnetLibraryCL.InsertContextTag(outbuf, ref optr, 1, (int)pID); return(optr); }
public bool detect_echo_packet(BACnetManager bnm, BACnetPacket packet) { foreach (IPAddress ipa in bnm.OurIPAddressList) { if (packet.directlyConnectedIPEndPointOfDevice.Address.Equals(ipa)) { // when the sent IP address matches one of ours, check the contents of the packet against the packets stored in the outbound copy queue // // remove all expired packets // foreach (BACnetPacket pkt in outgoing_buffer_copy_queue) // { // if (pkt.timestamp + 5000 < bnm._stopWatch.ElapsedMilliseconds) // { // // drop it // outgoing_buffer_copy_queue.Remove(pkt); // // and quit from this loop, since foreach may fail... // // todo, find a better way to remove all > 5000 ms items // break; // } // } // if (outgoing_buffer_copy_queue.Count > 100) // { // // time to panic // // todo Console.WriteLine("Outbound copy queue overflow"); // outgoing_buffer_copy_queue.Clear(); // return false; // } // if (outgoing_buffer_copy_queue.Contains(packet)) // { // // Console.WriteLine("This message is from ourselves"); // // inform that the packet was a match // return true; // } //} // todo - drop a warning... return(true); } } return(false); }
public PacketLog(bool sending, BACnetPacket packet) { this.sending = sending; this.BACnetPacket = packet; }
public void UpdateDeviceTreeView(BACnetManager bnm, BACnetPacket pkt) { if (!pkt.apdu_present) { // means that this packet must be a NPDU message. Treat it differently switch (pkt.npdu.function) { case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_INIT_RT_TABLE_ACK: // means we had a response from a router - establish the router in our tree. myTreeNode mtnd = EstablishTreeNodeDevice(bnm, pkt); if (mtnd != null) { // found, or established, the treenode matching the device, // now add the objects to it. // update the type of device - we now know it is a router (even if we did not know before). if (mtnd.device != null) { if (mtnd.device.GetType() == typeof(Device)) { // it is still a simple device type, upgrade it _apm.MessageConfigChange(String.Format("m0139 - Device changing from a {0} to a Router", mtnd.Text)); //if (mtnd.router == null) mtnd.router = new Router(mtnd.device); //mtnd.device = null; mtnd.device = new Router(mtnd.device); mtnd.type = myTreeNode.TREENODE_OBJ_TYPE.Router; mtnd.Text = "Router"; } } ((Router)mtnd.device).AddRoutingTableEntries(pkt.routerTableList); // now go through the Router's routing table and display each entry appropriately foreach (RoutingTableEntry rte in ((Router)mtnd.device).routingTableEntries) { bool found = false; for (int i = 0; i < mtnd.Nodes.Count; i++) { if (mtnd.Nodes[i].GetType() == typeof(myTreeNode)) { myTreeNode mtnObj = (myTreeNode)mtnd.Nodes[i]; if (mtnObj.type == myTreeNode.TREENODE_OBJ_TYPE.RouterTableEntry && mtnObj.rte.networkNumber == rte.networkNumber) { // if we get here, the object already exists in the display list and we must not add it again. // but let us check farSide flag for consistency if (mtnObj.rte.farSide != true) { _apm.MessageTodo("m0143-Farside error"); } mtnObj.rte.farSide = true; found = true; // Redo the text, something (like portID) may have been updated mtnObj.Text = rte.ToString(); break; } } } if (!found) { // not found, so add myTreeNode ntn = mtnd.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.RouterTableEntry, rte.ToString()); ntn.rte = rte; ntn.ToolTipText = "Do not right click on this item, it has no effect"; mtnd.Expand(); } } } mtnd.Expand(); break; //case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_INIT_RT_TABLE_ACK: // myTreeNode mtnrt = EstablishTreeNodeDevice(bnm, pkt); // if (mtnrt != null) // { // // found, or established, the treenode matching the device, // // now add the objects to it. // // update the type of device - we now know it is a router (even if we did not know before). // mtnrt.device.type = BACnetEnums.DEVICE_TYPE.Router; // mtnrt.Text = "Router"; // foreach (RoutingTableEntry rp in pkt.routerPortList) // { // bool found = false; // for (int i = 0; i < mtnrt.Nodes.Count; i++) // { // if (mtnrt.Nodes[i].GetType() == typeof(myTreeNode)) // { // myTreeNode mtnObj = (myTreeNode)mtnrt.Nodes[i]; // if (mtnObj.type == myTreeNode.TREENODE_OBJ_TYPE.RouterPort && mtnObj.rp.networkNumber == rp.networkNumber) // { // // if we get here, the object already exists in the list and we must not add it again. // found = true; // // farside nearside stuff mtnObj.networkNumberFromInitRouterTable = true; // // Let us update it though, may be new information // // mtnObj.Text = rp.ToString() ; // break; // } // } // } // if (!found) // { // //// not found, so add // myTreeNode ntn = mtnrt.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.RouterPort, rp.ToString()); // ntn.rp = rp; // // nearside farside stuff ntn.networkNumberFromInitRouterTable = true; // // ntn.ToolTipText = "Do not right click on this item, it has no effect"; // mtnrt.Expand(); // } // } // } // break; } return; } else { // If we reach here, means APDU is present switch (pkt.pduType) { case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: switch (pkt.unconfirmedServiceChoice) { case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM: pkt.srcDevice.directlyConnectedIPEndPointOfDevice = pkt.directlyConnectedIPEndPointOfDevice; // was fromBIP // todo, not sure where I use this - check // bnm.deviceList.Add(pkt.srcDevice); AddDeviceToTreeNode(bnm, pkt); // bnm.newPacketQueue.myEnqueue(packet); break; case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_WHO_IS: // ignore reflected who-is messages break; default: throw new Exception("m0178-Todo"); } break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_COMPLEX_ACK: switch (pkt.confirmedServiceChoice) { case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY: myTreeNode mtn; switch (pkt.propertyID) { case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_LIST: // what we need to do here is list the objects on the treeview... // first find the device in the tree mtn = findTreeNodeDevice(bnm, pkt); // add the objects to it if (mtn != null) { // found the treenode matching the device, add the objects to it. foreach (BACnetObjectIdentifier bno in pkt.objectList) { // does it exist? if so, ignore if (findTreeNodeObject(mtn, bno) == null) { // not found, so add myTreeNode ntn = new myTreeNode(); ntn.oID = bno; ntn.type = myTreeNode.TREENODE_OBJ_TYPE.BACnetObject; ntn.Text = bno.objectType.ToString() + " Instance: " + bno.objectInstance.ToString(); ntn.ToolTipText = "Right-click to read more data"; mtn.Nodes.Add(ntn); } } } break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_TYPE: // these properties are of academic interest only. We already have this data from the object list. _apm.MessageTodo("m0080 - Perhaps we need to confirm we have the object on our list already and panic if not"); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_NAME: // Leave these for when we implement stuff on the Browser. // find the device, then the object, then append the name. //mtn = findTreeNodeDevice(bnm, pkt); //myTreeNode mtn2 = findTreeNodeObject(mtn, pkt.objectID); //if (mtn2 == null) //{ // _apm.MessageTodo("m0081 - this is a surprise"); //} //else //{ // mtn2.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.GenericText, "Name"); //} break; default: mtn = findTreeNodeDevice(bnm, pkt); if (mtn != null) { // for now, just add the object. // _apm.MessageTodo("m0524"); //myTreeNode ntn = new myTreeNode(); //ntn.type = myTreeNode.TREENODE_OBJ_TYPE.BACnetObject; //ntn.Text = pkt.propertyID.ToString(); //ntn.ToolTipText = "Do not right click on this item, it has no effect"; //mtn.Nodes.Add(ntn); } break; } break; default: throw new Exception("m0179-Todo"); } break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_CONFIRMED_SERVICE_REQUEST: case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_REJECT: case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_ERROR: // These messages do not affect the Device TreeView, so we will ignore them.. break; default: _apm.MessageTodo("m0027 - Device Treeview needs to parse this message still: " + pkt.pduType.ToString()); break; } } }
void AddDeviceToTreeNode(BACnetManager bnm, BACnetPacket pkt) { // find the network display node, or else add a new one myTreeNode tni = EstablishTreeNodeNet(bnm, pkt); // found Network.. // check if node already exists bool founddeviceflag = false; for (int j = 0; j < tni.Nodes.Count; j++) { myTreeNode tnj = (myTreeNode)tni.Nodes[j]; if (tnj != null && tnj.device.Equals(pkt.srcDevice)) { // found, so quit tnj.lastHeardFromTime = _apm._stopWatch.ElapsedMilliseconds; founddeviceflag = true; tnj.device = pkt.srcDevice; // right here we can update some parameters... (eg. update i-am details from a router...) todonow // newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.BACnetADR, pkt.srcDevice.adr.ToString()); tnj.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.DeviceInstance, pkt.srcDevice.deviceObjectID.objectInstance.ToString()); tnj.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.MACaddress, pkt.srcDevice.adr.MACaddress.ToString()); tnj.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.VendorID, pkt.srcDevice.vendorID.ToString()); tnj.Expand(); break; } } // add a device node to the network node if (founddeviceflag == false) { myTreeNode newNode = new myTreeNode(); newNode.device = pkt.srcDevice; newNode.type = myTreeNode.TREENODE_OBJ_TYPE.Device; newNode.Name = "NewNode"; // todonetxt - add back devicetype //NewNode.Text = "Device " + devUpdate.deviceObjectID.objectInstance + " " + devUpdate.deviceType.ToString(); newNode.Text = "Device "; newNode.ToolTipText = "Right Click on Device Objects for further functionality"; newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.DeviceInstance, pkt.srcDevice.deviceObjectID.objectInstance.ToString()); newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.MACaddress, pkt.srcDevice.adr.MACaddress.ToString()); newNode.UpdatemyTreeNodeLeaf(myTreeNode.TREENODE_OBJ_TYPE.VendorID, pkt.srcDevice.vendorID.ToString()); newNode.Tag = pkt.srcDevice.deviceObjectID.objectInstance; // add other paramters to our new node newNode.lastHeardFromTime = _apm._stopWatch.ElapsedMilliseconds; // todo, need to fix this, since we are adding TreeNodes here, not myTreeNodes... // newNode.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.LastAccessTime, "Seconds since msg 0"); // newNode.Nodes.Add("Seconds since msg 0"); if (pkt.srcDevice.adr.directlyConnected != true) { newNode.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.GenericText, "Router IP Addr " + pkt.srcDevice.directlyConnectedIPEndPointOfDevice); } newNode.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.BACnetADR, "BACnet ADR " + pkt.srcDevice.adr.ToString()); newNode.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.GenericText, "Segmentation " + (int)pkt.srcDevice.SegmentationSupported); // migrated away NewNode.isDevice = true; newNode.Expand(); tni.Nodes.Add(newNode); // tni.ExpandAll(); tni.Expand(); } }
public static void RespondToAPDU(AppManager apm, BACnetManager bnm, BACnetPacket incomingPacket) { byte[] outbuf = new byte[2000]; int optr; PacketLog pktlog; BACnetPacket outgoingBACpacket = new BACnetPacket(apm, bnm); // fill in some CRP parameters for packet log display outgoingBACpacket.confirmedServiceChoice = incomingPacket.confirmedServiceChoice; outgoingBACpacket.apduConfirmedServiceTypeFlag = incomingPacket.apduConfirmedServiceTypeFlag; outgoingBACpacket.propertyID = incomingPacket.propertyID; outgoingBACpacket.apduUnconfirmedServiceFlag = incomingPacket.apduUnconfirmedServiceFlag; outgoingBACpacket.pduType = incomingPacket.pduType; outgoingBACpacket.unconfirmedServiceChoice = incomingPacket.unconfirmedServiceChoice; outgoingBACpacket.directlyConnectedIPEndPointOfDevice = incomingPacket.directlyConnectedIPEndPointOfDevice; BACnetPacket incomingBACpacket = (BACnetPacket)incomingPacket; if (incomingBACpacket.apduConfirmedServiceTypeFlag == true) { switch (incomingBACpacket.confirmedServiceChoice) { case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY: switch (incomingBACpacket.propertyID) { case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_NAME: // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTagString(outbuf, ref optr, apm.ourDeviceName); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED: optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); BACnetLibraryCL.InsertContextOpeningTag(outbuf, ref optr, 3); // hardcode the bitstring until we see where else it can be used, then generalized. outbuf[optr++] = 0x83; // Assume length = 3, including unused bits byte // outbuf[optr++] = 0x03; outbuf[optr++] = 0x06; // trailing bits not used InsertBitString(outbuf, optr, 2, (int)BACnetEnums.BACNET_OBJECT_TYPE.OBJECT_DEVICE); optr += 2; BACnetLibraryCL.InsertContextClosingTag(outbuf, ref optr, 3); SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_PROTOCOL_SERVICES_SUPPORTED: optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); BACnetLibraryCL.InsertContextOpeningTag(outbuf, ref optr, 3); //List<BACnetEnums.BACNET_SERVICES_SUPPORTED> servicesList = new List<BACnetEnums.BACNET_SERVICES_SUPPORTED>(); //servicesList.Add(BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_READ_PROPERTY); //// servicesList.Add(BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_WRITE_PROPERTY); //servicesList.Add(BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL); ////servicesList.Add(BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_REINITIALIZE_DEVICE); //servicesList.Add(BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_TIME_SYNCHRONIZATION); //servicesList.Add(BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_WHO_IS); //// todo, what about i-am ? //BACnetLibraryCL.InsertApplicationTagString(outbuf, ref optr, servicesList ); // hardcode the bitstring until we see where else it can be used, then generalized. outbuf[optr++] = 0x85; // Assume length = 6 outbuf[optr++] = 0x06; // Length, including the next byte outbuf[optr++] = 0x05; // 5 trailing bits not used InsertBitString(outbuf, optr, 5, (int)BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_READ_PROPERTY); InsertBitString(outbuf, optr, 5, (int)BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_DEVICE_COMMUNICATION_CONTROL); InsertBitString(outbuf, optr, 5, (int)BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_TIME_SYNCHRONIZATION); InsertBitString(outbuf, optr, 5, (int)BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_WHO_IS); InsertBitString(outbuf, optr, 5, (int)BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_WRITE_PROPERTY); InsertBitString(outbuf, optr, 5, (int)BACnetEnums.BACNET_SERVICES_SUPPORTED.SERVICE_SUPPORTED_REINITIALIZE_DEVICE); optr += 5; BACnetLibraryCL.InsertContextClosingTag(outbuf, ref optr, 3); SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_LIST: // Only respond if array index specified if (!incomingPacket.arrayIndexDecoded) { throw new Exception("m0058 - Not expecting open object list"); } if (incomingPacket.arrayIndex == 0) { optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // arrayIndex 0 InsertContextTag(outbuf, ref optr, 2, 0); // Object count InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTag(outbuf, ref optr, BACnetEnums.BACNET_APPLICATION_TAG.BACNET_APPLICATION_TAG_UNSIGNED_INT, 1); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; // supply the number of objects } else if (incomingPacket.arrayIndex == 1) { // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // arrayIndex 1 InsertContextTag(outbuf, ref optr, 2, 1); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); incomingPacket.objectID.EncodeApplicationTag(outbuf, ref optr); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); } else { throw new Exception("m0059 - Illegal object list index"); } break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_TYPE: // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTag(outbuf, ref optr, BACnetEnums.BACNET_APPLICATION_TAG.BACNET_APPLICATION_TAG_ENUMERATED, (uint)BACnetEnums.BACNET_OBJECT_TYPE.OBJECT_DEVICE); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_SYSTEM_STATUS: // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTag(outbuf, ref optr, BACnetEnums.BACNET_APPLICATION_TAG.BACNET_APPLICATION_TAG_ENUMERATED, (uint)BACnetEnums.BACNET_DEVICE_STATUS.STATUS_OPERATIONAL); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_IDENTIFIER: // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); incomingPacket.objectID.EncodeApplicationTag(outbuf, ref optr); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_VENDOR_NAME: // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTagString(outbuf, ref optr, apm.ourVendorName); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_MODEL_NAME: // supply the first (and only) (device) object optr = InsertReadPropertyResponse(apm, incomingBACpacket, outgoingBACpacket, outbuf, incomingBACpacket.propertyID); // Device Object ID InsertContextOpeningTag(outbuf, ref optr, 3); InsertApplicationTagString(outbuf, ref optr, apm.ourModelName); InsertContextClosingTag(outbuf, ref optr, 3); // Send it off SendOffPacket(apm, outgoingBACpacket, outbuf, optr); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_FIRMWARE_REVISION: case BACnetEnums.BACNET_PROPERTY_ID.PROP_APPLICATION_SOFTWARE_VERSION: RespondReadPropertyWithString(apm, incomingBACpacket, outgoingBACpacket, outbuf, apm.ourFirmwareRevision); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_VENDOR_IDENTIFIER: RespondReadPropertyWithUint(apm, incomingBACpacket, outgoingBACpacket, outbuf, apm.ourVendorID); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_PROTOCOL_VERSION: RespondReadPropertyWithUint(apm, incomingBACpacket, outgoingBACpacket, outbuf, 1); break; case BACnetEnums.BACNET_PROPERTY_ID.PROP_PROTOCOL_REVISION: RespondReadPropertyWithUint(apm, incomingBACpacket, outgoingBACpacket, outbuf, 4); break; default: apm.MessageTodo("m0046 - Implement read property " + incomingBACpacket.propertyID.ToString()); break; } break; default: apm.MessageTodo("m0044 - Implement confirmed service " + incomingBACpacket.confirmedServiceChoice.ToString()); break; } } if (incomingBACpacket.apduUnconfirmedServiceFlag == true) { switch (incomingBACpacket.pduType) { case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: switch (incomingBACpacket.unconfirmedServiceChoice) { case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_WHO_IS: // we need to respond // ONLY if we are in the range, and if not, ignore. if (incomingBACpacket.lowRange != 0 || incomingBACpacket.highRange != 0) { if (apm.ourDeviceId < incomingBACpacket.lowRange || apm.ourDeviceId > incomingBACpacket.highRange) { // This packet not for us apm.MessageLog("m0034 - Ranged Who-Is not addressed to us, ignoring"); break; } } // Compose the response (I-am) outgoingBACpacket.BACnetPort = incomingPacket.BACnetPort; outgoingBACpacket.npdu.isBroadcast = true; outgoingBACpacket.hopcount = 256; // destination address of the BACnet packet. (Must either be b'cast or directlyConnectedIPEP optr = 0; outgoingBACpacket.npdu.isNPDUmessage = false; // makes it an APDU outgoingBACpacket.pduType = BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST; outgoingBACpacket.unconfirmedServiceChoice = BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM; outgoingBACpacket.EncodeBACnetNew(outbuf, ref optr); // send the message // if there is no available adapter, this try will throw try { apm.bnm.bacnet_listen_socket.SendTo(outbuf, optr, SocketFlags.None, incomingPacket.directlyConnectedIPEndPointOfDevice); pktlog = new PacketLog(true, incomingPacket.directlyConnectedIPEndPointOfDevice, outgoingBACpacket); pktlog.BACnetPacket = (BACnetPacket)outgoingBACpacket; apm.bnm.BACnetMessageLog.Enqueue(pktlog); } catch (SocketException) { apm.MessageTodo("Either the network cable is unplugged, or there is no configured Ethernet Port on this computer"); } break; case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM: break; default: apm.MessageTodo("Implement " + incomingBACpacket.unconfirmedServiceChoice.ToString()); break; } break; default: apm.MessageTodo("Implement " + incomingBACpacket.pduType.ToString()); break; } } }
// This method that will be called when the thread is started public void BACnetListenerMethod() { Console.WriteLine("Thread starting for port " + Convert.ToString(BACnet_port)); while (true) { Byte[] received = new Byte[2000]; BACnetPacket incomingCRPpacket = new BACnetPacket(_apm, _bnm); // Create an IPEndPoint to capture the identity of the sending host. IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint senderRemote = (EndPoint)sender; try { incomingCRPpacket.length = _bnm.bacnet_listen_socket.ReceiveFrom(received, ref senderRemote); Console.WriteLine("This message was sent from " + ((IPEndPoint)senderRemote).Address.ToString() + " Port " + ((IPEndPoint)senderRemote).Port.ToString()); incomingCRPpacket.directlyConnectedIPEndPointOfDevice = new myIPEndPoint(senderRemote); incomingCRPpacket.buffer = received; // Decode the packet bool decodeOK = incomingCRPpacket.DecodeBACnet(received, incomingCRPpacket.length); if (!decodeOK) { continue; } // log this data PacketLog pkt = new PacketLog(false, (IPEndPoint)senderRemote, incomingCRPpacket); pkt.BACnetPacket = (BACnetPacket)incomingCRPpacket; _bnm.BACnetMessageLog.Enqueue(pkt); // did packet Decode fail to create a device? If so, we are not interested. e.g. Who-Is. if (incomingCRPpacket.srcDevice == null) { _apm.MessageTodo("m0039 - Device not created by packet decode"); continue; } _apm.pktQueueToApplication.Enqueue(incomingCRPpacket); } catch (SocketException) { // we expect a socket exception when shutting down System.Console.WriteLine("socket exception occurred"); } catch (System.Threading.ThreadAbortException) { System.Console.WriteLine("Thread abort exception occurred (shutting down)"); } catch (Exception efe) { // need to catch the inevitable exception when this blocking call is cancelled by the shutdown code _apm.MessagePanic(efe.ToString()); } } }
// This method that will be called when the thread is started public void BACnetInsideListener() { while (true) { // Byte[] received = new Byte[2000]; BACnetPacket packet = new BACnetPacket(_apm); // Create an IPEndPoint to capture the identity of the sending host. IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0); EndPoint senderRemote = (EndPoint)sender; try { // bacnet_listen_socket.Receive(received); packet.length = listen_socket.ReceiveFrom(packet.buffer, ref senderRemote); // Console.WriteLine("This message was sent from " + ((IPEndPoint)senderRemote).Address.ToString() + " Port " + ((IPEndPoint)senderRemote).Port.ToString()); // packet.fromBIP = (IPEndPoint) senderRemote; packet.directlyConnectedIPEndPointOfDevice = new myIPEndPoint(); packet.directlyConnectedIPEndPointOfDevice.Port = ((IPEndPoint)senderRemote).Port; packet.directlyConnectedIPEndPointOfDevice.Address = ((IPEndPoint)senderRemote).Address; // if the packet is from ourselves, discard if (listen_socket.detect_echo_packet(bnm, packet) == true) { continue; } // todo - one day, we will be able to see if this packet was addressed to this host in a broadcast packet, and mark the dadr accordingly, that is, if we care. // todo - remove directlyconnected //packet.srcDevice.adr = new ADR ( packet.directlyConnectedIPEndPointOfDevice ) ; // Make an undecoded copy of the packet for the application layer. This is to ease debugging in the asynch application layer. BACnetPacket appPkt = (BACnetPacket)packet.Clone(); // packet.buffer = received; packet.DecodeBACnet(); // extract some information from the packet for our caches if (packet.sAdr != null) { lock (_apm.internalRouterInfo) { _apm.internalRouterInfo.AddRoutingTableEntry(packet.sAdr.networkNumber); } } if (packet.routerTableList != null) { lock (_apm.internalRouterInfo) { foreach (RoutingTableEntry re in packet.routerTableList) { // surrounding this because we know of at least one router out there that has illegal network numbers try { _apm.internalRouterInfo.AddRoutingTableEntry(re.networkNumber); } catch (ProtocolException pe) { pe.DumpException(_apm); } } } } // display the decoded packet in the UI treeview bnm.newPacketQueue.myEnqueue(packet); // todo, if diagnostics are not running, then this queue will overflow.... hence the check.. find a cleaner method.. if (_apm.pktQueueToApplication.Count < 1000) { _apm.pktQueueToApplication.myEnqueue(appPkt); // notice, this is not a copy of the packet, it is a pointer to the same packet.... kick me if there are problems one day } } catch (ProtocolException pe) { pe.DumpException(_apm); } catch (SocketException) { // need to catch the inevitable exception when this blocking call is cancelled by the shutdown code // ignore, they will happen on shutdown } catch (ThreadAbortException) { } catch (Exception efe) { _apm.MessagePanic(efe.ToString()); } } }
public void UpdateDeviceTreeView(BACnetManager bnm, BACnetPacket pkt) { if (!pkt.apdu_present) { // means that this packet must be a NPDU message. Treat it differently switch (pkt.npdu.function) { case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK: //if (pkt.numberList.Count > 0) //{ // means we had a response from a router - establish the router in our tree. myTreeNode mtnd = EstablishTreeNodeDevice(bnm, pkt); if (mtnd != null) { // found, or established, the treenode matching the device, // now add the objects to it. // update the type of device - we now know it is a router (even if we did not know before). mtnd.device.type = BACnetEnums.DEVICE_TYPE.Router; mtnd.Text = "Router"; if (pkt.numberList != null) { foreach (int bno in pkt.numberList) { bool found = false; for (int i = 0; i < mtnd.Nodes.Count; i++) { if (mtnd.Nodes[i].GetType() == typeof(myTreeNode)) { myTreeNode mtnObj = (myTreeNode)mtnd.Nodes[i]; if (mtnObj.type == myTreeNode.TREENODE_OBJ_TYPE.NetworkNumber && mtnObj.networkNumber == bno) { // if we get here, the object already exists in the list and we must not add it again. mtnObj.networkNumberFromWhoIsRouter = true; found = true; break; } } } if (!found) { //// not found, so add myTreeNode ntn = mtnd.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.NetworkNumber, "Network " + bno.ToString()); ntn.networkNumber = (uint)bno; ntn.networkNumberFromWhoIsRouter = true; ntn.ToolTipText = "Do not right click on this item, it has no effect"; mtnd.Expand(); } } } else { _apm.MessageTodo("m0032"); } } //} break; case BACnetEnums.BACNET_NETWORK_MESSAGE_TYPE.NETWORK_MESSAGE_INIT_RT_TABLE_ACK: myTreeNode mtnrt = EstablishTreeNodeDevice(bnm, pkt); if (mtnrt != null) { // found, or established, the treenode matching the device, // now add the objects to it. // update the type of device - we now know it is a router (even if we did not know before). mtnrt.device.type = BACnetEnums.DEVICE_TYPE.Router; mtnrt.Text = "Router"; foreach (RouterPort rp in pkt.routerPortList) { bool found = false; for (int i = 0; i < mtnrt.Nodes.Count; i++) { if (mtnrt.Nodes[i].GetType() == typeof(myTreeNode)) { myTreeNode mtnObj = (myTreeNode)mtnrt.Nodes[i]; if (mtnObj.type == myTreeNode.TREENODE_OBJ_TYPE.NetworkNumber && mtnObj.networkNumber == rp.networkNumber) { // if we get here, the object already exists in the list and we must not add it again. found = true; mtnObj.networkNumberFromInitRouterTable = true; break; } } } if (!found) { //// not found, so add myTreeNode ntn = mtnrt.AddMyTreeNodeObject(myTreeNode.TREENODE_OBJ_TYPE.NetworkNumber, "Network " + rp.networkNumber.ToString()); ntn.networkNumber = rp.networkNumber; ntn.networkNumberFromInitRouterTable = true; // ntn.ToolTipText = "Do not right click on this item, it has no effect"; mtnrt.Expand(); } } } break; } return; } switch (pkt.pduType) { case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: switch (pkt.unconfirmedServiceChoice) { case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM: pkt.srcDevice.directlyConnectedIPEndPointOfDevice = pkt.directlyConnectedIPEndPointOfDevice; // was fromBIP // todo, not sure where I use this - check bnm.deviceList.Add(pkt.srcDevice); AddDeviceToTreeNode(bnm, pkt); // bnm.newPacketQueue.Enqueue(packet); break; case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_WHO_IS: // ignore reflected who-is messages break; default: BACnetLibraryCL.Panic("Todo"); break; } break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_COMPLEX_ACK: switch (pkt.confirmedServiceChoice) { case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY: switch (pkt.propertyID) { case BACnetEnums.BACNET_PROPERTY_ID.PROP_OBJECT_LIST: // what we need to do here is list the objects on the treeview... // find the device in the tree // add the objects to it myTreeNode mtn = findTreeNodeDevice(bnm, pkt); if (mtn != null) { // found the treenode matching the device, add the objects to it. if (pkt.objectList != null) { foreach (BACnetObjectIdentifier bno in pkt.objectList) { // does it exist? if so, ignore if (findTreeNodeObject(mtn, bno) == null) { // not found, so add myTreeNode ntn = new myTreeNode(); ntn.oID = bno; ntn.type = myTreeNode.TREENODE_OBJ_TYPE.BACnetObject; ntn.Text = bno.objectType.ToString() + " Instance: " + bno.objectInstance.ToString(); ntn.ToolTipText = "Do not right click on this item, it has no effect"; mtn.Nodes.Add(ntn); } } } // now remove the object list??? (but it will be removed when packet is destroyed.... } break; default: _apm.MessagePanic("m0030 " + pkt.propertyID.ToString()); break; } break; default: _apm.MessagePanic("m0029"); break; } break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_CONFIRMED_SERVICE_REQUEST: case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_REJECT: // These messages do not affect the Device TreeView, so we will ignore them.. break; default: _apm.MessageTodo("m0027 - Device Treeview needs to parse this message still: " + pkt.pduType.ToString()); break; } }
public PacketLog(bool sending, IPEndPoint ipep, BACnetPacket packet) { this.sending = sending; this.ipep = ipep; this.BACnetPacket = packet; }