a/branches/FeatureBranches/Debuglogging/SparkplugB/Function Blocks/FB_Edge/FB_Edge/NCMD/onNCMDMessage/svnobj b/branches/FeatureBranches/Debuglogging/SparkplugB/Function Blocks/FB_Edge/FB_Edge/NCMD/onNCMDMessage/svnobj
1
Gx_lh!0…jüoÏLŒ»Ò?UE«ÅSystem.StringL{f8a58466-d7f6-439f-bbb8-d4600e41d099}ImplementationL{3b83b776-fb25-43b8-99f2-3c507c9143fc}TextDocumentL{f3878285-8e4f-490b-bb1b-9acbb7eb04db}TextLinesL{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}    Id
1
Gx_lh!0…jüoÓL]ê>ìUE«ÅSystem.StringL{f8a58466-d7f6-439f-bbb8-d4600e41d099}ImplementationL{3b83b776-fb25-43b8-99f2-3c507c9143fc}TextDocumentL{f3878285-8e4f-490b-bb1b-9acbb7eb04db}TextLinesL{a5de0b0b-1cb5-4913-ac21-9d70293ec00d}    Id
2
longTagText
F//note: pMessage is already decoded.onNCMDMessage := FALSE;&//get first messageXpMessage.GetFirstMetric( name => MetricName,\                         datatype => datatype,f                         timestamp =>, //don't caret                         valueString => MetricValueString,p                         valueLreal => MetricValueLreal,l                         valueReal => MetricValueReal,t                         valueVarInt => MetricValueVarInt,h                         MetricValid => MetricValid,\                         HasNext => HasNext );ĖREPEAT //process the metric and grab the next metric until there are no more metrics (hasnext = FALSE).    IF MetricValid THEN0        CASE datatype OF@            MetricDataType.Int8:x                FOR i := LOWER_BOUND( THIS^.arSparkplugInt8,                                       1 ) TO UPPER_BOUND( THIS^.arSparkplugInt8, €                                                          1 ) DO!€                    IF MetricName = arSparkplugInt8[i].Name THEN"–                        arSparkplugInt8[i].Value := MetricValueVarInt.Int8;#4                    END_IF$0                END_FOR;%B            MetricDataType.Int16:&z                FOR i := LOWER_BOUND( THIS^.arSparkplugInt16,'Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugInt16,(‚                    IF MetricName = arSparkplugInt16[i].Name THEN)š                        arSparkplugInt16[i].Value := MetricValueVarInt.Int16;*Ō                // because cirrus Link MQTT Engine returns the ignition data type not the NBIRTH datatype+z                FOR i := LOWER_BOUND( THIS^.arSparkplugUInt8,,Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUInt8,-‚                    IF MetricName = arSparkplugUInt8[i].Name THEN.š                        arSparkplugUInt8[i].Value := MetricValueVarInt.UInt8;/B            MetricDataType.Int32:0z                FOR i := LOWER_BOUND( THIS^.arSparkplugInt32,1Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugInt32,2‚                    IF MetricName = arSparkplugInt32[i].Name THEN3š                        arSparkplugInt32[i].Value := MetricValueVarInt.Int32;4|                FOR i := LOWER_BOUND( THIS^.arSparkplugUInt16,5Ī                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUInt16,6„                    IF MetricName = arSparkplugUInt16[i].Name THEN7ž                        arSparkplugUInt16[i].Value := MetricValueVarInt.UInt16;8B            MetricDataType.Int64:9z                FOR i := LOWER_BOUND( THIS^.arSparkplugInt64,:Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugInt64,;‚                    IF MetricName = arSparkplugInt64[i].Name THEN<š                        arSparkplugInt64[i].Value := MetricValueVarInt.Int64;=|                FOR i := LOWER_BOUND( THIS^.arSparkplugUInt32,>Ī                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUInt32,?„                    IF MetricName = arSparkplugUInt32[i].Name THEN@ž                        arSparkplugUInt32[i].Value := MetricValueVarInt.UInt32;A|                FOR i := LOWER_BOUND( THIS^.arSparkplugUint64,BĪ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUint64,C„                    IF MetricName = arSparkplugUint64[i].Name THENDž                        arSparkplugUint64[i].Value := MetricValueVarInt.Uint64;EB            MetricDataType.UInt8:FD            MetricDataType.UInt16:GD            MetricDataType.UInt32:HD            MetricDataType.UInt64:IB            MetricDataType.Float:Jz                FOR i := LOWER_BOUND( THIS^.arSparkplugFloat,KĒ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugFloat,L‚                    IF MetricName = arSparkplugFloat[i].Name THENMŠ                        arSparkplugFloat[i].Value := MetricValueReal;ND            MetricDataType.Double:O|                FOR i := LOWER_BOUND( THIS^.arSparkplugDouble,PĪ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugDouble,Q„                    IF MetricName = arSparkplugDouble[i].Name THENRŽ                        arSparkplugDouble[i].Value := MetricValueLreal;SF            MetricDataType.Boolean:Th                //Special place for handling RebirthUz                IF (MetricName = "Node Control/Rebirth") THENVŽ                    //We have found that the server wants us to rebirthWH                    Rebirth := TRUE;Xt                    WriteDeviceLog( gc_sparkplug.CMP_EDGE,Yz                                    CmpLog.LogClass.LOG_INFO,ZĒ                                    'EoN NCMD Received is a Rebirth Command: %s',[š                                    TO_STRING( MetricValueVarInt.Boolean ) );\,                END_IF]d                //normal place for normal booleans^~                FOR i := LOWER_BOUND( THIS^.arSparkplugBoolean,_Ķ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugBoolean,`†                    IF MetricName = arSparkplugBoolean[i].Name THENaĒ                        arSparkplugBoolean[i].Value := MetricValueVarInt.Boolean;bF            MetricDataType.String_:c|                FOR i := LOWER_BOUND( THIS^.arSparkplugString,dĪ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugString,e„                    IF MetricName = arSparkplugString[i].Name THENf                        arSparkplugString[i].Value := MetricValueString;gx                FOR i := LOWER_BOUND( THIS^.arSparkplugText,h                                       1 ) TO UPPER_BOUND( THIS^.arSparkplugText,i€                    IF MetricName = arSparkplugText[i].Name THENjŒ                        arSparkplugText[i].Value := MetricValueString;kx                FOR i := LOWER_BOUND( THIS^.arSparkplugUUID,l                                       1 ) TO UPPER_BOUND( THIS^.arSparkplugUUID,m€                    IF MetricName = arSparkplugUUID[i].Name THENnŒ                        arSparkplugUUID[i].Value := MetricValueString;oH            MetricDataType.DateTime:p€                FOR i := LOWER_BOUND( THIS^.arSparkplugDateTime,qĻ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugDateTime,rˆ                    IF MetricName = arSparkplugDateTime[i].Name THENsŽ                        arSparkplugDateTime[i].Value := MetricValueVarInt.uliDateTime;t@            MetricDataType.Text:u@            MetricDataType.UUID:vĖ            MetricDataType.Unknown, MetricDataType.DataSet, MetricDataType.Bytes, MetricDataType.File,wP                MetricDataType.Template:x†                ; //maybe a log message? in any case, do nothing.  yĘ        //It might be posible that someone sends a NCMD without a datatype but that would be so weirdz        ELSE{            ;|         END_CASE}    END_IF~2    //get the next metric^    pMessage.GetNextMetric( name => MetricName,€b                            datatype => datatype,l                            timestamp =>, //don't care‚z                            valueString => MetricValueString,ƒv                            valueLreal => MetricValueLreal,„r                            valueReal => MetricValueReal,…z                            valueVarInt => MetricValueVarInt,†n                            MetricValid => MetricValid,‡b                            HasNext => HasNext );ˆ*UNTIL HasNext = FALSE‰END_REPEAT;ŠR//pMessage.GetNextMetric don't care today‹D//pMessage.GetSeq don't care todayŒP//pMessage.GetTimestamp don't care todayLWriteDeviceLog( gc_sparkplug.CMP_EDGE,ŽR                CmpLog.LogClass.LOG_INFO,\                'EoN NCMD Received Topic: %s',^                WSTRING_TO_STRING( pTopic^ ) );‘,onNCMDMessage := TRUE;’Interface“L{a9ed5b7e-75c5-4651-af16-d2c27e98cb94}”(*•    At the moment, this only supports the one specific metric, Node Control/Rebirth–.    Node Command (NCMD)—    ˜Ę    NCMD messages are used by backend applications to write to EoN node outputs and send Node Control™Š    commands to EoN nodes. Multiple metrics can be supplied in a single NCMD message.š˜    The following is a representation of a simple NCMD message on the topic:›l        spBv1.0/Sparkplug"! B Devices/NCMD/Raspberry Piœ„        "    The  Group ID  of this device is: Sparkplug"! B Devicesˆ        "    The host  EoN node ID  of this EoN node is: Raspberry Pižd        "    This is an NCMD message to an EoN nodeŸ     Consider the following Sparkplug"! B payload in the NCMD message shown above: 
2
longTagText
F//note: pMessage is already decoded.onNCMDMessage := FALSE;&//get first messageXpMessage.GetFirstMetric( name => MetricName,\                         datatype => datatype,f                         timestamp =>, //don't caret                         valueString => MetricValueString,p                         valueLreal => MetricValueLreal,l                         valueReal => MetricValueReal,t                         valueVarInt => MetricValueVarInt,h                         MetricValid => MetricValid,\                         HasNext => HasNext );ĖREPEAT //process the metric and grab the next metric until there are no more metrics (hasnext = FALSE).    IF MetricValid THEN0        CASE datatype OF@            MetricDataType.Int8:x                FOR i := LOWER_BOUND( THIS^.arSparkplugInt8,                                       1 ) TO UPPER_BOUND( THIS^.arSparkplugInt8, €                                                          1 ) DO!€                    IF MetricName = arSparkplugInt8[i].Name THEN"–                        arSparkplugInt8[i].Value := MetricValueVarInt.Int8;#4                    END_IF$0                END_FOR;%B            MetricDataType.Int16:&z                FOR i := LOWER_BOUND( THIS^.arSparkplugInt16,'Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugInt16,(‚                    IF MetricName = arSparkplugInt16[i].Name THEN)š                        arSparkplugInt16[i].Value := MetricValueVarInt.Int16;*Ō                // because cirrus Link MQTT Engine returns the ignition data type not the NBIRTH datatype+z                FOR i := LOWER_BOUND( THIS^.arSparkplugUInt8,,Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUInt8,-‚                    IF MetricName = arSparkplugUInt8[i].Name THEN.š                        arSparkplugUInt8[i].Value := MetricValueVarInt.UInt8;/B            MetricDataType.Int32:0z                FOR i := LOWER_BOUND( THIS^.arSparkplugInt32,1Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugInt32,2‚                    IF MetricName = arSparkplugInt32[i].Name THEN3š                        arSparkplugInt32[i].Value := MetricValueVarInt.Int32;4|                FOR i := LOWER_BOUND( THIS^.arSparkplugUInt16,5Ī                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUInt16,6„                    IF MetricName = arSparkplugUInt16[i].Name THEN7ž                        arSparkplugUInt16[i].Value := MetricValueVarInt.UInt16;8B            MetricDataType.Int64:9z                FOR i := LOWER_BOUND( THIS^.arSparkplugInt64,:Ē                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugInt64,;‚                    IF MetricName = arSparkplugInt64[i].Name THEN<š                        arSparkplugInt64[i].Value := MetricValueVarInt.Int64;=|                FOR i := LOWER_BOUND( THIS^.arSparkplugUInt32,>Ī                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUInt32,?„                    IF MetricName = arSparkplugUInt32[i].Name THEN@ž                        arSparkplugUInt32[i].Value := MetricValueVarInt.UInt32;A|                FOR i := LOWER_BOUND( THIS^.arSparkplugUint64,BĪ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugUint64,C„                    IF MetricName = arSparkplugUint64[i].Name THENDž                        arSparkplugUint64[i].Value := MetricValueVarInt.Uint64;EB            MetricDataType.UInt8:FD            MetricDataType.UInt16:GD            MetricDataType.UInt32:HD            MetricDataType.UInt64:IB            MetricDataType.Float:Jz                FOR i := LOWER_BOUND( THIS^.arSparkplugFloat,KĒ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugFloat,L‚                    IF MetricName = arSparkplugFloat[i].Name THENMŠ                        arSparkplugFloat[i].Value := MetricValueReal;ND            MetricDataType.Double:O|                FOR i := LOWER_BOUND( THIS^.arSparkplugDouble,PĪ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugDouble,Q„                    IF MetricName = arSparkplugDouble[i].Name THENRŽ                        arSparkplugDouble[i].Value := MetricValueLreal;SF            MetricDataType.Boolean:Th                //Special place for handling RebirthUz                IF (MetricName = "Node Control/Rebirth") THENVŽ                    //We have found that the server wants us to rebirthWH                    Rebirth := TRUE;Xt                    WriteDeviceLog( gc_sparkplug.CMP_EDGE,Y|                                    CmpLog.LogClass.LOG_DEBUG,ZĒ                                    'EoN NCMD Received is a Rebirth Command: %s',[š                                    TO_STRING( MetricValueVarInt.Boolean ) );\,                END_IF]d                //normal place for normal booleans^~                FOR i := LOWER_BOUND( THIS^.arSparkplugBoolean,_Ķ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugBoolean,`†                    IF MetricName = arSparkplugBoolean[i].Name THENaĒ                        arSparkplugBoolean[i].Value := MetricValueVarInt.Boolean;bF            MetricDataType.String_:c|                FOR i := LOWER_BOUND( THIS^.arSparkplugString,dĪ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugString,e„                    IF MetricName = arSparkplugString[i].Name THENf                        arSparkplugString[i].Value := MetricValueString;gx                FOR i := LOWER_BOUND( THIS^.arSparkplugText,h                                       1 ) TO UPPER_BOUND( THIS^.arSparkplugText,i€                    IF MetricName = arSparkplugText[i].Name THENjŒ                        arSparkplugText[i].Value := MetricValueString;kx                FOR i := LOWER_BOUND( THIS^.arSparkplugUUID,l                                       1 ) TO UPPER_BOUND( THIS^.arSparkplugUUID,m€                    IF MetricName = arSparkplugUUID[i].Name THENnŒ                        arSparkplugUUID[i].Value := MetricValueString;oH            MetricDataType.DateTime:p€                FOR i := LOWER_BOUND( THIS^.arSparkplugDateTime,qĻ                                      1 ) TO UPPER_BOUND( THIS^.arSparkplugDateTime,rˆ                    IF MetricName = arSparkplugDateTime[i].Name THENsŽ                        arSparkplugDateTime[i].Value := MetricValueVarInt.uliDateTime;t@            MetricDataType.Text:u@            MetricDataType.UUID:vĖ            MetricDataType.Unknown, MetricDataType.DataSet, MetricDataType.Bytes, MetricDataType.File,wP                MetricDataType.Template:x†                ; //maybe a log message? in any case, do nothing.  yĘ        //It might be posible that someone sends a NCMD without a datatype but that would be so weirdz        ELSE{            ;|         END_CASE}    END_IF~2    //get the next metric^    pMessage.GetNextMetric( name => MetricName,€b                            datatype => datatype,l                            timestamp =>, //don't care‚z                            valueString => MetricValueString,ƒv                            valueLreal => MetricValueLreal,„r                            valueReal => MetricValueReal,…z                            valueVarInt => MetricValueVarInt,†n                            MetricValid => MetricValid,‡b                            HasNext => HasNext );ˆ*UNTIL HasNext = FALSE‰END_REPEAT;ŠR//pMessage.GetNextMetric don't care today‹D//pMessage.GetSeq don't care todayŒP//pMessage.GetTimestamp don't care todayLWriteDeviceLog( gc_sparkplug.CMP_EDGE,ŽT                CmpLog.LogClass.LOG_DEBUG,\                'EoN NCMD Received Topic: %s',^                WSTRING_TO_STRING( pTopic^ ) );‘,onNCMDMessage := TRUE;’Interface“L{a9ed5b7e-75c5-4651-af16-d2c27e98cb94}”(*•    At the moment, this only supports the one specific metric, Node Control/Rebirth–.    Node Command (NCMD)—    ˜Ę    NCMD messages are used by backend applications to write to EoN node outputs and send Node Control™Š    commands to EoN nodes. Multiple metrics can be supplied in a single NCMD message.š˜    The following is a representation of a simple NCMD message on the topic:›l        spBv1.0/Sparkplug"! B Devices/NCMD/Raspberry Piœ„        "    The  Group ID  of this device is: Sparkplug"! B Devicesˆ        "    The host  EoN node ID  of this EoN node is: Raspberry Pižd        "    This is an NCMD message to an EoN nodeŸ     Consider the following Sparkplug"! B payload in the NCMD message shown above: 
3
    {¡F        "timestamp": 1486144502122,¢*        "metrics": [{£^                "name": "Node Control/Rebirth",¤V                "timestamp": 1486144502122,¥L                "dataType": "Boolean",¦:                "value": true§         }]¨
3
    {¡F        "timestamp": 1486144502122,¢*        "metrics": [{£^                "name": "Node Control/Rebirth",¤V                "timestamp": 1486144502122,¥L                "dataType": "Boolean",¦:                "value": true§         }]¨
4
    }©â    This NCMD payload tells the EoN node to republish its NBIRTH and DBIRTH(s) messages. This can be requested ifªä    a backend application gets an out of order seq number or if a metric arrives in an NDATA or DDATA message that«~    was not provided in the original NBIRTH or DBIRTH messages.¬*)­${attribute 'hide'}®6METHOD onNCMDMessage : BOOL¯VAR_INPUT°‚    pTopic : POINTER TO WSTRING(GC_Sparkplug.supported_string_lengths); // resembles the topic under which the message is posted ±END_VAR²VAR_IN_OUT³†    pMessage : FB_PayloadSimpleDecoder; //should already be decoded´VAR_OUTPUTµ8    Rebirth : BOOL := FALSE;¶VAR·Ž    MetricName        : WSTRING(GC_Sparkplug.supported_string_lengths);¸:    MetricValid       : BOOL;¹L    MetricValueVarInt : DecodedVarInt;º@    MetricValueString : WSTRING;»<    MetricValueLreal  : LREAL;¼:    MetricValueReal   : REAL;½:    HasNext           : BOOL;¾N    datatype          : MetricDataType;¿:    i                 : DINT;ÐÐÐEèÐÐ  
4
    }©â    This NCMD payload tells the EoN node to republish its NBIRTH and DBIRTH(s) messages. This can be requested ifªä    a backend application gets an out of order seq number or if a metric arrives in an NDATA or DDATA message that«~    was not provided in the original NBIRTH or DBIRTH messages.¬*)­${attribute 'hide'}®6METHOD onNCMDMessage : BOOL¯VAR_INPUT°‚    pTopic : POINTER TO WSTRING(GC_Sparkplug.supported_string_lengths); // resembles the topic under which the message is posted ±END_VAR²VAR_IN_OUT³†    pMessage : FB_PayloadSimpleDecoder; //should already be decoded´VAR_OUTPUTµ8    Rebirth : BOOL := FALSE;¶VAR·Ž    MetricName        : WSTRING(GC_Sparkplug.supported_string_lengths);¸:    MetricValid       : BOOL;¹L    MetricValueVarInt : DecodedVarInt;º@    MetricValueString : WSTRING;»<    MetricValueLreal  : LREAL;¼:    MetricValueReal   : REAL;½:    HasNext           : BOOL;¾N    datatype          : MetricDataType;¿:    i                 : DINT;ÐÐÐEèÐÐ  
5
­UÚÐ-
ÐÐ  
5
­UÚÐ-
ÐÐ  
6
­VÚÐ-ÐÐ  
6
­VÚÐ-ÐÐ  
7
­WÚÐ-ÐÐ  
7
­WÚÐ-ÐÐ  
...
...
286
­QÚÐ-¼ÐÐ 
286
­QÚÐ-¼ÐÐ 
287
­RÚÐ-½ÐÐ 
287
­RÚÐ-½ÐÐ 
288
­SÚÐ-¾ÐÐ 
288
­SÚÐ-¾ÐÐ 
289
­TÚÐ-¿ÐÐ 
289
­TÚÐ-¿ÐÐ 
290
­ÚÐ-±
290
­ÚÐ-±