Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when subscribing data from PLC.. #5

Closed
yltsa opened this issue Jun 5, 2019 · 14 comments
Closed

Error when subscribing data from PLC.. #5

yltsa opened this issue Jun 5, 2019 · 14 comments

Comments

@yltsa
Copy link

yltsa commented Jun 5, 2019

Hi, I am not so good in BACnet. But here is the problem.

I am using the SubscriptionManager from these examples (AnotherStorageImplementation).

We have a PLC which is trying to subscribe AnalogValue parameters from a Windows service which is based on BacnetActivity classes.

The problem is that the server decodes an error after bacnetClient.Notify function. The error comes in this function in BacnetClient class:

private void OnRecieve(IBacnetTransport sender, byte[] buffer, int offset, int msgLength, BacnetAddress remoteAddress)

The buffer[] contains the following data:
[0] 129
{1] 10
[2] 0
[3] 13
[4] 1
[5] 0
[6] 80
[7] 1
[8] 1
[9] 145
[10] 5
[11] 145
[12] 7
The offset parameter is 6 which points to 80 => Error

The subscribing works with Yabe.. but not with the PLC.

@gralin
Copy link
Member

gralin commented Jun 6, 2019

Hi @yltsa, fist of all can you update the nuget packet to reference the latest version of BACnet client library? These examples are a bit outdated and not maintained, so that might be one cause for the issue. If this doesn't help, can you provide a wireshark dump from this situation where PLC subscribes and you get this issue? Best would be if the dump was filterer to only contained BACnet related traffic (capture filter on interface: udp port 47808 or display filter: bacnet || bvlc || bacapp and export visible)

@gralin
Copy link
Member

gralin commented Jun 6, 2019

There is an open abandoned pull request that updates the library reference, adjustes code to new namespacing and fixes a problem with Analog Object, but code review was not addresses. If you want you can start from there and later.

@yltsa
Copy link
Author

yltsa commented Jun 6, 2019

Hello.. I have the newest nuget packages. Have also tried with the version 2 BACnet lib but the same result.

Here is a wireshark dump file (I use it first time). This file should contain three subscriptions and the following sequence:

Add BBMD
2019-06-06 14:38:32.4894 - INFO: Add peer BBMD: 10.102.0.19;255.255.255.255;47808

This is OK. From Yabe software running in 10.102.0.20 IP address
2019-06-06 14:38:59.3525 - INFO: New subscription, Receiver:10.102.0.20:59906, Object:OBJECT_ANALOG_VALUE:212

This is from PLC in 10.102.0.17. Does not work:
2019-06-06 14:39:18.1604 - INFO: New subscription, Receiver:10.102.0.17:47808, Object:OBJECT_ANALOG_VALUE:212
2019-06-06 14:39:18.2824 - ERROR: BacnetActivity::OnSubscribeCOV: Error from device: ERROR_CLASS_SERVICES - ERROR_CODE_INCONSISTENT_PARAMETERS, BACnet

This is from the same PLC. Does not work:
2019-06-06 14:39:19.1425 - INFO: New subscription, Receiver:10.102.0.17:47808, Object:OBJECT_ANALOG_VALUE:1212
2019-06-06 14:39:19.1635 - ERROR: BacnetActivity::OnSubscribeCOV: Error from device: ERROR_CLASS_SERVICES - ERROR_CODE_INCONSISTENT_PARAMETERS, BACnet

BACnetSubscription.zip

@yltsa
Copy link
Author

yltsa commented Jun 6, 2019

Hi.. I downloaded the 1.0.20 beta Examples and tried Analog Object from that code. But the same result..

@yltsa
Copy link
Author

yltsa commented Jun 11, 2019

Hi,

this works now with the PLC. My colleague made some changes to the following two functions in BacnetActivity class:

        /*****************************************************************************************************/
        static void handler_OnSubscribeCOV(BacnetClient sender, BacnetAddress adr, byte invoke_id, uint subscriberProcessIdentifier, BacnetObjectId monitoredObjectIdentifier, bool cancellationRequest, bool issueConfirmedNotifications, uint lifetime, BacnetMaxSegments max_segments)
        {
            lock (_device)
            {
                BaCSharpObject bacobj = _device.FindBacnetObject(monitoredObjectIdentifier);
                if (bacobj != null)
                {
                    //create 
                    Subscription sub = SubscriptionManager.HandleSubscriptionRequest(sender, adr, invoke_id, subscriberProcessIdentifier, monitoredObjectIdentifier, (uint)BacnetPropertyIds.PROP_ALL, cancellationRequest, issueConfirmedNotifications, lifetime, 0);

                    //send confirm
                    sender.SimpleAckResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV, invoke_id);

                    //also send first values
                    if (!cancellationRequest)
                    {
                        System.Threading.ThreadPool.QueueUserWorkItem((o) =>
                        {
                            IList<BacnetPropertyValue> values;
                            List<BacnetPropertyReference> references = new List<BacnetPropertyReference>();
                            references.Add(new BacnetPropertyReference((uint)BacnetPropertyIds.PROP_PRESENT_VALUE, System.IO.BACnet.Serialize.ASN1.BACNET_ARRAY_ALL));
                            references.Add(new BacnetPropertyReference((uint)BacnetPropertyIds.PROP_STATUS_FLAGS, System.IO.BACnet.Serialize.ASN1.BACNET_ARRAY_ALL));

                            bacobj.ReadPropertyMultiple(sender, adr, references, out values);
                            if (values.Count > 0)
                            {
                                if (!sender.Notify(adr, sub.subscriberProcessIdentifier, _deviceId, sub.monitoredObjectIdentifier, (uint)sub.GetTimeRemaining(), sub.issueConfirmedNotifications, values))
                                {
                                    Log.Instance.Error("Couldn't send notify");
                                }
                            }
                        }, null);
                    }
                }
                else
                {
                    sender.ErrorResponse(adr, BacnetConfirmedServices.SERVICE_CONFIRMED_SUBSCRIBE_COV, invoke_id, BacnetErrorClasses.ERROR_CLASS_DEVICE, BacnetErrorCodes.ERROR_CODE_OTHER);
                }  
            }
        }
    /*****************************************************************************************************/
      static void handler_OnCOVManagementNotify(BaCSharpObject sender, BacnetPropertyIds propId)
      {
          if (propId == BacnetPropertyIds.PROP_PRESENT_VALUE)
          {
              System.Threading.ThreadPool.QueueUserWorkItem((o) =>
              {
                  lock (_device)
                  {
                      //remove old leftovers
                      SubscriptionManager.RemoveOldSubscriptions();
                      //find subscription
                      List<Subscription> subs = SubscriptionManager.GetSubscriptionsForObject(sender.PROP_OBJECT_IDENTIFIER);
                      if (subs == null) return; // nobody
                                                //Read the property
                      IList<BacnetValue> value;
                      BacnetPropertyReference br = new BacnetPropertyReference((uint)propId, (uint)System.IO.BACnet.Serialize.ASN1.BACNET_ARRAY_ALL);
                      ErrorCodes error = sender.ReadPropertyValue(br, out value);
                      List<BacnetPropertyValue> values = new List<BacnetPropertyValue>();
                      BacnetPropertyValue tmp = new BacnetPropertyValue();
                      tmp.value = value;
                      tmp.property = br;
                      values.Add(tmp);

                      IList<BacnetValue> value2;
                      BacnetPropertyReference br2 = new BacnetPropertyReference((uint)BacnetPropertyIds.PROP_STATUS_FLAGS, (uint)System.IO.BACnet.Serialize.ASN1.BACNET_ARRAY_ALL);
                      ErrorCodes error2 = sender.ReadPropertyValue(br2, out value2);
                      if (error2 == ErrorCodes.Good)
                      {
                          BacnetPropertyValue tmp2 = new BacnetPropertyValue();
                          tmp2.value = value2;
                          tmp2.property = br2;
                          values.Add(tmp2);
                      }
                      //send to all
                      foreach (Subscription sub in subs)
                      {
                          if (sub.monitoredProperty.propertyIdentifier == (uint)BacnetPropertyIds.PROP_ALL || sub.monitoredProperty.propertyIdentifier == (uint)propId)
                          {
                              tmp.property = sub.monitoredProperty;

                              if (!sub.reciever.Notify(sub.reciever_address, sub.subscriberProcessIdentifier, _deviceId, sub.monitoredObjectIdentifier, (uint)sub.GetTimeRemaining(), sub.issueConfirmedNotifications, values))
                              {
                                  SubscriptionManager.RemoveReceiver(sub.reciever_address);
                              }
                          }
                      }
                  }
              }, null);
          }
      }

@yltsa yltsa closed this as completed Jun 11, 2019
@gralin
Copy link
Member

gralin commented Jun 11, 2019

@yltsa thank you for the feedback, I will check the changes and update the examples so that others don't have same problem

@yltsa
Copy link
Author

yltsa commented Jun 11, 2019

@gralin Yes.. but please be careful. It was working before with Yabe. This was a quick fix for us that we get the PLC compatibility. Maybe we have broken something else.

I put the BaCSharp code into own assembly which is referenced from our application. BaCSharp is a nice layer above the BACnet library:

BaCSharp

@gralin
Copy link
Member

gralin commented Jun 11, 2019

@yltsa sure I will see why it works in Yabe, it could be that it was fixed after the codebases diverged and was never synced back. Question, I see you also have the source of BACnet library in your solution. Was there a reason to do it like that instead of using NuGet package?

@yltsa
Copy link
Author

yltsa commented Jun 11, 2019

@gralin Hi, I used the BACnet source code only for debugging and also made some useless trials before. The NuGet package works too.

I tested also the BACnet ver. 2 from this site. Today a quick test with the ver. 2 was not OK. Other error when making the subscription.

I made some new properties for the BACnet 1 so can switch quickly between the libs. Other small work was to get Yabe source code and modify it to use the BACnet lib. directly. I can send this project for you if you want..

@yltsa
Copy link
Author

yltsa commented Jun 11, 2019

OK, some hacking. Yabe is not compatible with the NuGet package:

Yabe

@yltsa
Copy link
Author

yltsa commented Jun 11, 2019

My changes are marked with //XXXIR string in BACnet lib. The code is here:

BACnetAndYabe.zip

@gralin
Copy link
Member

gralin commented Jun 11, 2019

@yltsa thank you. If you have time would you be willing to check what has been broken in v2 that it's not working for you? There is one unmerged PR you can also check, but it's mainly refactor and tests so shouldn't be much different from v2.

git clone https://github.com/DarkStarDS9/BACnet.git   
git checkout Tests/Back2Back

@yltsa
Copy link
Author

yltsa commented Jun 11, 2019

@gralin Yes, I play later with the BACnet lib v2. I can try test it with my colleague on the next Tuesday.

@gralin
Copy link
Member

gralin commented Jun 11, 2019

@yltsa great thank you. If you find the problem and submit a fix, later v2 will be already working for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants