public static void TreeViewUpdate(AppManager apm, BACnetManager bnm, TreeView treeViewMessageLog, bool logmessages) { if (bnm.BACnetMessageLog.Count > 0) { while (bnm.BACnetMessageLog.Count > 0) { // remove the first treenode _count++; PacketLog pktlog = bnm.BACnetMessageLog.Dequeue(); if (!logmessages) { // discard the message, unless it has been logged as an error if (pktlog.BACnetPacket != null && !pktlog.BACnetPacket.errorFlag) { continue; } } TreeNode ntn = new TreeNode(); TreeNodeCollection addBACnetHere = treeViewMessageLog.Nodes; if (pktlog.BACnetPacket != null) { // bump the rest up a level TreeNode nntn = new TreeNode(); nntn.Text = "BACnet"; if (pktlog.sending == true) { nntn.Text = _count.ToString() + " BACnet Sent"; nntn.BackColor = Color.LightPink; } else { nntn.Text = _count.ToString() + " BACnet Recd"; nntn.BackColor = Color.LightGreen; } // display some NPDU parameters if (pktlog.BACnetPacket.npdu.isBroadcast) { nntn.Nodes.Add("To: Broadcast"); } else { if (pktlog.BACnetPacket.dadr != null) { nntn.Nodes.Add("To: " + pktlog.BACnetPacket.dadr.ToString()); } } // From address if (pktlog.BACnetPacket.directlyConnectedIPEndPointOfDevice != null) { nntn.Nodes.Add("From: " + pktlog.BACnetPacket.directlyConnectedIPEndPointOfDevice.ToString()); } if (pktlog.BACnetPacket.npdu.expectingReply) { nntn.Nodes.Add("Expecting Reply"); } if (!pktlog.BACnetPacket.npdu.isNPDUmessage) { switch (pktlog.BACnetPacket.pduType) { case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST: nntn.Text += " Unconfirmed Service Request -"; switch (pktlog.BACnetPacket.unconfirmedServiceChoice) { case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_I_AM: nntn.Text += " I-Am"; break; case BACnetEnums.BACNET_UNCONFIRMED_SERVICE.SERVICE_UNCONFIRMED_WHO_IS: nntn.Text += " Who-Is"; break; default: nntn.Text += " m0019 Unknown BACnet unconfirmed service type - fix line 196 PacketLog.cs"; break; } break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_CONFIRMED_SERVICE_REQUEST: nntn.Text += " Confirmed Service Request"; switch (pktlog.BACnetPacket.confirmedServiceChoice) { case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY: nntn.Nodes.Add("Read Property " + pktlog.BACnetPacket.propertyID.ToString()); break; case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROP_MULTIPLE: nntn.Nodes.Add("Read Property Multiple"); break; default: nntn.Nodes.Add("m0014 Unknown BACnet confirmed service type " + pktlog.BACnetPacket.confirmedServiceChoice.ToString()); break; } break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_COMPLEX_ACK: nntn.Text += " Complex ACK -"; switch (pktlog.BACnetPacket.confirmedServiceChoice) { case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROPERTY: nntn.Text += " Read Property " + pktlog.BACnetPacket.propertyID.ToString(); break; case BACnetEnums.BACNET_CONFIRMED_SERVICE.SERVICE_CONFIRMED_READ_PROP_MULTIPLE: nntn.Text += " Read Property Multiple"; break; default: nntn.Text += " m0036 Unknown BACnet confirmed service type"; break; } break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_REJECT: nntn.Text += " Reject PDU - " + pktlog.BACnetPacket.pduRejectReason.ToString() + " [" + pktlog.BACnetPacket.invokeID.ToString() + "]"; break; case BACnetEnums.BACNET_PDU_TYPE.PDU_TYPE_ABORT: apm.MessageTodo("m0092 Resolve pktlog.bacnetpacket.pdutyp " + pktlog.BACnetPacket.pduType.ToString()); break; default: apm.MessageTodo("m0015 Resolve pktlog.bacnetpacket.pdutyp " + pktlog.BACnetPacket.pduType.ToString()); break; } } else if (pktlog.BACnetPacket.apdu_present) { apm.MessageTodo("m0018 I dont expect to see this"); } else { // todo, clean up this flag one day nntn.Nodes.Add("NPDU Function: " + pktlog.BACnetPacket.npdu.function.ToString()); } addBACnetHere.Add(nntn); } treeViewMessageLog.ExpandAll(); // remove all the earlier nodes... while (treeViewMessageLog.Nodes.Count > 150) { treeViewMessageLog.Nodes.RemoveAt(0); } } } }
// 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()); } } }
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; } } }