diff --git a/src/main/java/ipos/project/MainApp.java b/src/main/java/ipos/project/MainApp.java index 60cd9083d7f8eea83f16f094a7e433cd9f8a3b4f..6018fea2915df5f42e1e545fc4696cad49717624 100644 --- a/src/main/java/ipos/project/MainApp.java +++ b/src/main/java/ipos/project/MainApp.java @@ -80,6 +80,12 @@ public class MainApp { ipos.project.SensorValueIntegration.api.MqttPositionHandler.setInitialized(true); } + /** + * IPos-Framework is initialized with data that is suitable for testing the "OrderPicker"-usecase + * This initialization data is contained in configuration file ORDERPICKER_FILE. + * OrderPicker extension is initialized (OFBizOrderPicker.initialize()). + * After initialization the "OrderPicker extension" should be updated by the IPos-FW with all relevant positions + */ private static void initOp() { ipos.project.SensorValueIntegration.api.MqttPositionHandler.setInitialized(false); SimpleSceneIntegration.init(ORDERPICKER_FILE); diff --git a/src/main/java/ipos/project/devkit/eca/ECARule.java b/src/main/java/ipos/project/devkit/eca/ECARule.java index b3f7d3e99c0cc1568e879699975d782fef0588d9..89b6999484226b9a104ab4b1b3cf71f486126f2e 100644 --- a/src/main/java/ipos/project/devkit/eca/ECARule.java +++ b/src/main/java/ipos/project/devkit/eca/ECARule.java @@ -8,6 +8,16 @@ public abstract class ECARule { protected Condition condition; + /** + * This function implements the overall behaviour of each ECARule: + * Determine applicability of the PositionEvent -> + * determine whether the PositionEvent fulfills the current condition and can be accepted -> + * translate the PositionEvent into an action and execute it. + * Remark: If the PositionEvent can not be accepted a no-operation action is created and executed. + * The behaviour of the ECARule at runtime depends on the implementation of the Condition- and + * Action-interface + * @param posEvent + */ public void apply(IposPositionEvent posEvent){ if (isApplicable(posEvent)){ Action action = condition.evaluate(posEvent); diff --git a/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPicker.java b/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPicker.java index cbb7c705bc45bdef1ae08e0311e788e4068d2a94..e93f1f3e3895c5a452f8455fcc01d685373cb6c9 100644 --- a/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPicker.java +++ b/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPicker.java @@ -22,6 +22,8 @@ import java.io.File; * This filter is part of this IPos-FW and is used for the verification. Also, the * frontend application is initialized and updated to allow the operator to track the * progress of the picker and detect errors. + * + * The picklist conforms to the datamodel defined in the open-source ERP-system OFBiz. */ @Component public class OFBizOrderPicker { @@ -43,6 +45,12 @@ public class OFBizOrderPicker { ofbizOpIposExt.setMqttService(mqttService); } + /** + * The OFBizOrderPicker application is an extension of the IPos-FW. Therefore, initialization relies + * on the function "configureIpos", which is provided by the abstract class IPosExtension. Each application-specific + * extension of the IPos-FW, i.e., also the OrderPicker extension, has to derive a concrete class from that class. + * The OrderPicker extension derives the class ipos.project.iposextension.orderpicker.OFBizOrderPickerExt + */ public static void initialize(){ try { ofbizOpIposExt.configureIpos(new IPosArguments.IPosConfigData() { @@ -53,6 +61,14 @@ public class OFBizOrderPicker { } } + /** Function transforms the received picklist into a data format that can be handled + * by the frontend-application (FETable) and publishes the picklist to the + * frontend-application. Moreover, a filter (ECARule) is set up for accepting the + * PositionEvents that are sent from the IPos-FW. The information that is relevant + * for the filter is the zone that the position belongs to. + * + * @param picklist + */ public static void handlePicklist(Picklist picklist){ try { FETable feTable = OFBizOrderPickerTrans.transformPicklistIntoFeTable(picklist); diff --git a/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPickerExt.java b/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPickerExt.java index 2d53fdb975c2b9dd5fd35e999c14eaa8936b38e7..8e277b29e76b859ebc2cb55ff98aba1ce7fa5fa3 100644 --- a/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPickerExt.java +++ b/src/main/java/ipos/project/iposextension/orderpicker/OFBizOrderPickerExt.java @@ -19,6 +19,9 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; +/** + * Extension of the IPos-FW specific to the usecase "OrderPicker". + */ public class OFBizOrderPickerExt extends IPosExtension { private static org.apache.logging.log4j.Logger LOG = LogManager.getLogger(); @@ -39,15 +42,21 @@ public class OFBizOrderPickerExt extends IPosExtension { return zoneIds.substring(0, zoneIds.length()-2); } + /** + * Function runs through all registered picklists (i.e., all ECARules that have been created) and + * applies the received PositionEvent to it. It is not the responsibility of this function to determine + * whether a given PositionEvent is applicable to a given ECARule. This decision is determined by the ECARule. + * For handling a PositionEvent the classes SeqPicklistRule, SeqPicklistRule, SeqPicklistCondition, and UpdateFrontendAction are relevant. + * + * @param posEvent + * @param _posEvtConf + */ @Override public void handlePositionEvent(IposPositionEvent posEvent, IPosArguments.HandlePosEventConf _posEvtConf) { LOG.info("OP:"); LOG.info("OP:----OFBizOrderPickerExt--------------------------"); LOG.info("OP: Received IposPositionEvent for agent " + posEvent.getAgentId() + ". Zones: " + extractZoneIdsAsString(posEvent.getZoneDescriptors()) + "; position: " + logPoint((Point3D) posEvent.getPosition().getPoint())); try { - // String picklistId = readPicklistId(_posEvtConf); - // SeqPicklistRule spRule = getEcaRule(picklistId); - spRules.forEach(spRule -> spRule.apply(posEvent)); /* above: lambda-expression, shortform of: @@ -58,8 +67,6 @@ public class OFBizOrderPickerExt extends IPosExtension { } }); */ - // CEFResult cefResult = cef_seq.acceptPositionEvent(posEvent); - // handleCefResult(picklistId, cefResult); }catch (RuntimeException e){ LOG.info("OP: PositionEvent could not be handled: " + e.getMessage()); return; @@ -98,6 +105,13 @@ public class OFBizOrderPickerExt extends IPosExtension { return picklistId; } */ + + /** + * Functions prepares a MonitoringRequest that causes the IPos-FW to update the OrderPicker extension with all positions + * relevant for the OrderPicker-usecase. + * @param iposConfigData + * @return + */ @Override public SimpleScene.IposConfigWrapper prepareConfigWrapper(IPosArguments.IPosConfigData iposConfigData) { try { @@ -107,6 +121,14 @@ public class OFBizOrderPickerExt extends IPosExtension { } } + /** + * Function creates an ECARule that is able to detect whether PositionEvents have been received in + * an order that conforms to the order that is specified by the Picklist (see testdata-file testdata_raw_orderpicker_readable.txt). + * The picklist specifies picklistBins and InventoryItems. InventoryItems have to be placed in the picklistBins they belong to. + * Picklistbins have to be handled in the order of their occurence in the textfile. InventoryItems have to be handled + * in the order of their occurence in their picklistbin. + * @param picklist + */ public void setupECARule(Picklist picklist){ String pickerId = extractPickerId(picklist).orElseThrow(() -> new RuntimeException("Picklist did not contain the ID of the picker who is responsible for it")); SeqPicklistRule spRule = new SeqPicklistRule(picklist.getPicklistId(), pickerId); // complex event filter for verifying the picker diff --git a/src/main/java/ipos/project/iposextension/orderpicker/README.md b/src/main/java/ipos/project/iposextension/orderpicker/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a7a868019fd440213c6f7aab4daa90b6010d00f2 --- /dev/null +++ b/src/main/java/ipos/project/iposextension/orderpicker/README.md @@ -0,0 +1,55 @@ +# OrderPicker extension + +## How to run? +1. Preparation + - Make sure that IPos-FW can connect to an MQTT-server + - Verify MQTT-configuration in `src\main\resources\application.yml` + - Check logger configuration in `ipos.project.CustomLoggingFilter` + - Returning `FilterReply.DENY` prevents messages from being logged, `FilterReply.ACCEPT` allows them to be logged + - Logging all messages with relevance for this extension requires accepting all messages that contain the string `OP:` + - Check that the *modules*-submodule has been checked out properly + - folder `models` should not be empty + - if empty, try to clone the repository together with checking out all submodules + - `git clone -b SimpleScene --recurse-submodules https://git-st.inf.tu-dresden.de/ipos/project.git project4` + - additionally: `git status` in folder `models` should return `Head detached`. To fix that: `git checkout main` + - Make sure that an instance of the [frontend-app](https://git-st.inf.tu-dresden.de/ipos/front-end-app) is running and accessible by the IPos-FW + - Remark: This is not necessary if you only want to debug the IPos-FW or examine its logging messages +2. Launch IPos-FW + - main-function: `ipos.project.MainApp.main` + - Console should print an overview of the available comments (if CustomLoggingFilter accepts messages containing string `SHELL:`) + - Console can be made to reprint the overview by entering `help` +3. Enter `init op` + - Initializes both, IPos-FW and OrderPicker extension + - OrderPicker extension sends MonitoringRequest to IPos-FW that causes it to send *Position-Updates* to the OrderPicker that cover all zones relevant for the verification of order-picking +4. Enter `oppl testdata` + - Reads a test-picklist contained in JSON-file `testdata_raw_orderpicker.txt` + - The logger should print the sequence of zones the picker is expected to visit +5. Enter `opevts testdata` + - Reads the JSON-file `testdata_raw_orderpicker_posEvts.txt` containing a sequence of test-messages indicating to the *OrderPicker extension* the presence of the picker in certain zones + - The OrderPicker verifies whether the picker follows the expected sequence. + - The *OrderPicker extension* informs the frontend-app about certain events by sending appropriate messages: + - Picker entered a zone in order + - Picker entered a zone out of order + - The behaviour of the *OrderPicker extension* can be verified by inspecting the (exhaustive) logger-output + - Messages sent are sent to the frontend-app are logged + - Events that have occured but are not indicated to the frontend-app are logged + +## Selected positions in source-code +### Execution of the SHELL-commands +- function `ipos.project.MainApp.processCommands` +### Initialization of the *OrderPicker extension* +- starting point: function `ipos.project.MainApp.initOp` +- The MonitoringReqeuest is prepared: function `ipos.project.iposextension.orderpicker.OFBizOrderPickerExt.prepareConfigWrapper` +### Information on the extension-mechanism of the IPos-FW +- see documentation of function `ipos.project.iposextension.orderpicker.OFBizOrderPicker.initialize` +### Information on the general behaviour of the `OrderPicker extension` +- see documentation of class `ipos.project.iposextension.orderpicker.OFBizOrderPicker` +### Testdata processing +- picklist testdata: function `ipos.project.iposextension.orderpicker.OFBizOrderPicker.processPicklistTestData` +- position testdata: function `ipos.project.iposextension.orderpicker.OFBizOrderPicker.processPosEvtTestData` +### Picklist-handling +- function: `ipos.project.iposextension.orderpicker.OFBizOrderPicker.handlePicklist` +- filter-behaviour: see documentation of function `ipos.project.iposextension.orderpicker.OFBizOrderPickerExt.setupECARule` +### Handling a PositionEvent sent from IPos-FW +- function: `ipos.project.iposextension.orderpicker.OFBizOrderPickerExt.handlePositionEvent(ipos.project.DataModellntegration.iPos_Datamodel.IPosDevKit.IposPositionEvent, ipos.project.devkit.iposext.IPosArguments.HandlePosEventConf)` +- overall behaviour of each ECA-rule: `ipos.project.devkit.eca.ECARule.apply` \ No newline at end of file