Working with signals and rules
Data Source
Both equipment and users have knowledge about the factory, it can be either a counter value, a machine alarm or a current thermostat setting.
In PackOS we call these parameters ‘signals’, they are constantly being observed and processed to determine what’s currently happening on the shop-floor.
Our edge component - LogiX Gate - is a listener designed to handle many communication protocols in parallel - OPC, HTTP, SQL, listen for value changes and send them to our cloud-based processing.
LogiX Gate will buffer all messages if connection is not available, and send them as soon as it’s back.
It’s important to keep in mind that a single machine should not be powered by multiple LogiX Gates as it might cause issues with clock synchronisation. More on that later.
LogiX Gate sends messages in batches of configurable size, below you can see an example message consisting of 3 signal value changes:
[
{
"NodeId": "s=Filler_Counter",
"ApplicationUri": "OPC1",
"Value": {
"Value": 100,
"SourceTimestamp": "2021-04-30T00:03:20.917Z"
}
},
{
"NodeId": "s=Filler_Counter",
"ApplicationUri": "OPC1",
"Value": {
"Value": 110,
"SourceTimestamp": "2021-04-30T00:03:31.026Z"
}
},
{
"NodeId": "s=Capper_Alarm",
"ApplicationUri": "OPC1",
"Value": {
"Value": 1,
"SourceTimestamp": "2021-04-30T00:03:31.026Z"
}
},
]
Ability to input manual data - parameters, photos etc. using a mobile app is under development
Before the main processing, each signal can be transformed and/or augmented using PackOS pre-processing functions: https://ilabo.atlassian.net/wiki/spaces/LW/pages/1774420110
Machine model
Regardless of the technical details of gathering data from the factory, a machine is modelled in PackOS as an asset with pre-defined set of:
Signals
Properties
State definitions
State Rules
We are developing a new model of an asset, describing its internal structure (parts) and models for processes, health, behaviour and predictive maintenance
Read More: The Story Behind the Self-Learning Factory Concept
Signals
Each signal is identified by its Name
. It’s an identifier which needs to be unique in the context of a machine, important in rule execution (see below). It should not contain any spaces or special characters, and cannot be changed after the signal is created.
To display a more user-friendly name, use signal Description
Type - control the meaning of the signal value:
SIGNAL - a default value having no meaning, the signal can be used in rules to control the state of the machine
NOPROCESSING - makes the processing skip this signal, it’s value is not being tracked
COUNTER - is used as a good product count, its
Unit
field sets the machine production unit. Currently, only a single good counter per machine is allowedWASTE_COUNTER - defines a waste product count. There can be many waste counters on a single machine. Its
Unit
can be different than the one of theCOUNTER
- PackOS will make a conversion using an active packing structure.SHORT_PERFORMANCE - used to track current performance value. It's calculated automatically from the COUNTER. There should be only one signal of this type per machine and production line.
Unit
defines how the signal is being calculated (e.g. car/min) converting the production unit from the Counter unit using an active packing structure and appropriate time denominator.ENERGY_ACTIVE_COUNTER - electricity consumption counter (currently assumed to always be in kWh, if you need to convert units - please use pre-processing function). You can define multiple counters for a single machine / line.
ENERGY_CURRENT_POWER - current electricity demand (assumed to be in kW). Shown in a gauge.
KEEP_ALIVE - used to capture status messages from the edge. There should be exactly 1 for each machine. Its Source URI should be
KEEPALIVE
and Device ID corresponds to the name of the LogiX Gate.
Should Archive - decides if a history of signal values should be persisted. You can still use it in rules to determine machine state etc. But you won’t be able to analyse it’s historical values
Value type - currently not used
Source URI & Device ID - defines a data source for the signal.
Source URI
corresponds to the name of the OPC tag (theNodeId
from the message), andDevice ID
to the name of the input defined in the LogiX Gate (ApplicationUri
in the message)Unit - used for unit conversions of the COUNTER and WASTE_COUNTER signals
Min & Max - can be defined to display threshold lines in the signal history, and publish notifications about exceeded thresholds
Clocks
Each machine is ‘powered’ by multiple signals, sometimes from multiple data sources (e.g. 2 different OPC servers). When LogiX Gates reads values from these sources, it sorts them and assigns each message a current timestamp based on the local clock. This makes sure that messages sent by a single LogiX Gate are always in-order, regardless of the clocks of the sources.
Each machine tracks its own clock. This clock does not tick continuously like a usual clock, but rather it is dependent on the latest timestamp of the received messages. Time-dependent computation states like time rules or short performance are applied instantly for the whole period between the last and the current clock.
(e.g. when there are two messages 10:00:00 → 10:00:10, the rules are evaluated instantly 10 times for all timestamps in-between: 10:00:00, 10:00:01 …. 10:00:10)
This creates 2 types of corrupted messages, usually incorrectly coming from a second LogiX Gate instance:
Delayed messages - when the timestamp from the message is older than the most recent observed timestamp.
Messages from the future - a single message with a clock ‘from the future’ will make the system ignore all ‘good’ messages up to that point in time.
To resolve issues with time:
1 machine is never powered with more than 1 LogiX Gate (1 LG can power multiple machines)
Make sure that all signals have correct Device ID specified
State Rules
State rules control a current state of a machine, there are two possible formats:
Simple format, which allows for very simple rules checking signal values
Advanced format, which can be used for more advanced rules
Both formats can be used simultaneously for different rules on a single machine.
To remove problem you need to remove all rules assigned to it.
Simple conditions
If you work with simple value comparisons, you can just use the UI for the list of conditions, and don’t need to dig deeper into this topic
The ‘advanced editor' uses the following syntax:
(expression1) && (expression2) || (expression3)
Each expression can consist of exactly one Name
, Value
and Timestamp
comparison
(Name Equals AlarmOne && Value Equals 1) && (Name Equals AlarmTwo && Value Equals 0)
To understand it, imagine the following table of all signals, with their current values and timestamps of last updates:
Name | Value | Timestamp |
---|---|---|
AlarmOne | 1 | 3rd Feb, 10:00:00 |
AlarmTwo | 2 | 3rd Feb, 9:50:00 |
… | … | … |
The expression is true, if there is a row in this table which corresponds to the expression conditions.
E.g. this expression is true:
Because there is a row where Name = 'AlarmOne'
and at the same time Value = '1'
.
However this rule:
Is not true, the current value of AlarmTwo
is 2.
Sometimes, you need to use a dynamic value for comparison, injected when the rule is executed:
msOffset[-x]
- represents the current machine time (see ‘Clocks’ above), can be used to compare it to the last update timestamp. The value in[]
can be used to subtract some number of milliseconds from the current clock, before comparison.
E.g. if the machine time is 10:00:00,msOffset[-2000]
will represent 9:59:58.
(Using a non-negative value will move the clock into the future - which never makes sense)
This allows you to check if a value ofCounterOne
has been updated during the last 15 seconds:
Or make sure that the last value ofAlarmOne
is older than 4 secondshourlyExpectedPerformanceOffset[]
- uses machineDesignSpeed
setting to calculate the expected time between counter increases.
E.g. if design performance = 6 car/min, it means that we expect a carton every ~10 seconds (+- some tolerance). So you can write a rule, similar to the hand-provided duration above:
Supported value comparisons:
Equal
/Equals
/==
/=
- checks if value is equal (case sensitive). Watch out for boolean values, if they are represented as decimal ‘1’, comparing them to ‘true' won’t work, you need to compare it to '1' explicitly. And the other way round.
The following expressions will attempt to convert value to a decimal before comparing, if
GreaterThan
/>
GreaterThanOrEqual
/>=
LessThan
/<
LessThanOrEqual
/<=
To combine expressions you can use:
Or
/||
And
/&&
Note that:
There can be only 1 ‘Name’, ‘Value’ and ‘Timestamp’ comparison in a single expression
Nested expressions are not supported e.g: ((expression1) && (expression2)) || (expression3)
If no
Value
orTimestamp
comparison is present in the rule, the rule will be always true
e.g.(Name Equals AlarmOne)
always evaluates totrue
Operations like
+
,-
,/
,*
are not supportedComparison of signals is not supported
All of the points mentioned above, and much more is supported by the advanced format:
Advanced format
It allows you to write arbitrary C# expressions returning true
or false
.
Before writing a rule, you need to decide if the rule is time-dependent (which will allow you to use Now
) and check for example if last signal timestamp exceeded some duration.
An example rule looks as follows:
The following variables are available:
DateTime Now
- Current Date
Current UTC date (Read more...)
Only available if the rule is time-dependentSignalDictionary Signals
- Signal Dictionary
A dictionary of raw machine signals, holding the current and previous value.string GetCurrentValue(string key)
- returns last value of the signal as stringstring GetPreviousValue(string key)
- like above, but for the previous valueT GetCurrentValue<T>(string key)
- returns the current value as the requested typeT GetPreviousValue<T>(string key)
- like above, but for the previous valueDateTime GetCurrentUpdate(string key)
- returns the UTC date of last signal updateDateTime GetPreviousUpdate(string key)
- like above, but for the previous value
CounterDictionary Counters
- Counter Dictionary
Similar to the SignalDictionary, but holds only validated counter values (after guards, resets etc).
e.g. if raw signal goes like: 100 → 102 → 0 → 105 → 0 → 110 → 0 → 5 → 1000 → 10
this dictionary will track only: 100 → 102 → 105 → 110 → 5 → 10double GetCurrentValue(string key)
- current value of the counterDateTime GetCurrentUpdate(string key)
- timestamp of current value updatedouble GetPreviousValue(string key)
- previous value of the counterDateTime GetPreviousUpdate(string key)
- timestamp of previous value update
double DesignPerformance
- Current performance setting for a machine
in production_unit / hour.
e.g. it’s useful to compare the delay from the last counter increase to the machine performance: