diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml
index ba9568a..c683433 100644
--- a/nbproject/build-impl.xml
+++ b/nbproject/build-impl.xml
@@ -1092,6 +1092,15 @@ is divided into following sections:
+
+
+
+
+
+
+
+
+
@@ -1762,6 +1771,15 @@ is divided into following sections:
+
+
+
+
+
+
+
+
+
diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties
index 1b14c9d..719dd4d 100644
--- a/nbproject/genfiles.properties
+++ b/nbproject/genfiles.properties
@@ -3,6 +3,6 @@ build.xml.script.CRC32=da12c040
build.xml.stylesheet.CRC32=f85dc8f2@1.94.0.48
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=390183ca
-nbproject/build-impl.xml.script.CRC32=64165c0f
+nbproject/build-impl.xml.data.CRC32=97e0c359
+nbproject/build-impl.xml.script.CRC32=a31f424b
nbproject/build-impl.xml.stylesheet.CRC32=f89f7d21@1.94.0.48
diff --git a/nbproject/project.properties b/nbproject/project.properties
index 4655c91..d3f5276 100644
--- a/nbproject/project.properties
+++ b/nbproject/project.properties
@@ -41,7 +41,8 @@ includes=**
jar.compress=false
javac.classpath=\
${file.reference.jlibmodbus-1.2.9.7.jar}:\
- ${file.reference.etherip.jar}
+ ${file.reference.etherip.jar}:\
+ ${reference.EIPGetAttr.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
@@ -82,7 +83,9 @@ manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
mkdist.disabled=false
platform.active=default_platform
+project.EIPGetAttr=../MinimalCIPJ
project.license=apache20
+reference.EIPGetAttr.jar=${project.EIPGetAttr}/dist/MinimalCIPJ.jar
run.classpath=\
${javac.classpath}:\
${build.classes.dir}
diff --git a/nbproject/project.xml b/nbproject/project.xml
index 285c269..1781714 100644
--- a/nbproject/project.xml
+++ b/nbproject/project.xml
@@ -14,6 +14,15 @@
.\lib\nblibraries.properties
-
+
+
+ EIPGetAttr
+ jar
+
+ jar
+ clean
+ jar
+
+
diff --git a/src/protocolwhisperer/BridgeManager.java b/src/protocolwhisperer/BridgeManager.java
index 8772d6a..d79d958 100644
--- a/src/protocolwhisperer/BridgeManager.java
+++ b/src/protocolwhisperer/BridgeManager.java
@@ -56,6 +56,7 @@ public BridgeManager(boolean aHeadless, String fileName)
headless = aHeadless;
driverList.add(new ModbusProtocolDriver());
driverList.add(new CIPProtocolDriver());
+ driverList.add(new DriveParameterProtocolDriver());
driverList.add(new StaticTagProtocolDriver());
loadDrivers();
loadDatalogDrivers();
diff --git a/src/protocolwhisperer/drivers/DriveParameterConfigFrame.form b/src/protocolwhisperer/drivers/DriveParameterConfigFrame.form
new file mode 100644
index 0000000..bf9226b
--- /dev/null
+++ b/src/protocolwhisperer/drivers/DriveParameterConfigFrame.form
@@ -0,0 +1,168 @@
+
+
+
diff --git a/src/protocolwhisperer/drivers/DriveParameterConfigFrame.java b/src/protocolwhisperer/drivers/DriveParameterConfigFrame.java
new file mode 100644
index 0000000..72604d7
--- /dev/null
+++ b/src/protocolwhisperer/drivers/DriveParameterConfigFrame.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2021 Matt Jamesson .
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package protocolwhisperer.drivers;
+
+import javax.swing.*;
+import java.util.*;
+import java.awt.event.*;
+import static protocolwhisperer.drivers.ModbusConfigFrame.dataTypeMenuNames;
+import protocolwhisperer.*;
+
+/**
+ *
+ * @author Matt Jamesson
+ */
+public class DriveParameterConfigFrame extends javax.swing.JFrame {
+
+ /**
+ * Creates new form CIPConfigFrame
+ */
+ DriveParameterProtocolRecord currentRecord = null;
+ ArrayList tagGuiRecords = new ArrayList();
+ BridgeManager manager = null;
+ public DriveParameterConfigFrame(DriveParameterProtocolRecord aCurrentRecord, BridgeManager aManager) {
+ initComponents();
+ currentRecord = aCurrentRecord;
+ manager = aManager;
+ if (currentRecord.configured)
+ {
+ cipHostField.setText(currentRecord.host);
+ buildTagRecords(currentRecord.tagRecords);
+ }
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // //GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ topPane = new javax.swing.JPanel();
+ configPane = new javax.swing.JPanel();
+ jLabel1 = new javax.swing.JLabel();
+ cipHostField = new javax.swing.JTextField();
+ addTagPane = new javax.swing.JPanel();
+ addTagButton = new javax.swing.JButton();
+ headerPane = new javax.swing.JPanel();
+ jLabel2 = new javax.swing.JLabel();
+ filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(70, 0), new java.awt.Dimension(70, 0), new java.awt.Dimension(70, 32767));
+ jLabel4 = new javax.swing.JLabel();
+ filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(70, 0), new java.awt.Dimension(70, 0), new java.awt.Dimension(70, 32767));
+ jScrollPane1 = new javax.swing.JScrollPane();
+ tagRecordParent = new javax.swing.JPanel();
+ tagRecordPane = new javax.swing.JPanel();
+ okPane = new javax.swing.JPanel();
+ okButton = new javax.swing.JButton();
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+
+ topPane.setLayout(new javax.swing.BoxLayout(topPane, javax.swing.BoxLayout.Y_AXIS));
+
+ jLabel1.setText("Drive IP:");
+ configPane.add(jLabel1);
+
+ cipHostField.setColumns(10);
+ configPane.add(cipHostField);
+
+ topPane.add(configPane);
+
+ addTagButton.setText("Add tag");
+ addTagButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ addTagButtonActionPerformed(evt);
+ }
+ });
+ addTagPane.add(addTagButton);
+
+ topPane.add(addTagPane);
+
+ jLabel2.setText("Tag");
+ headerPane.add(jLabel2);
+ headerPane.add(filler1);
+
+ jLabel4.setText("Parameter");
+ headerPane.add(jLabel4);
+ headerPane.add(filler2);
+
+ topPane.add(headerPane);
+
+ getContentPane().add(topPane, java.awt.BorderLayout.NORTH);
+
+ tagRecordParent.setLayout(new java.awt.BorderLayout());
+
+ tagRecordPane.setLayout(new javax.swing.BoxLayout(tagRecordPane, javax.swing.BoxLayout.Y_AXIS));
+ tagRecordParent.add(tagRecordPane, java.awt.BorderLayout.NORTH);
+
+ jScrollPane1.setViewportView(tagRecordParent);
+
+ getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
+
+ okButton.setText("OK");
+ okButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ okButtonActionPerformed(evt);
+ }
+ });
+ okPane.add(okButton);
+
+ getContentPane().add(okPane, java.awt.BorderLayout.SOUTH);
+
+ setBounds(0, 0, 332, 268);
+ }// //GEN-END:initComponents
+
+ private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
+ currentRecord.host = cipHostField.getText();
+ currentRecord.configured = true;
+ mapTagRecords();
+ dispose();
+ }//GEN-LAST:event_okButtonActionPerformed
+
+ private void addTagButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addTagButtonActionPerformed
+ DriveParameterTagRecord tagRecord = new DriveParameterTagRecord();
+ currentRecord.tagRecords.add(tagRecord);
+ buildTagRecord(tagRecord);
+ revalidate();
+ repaint();
+ }//GEN-LAST:event_addTagButtonActionPerformed
+
+ public void mapTagRecords()
+ {
+ currentRecord.tagRecords.clear();
+ for (int i = 0; i < tagGuiRecords.size(); i++)
+ {
+ currentRecord.tagRecords.add(tagGuiRecords.get(i).mapTagRecord());
+ }
+ }
+ public void buildTagRecords(ArrayList tagRecords)
+ {
+ for (int i = 0; i < tagRecords.size(); i++)
+ {
+ DriveParameterTagRecord currentRecord = (DriveParameterTagRecord)tagRecords.get(i);
+ buildTagRecord(currentRecord);
+ }
+ }
+ public void buildTagRecord(DriveParameterTagRecord currentTagRecord)
+ {
+ JPanel currentTagPane = new JPanel();
+ java.awt.Component tagField;
+ if (currentRecord.type == ProtocolRecord.RECORD_TYPE_INCOMING)
+ {
+ tagField = new JTextField(10);
+ if (currentTagRecord.configured)
+ {
+ ((JTextField)tagField).setText(currentTagRecord.tag);
+ }
+ }
+ else
+ {
+ if (currentTagRecord.configured)
+ {
+ tagField = manager.getOutgoingRecordTags(currentTagRecord.tag);
+ }
+ else
+ {
+ tagField = manager.getOutgoingRecordTags("");
+ }
+ }
+ JTextField parameterField = new JTextField(3);
+ currentTagPane.add(tagField);
+ currentTagPane.add(parameterField);
+ JButton deleteButton = new JButton("Delete");
+ currentTagPane.add(deleteButton);
+ if (currentTagRecord.configured)
+ {
+ parameterField.setText(currentTagRecord.parameter + "");
+ }
+ tagRecordPane.add(currentTagPane);
+ TagMapper tm = new TagMapper()
+ {
+ public DriveParameterTagRecord mapTagRecord()
+ {
+ DriveParameterTagRecord outputRecord = new DriveParameterTagRecord();
+ if (currentRecord.type == ProtocolRecord.RECORD_TYPE_INCOMING)
+ {
+ outputRecord.tag = ((JTextField)tagField).getText();
+ }
+ else
+ {
+ outputRecord.tag = ((JComboBox)tagField).getSelectedItem().toString();
+ }
+ outputRecord.parameter = Integer.parseInt(parameterField.getText());
+ outputRecord.configured = true;
+ return outputRecord;
+ }
+ };
+ tagGuiRecords.add(tm);
+ deleteButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e)
+ {
+ tagGuiRecords.remove(tm);
+ tagRecordPane.remove(currentTagPane);
+ revalidate();
+ repaint();
+
+ }});
+ }
+
+ /**
+ * @param args the command line arguments
+ */
+
+ public interface TagMapper
+ {
+ public DriveParameterTagRecord mapTagRecord();
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton addTagButton;
+ private javax.swing.JPanel addTagPane;
+ private javax.swing.JTextField cipHostField;
+ private javax.swing.JPanel configPane;
+ private javax.swing.Box.Filler filler1;
+ private javax.swing.Box.Filler filler2;
+ private javax.swing.JPanel headerPane;
+ private javax.swing.JLabel jLabel1;
+ private javax.swing.JLabel jLabel2;
+ private javax.swing.JLabel jLabel4;
+ private javax.swing.JScrollPane jScrollPane1;
+ private javax.swing.JButton okButton;
+ private javax.swing.JPanel okPane;
+ private javax.swing.JPanel tagRecordPane;
+ private javax.swing.JPanel tagRecordParent;
+ private javax.swing.JPanel topPane;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/src/protocolwhisperer/drivers/DriveParameterProtocolDriver.java b/src/protocolwhisperer/drivers/DriveParameterProtocolDriver.java
new file mode 100644
index 0000000..86ec8cb
--- /dev/null
+++ b/src/protocolwhisperer/drivers/DriveParameterProtocolDriver.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2020 Matt Jamesson .
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package protocolwhisperer.drivers;
+
+import minimalcipj.DPIOnlineReadFullResponse;
+import minimalcipj.CIPResponse;
+import minimalcipj.CIPDataFormatter;
+import minimalcipj.CIPClient;
+import etherip.EtherNetIP;
+import etherip.types.CIPData;
+import java.util.ArrayList;
+import java.util.Arrays;
+import protocolwhisperer.*;
+
+/**
+ *
+ * @author Matt Jamesson
+ */
+public class DriveParameterProtocolDriver extends ProtocolDriver{
+ boolean enabled = true;
+
+ public void setEnabled(boolean aEnabled)
+ {
+ enabled = aEnabled;
+ }
+ public boolean getEnabled()
+ {
+ return enabled;
+ }
+
+ public void ParameterRead(DriveParameterProtocolRecord currentRecord)
+ {
+ CIPClient client = null;
+ try
+ {
+ client = new CIPClient(currentRecord.host);
+ client.connect();
+ for (int i = 0; i < currentRecord.tagRecords.size(); i++)
+ {
+ DriveParameterTagRecord currentTagRecord = ((DriveParameterTagRecord)currentRecord.tagRecords.get(i));
+ double oldValue = currentTagRecord.getValue();
+ CIPResponse response = client.getAttribute(0x93, currentTagRecord.parameter, 0x07);
+ if (response instanceof DPIOnlineReadFullResponse)
+ {
+ CIPDataFormatter formatter = ((DPIOnlineReadFullResponse)(response)).getCIPDataFormatter();
+ currentTagRecord.setValue(formatter.getDisplayVal(((DPIOnlineReadFullResponse)(response)).getParamValue()));
+ }
+ if (oldValue != currentTagRecord.getValue())
+ {
+ currentTagRecord.lastChangedTime = System.currentTimeMillis();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (ProtocolWhisperer.debug)
+ {
+ e.printStackTrace();
+ }
+ }
+ try
+ {
+ client.disconnect();
+ }
+ catch (java.io.IOException e)
+ {
+ if (ProtocolWhisperer.debug)
+ {
+ e.printStackTrace();
+ }
+ }
+ }
+ public void storeProtocolRecord(ProtocolRecord pr)
+ {
+ recordList.add(pr);
+ }
+ public void getIncomingRecords()
+ {
+ for (int i = 0; i < recordList.size(); i++)
+ {
+ DriveParameterProtocolRecord currentRecord = (DriveParameterProtocolRecord)recordList.get(i);
+ if (currentRecord.getType() == ProtocolRecord.RECORD_TYPE_INCOMING)
+ {
+ ParameterRead(currentRecord);
+ }
+ }
+ }
+ public void mapIncomingValues()
+ {
+ }
+
+ public void sendOutgoingRecords()
+ {
+
+ }
+ public Class getProtocolHandlerClass()
+ {
+ return DriveParameterProtocolHandler.class;
+ }
+ public Class getProtocolRecordClass()
+ {
+ return DriveParameterProtocolRecord.class;
+ }
+}
diff --git a/src/protocolwhisperer/drivers/DriveParameterProtocolHandler.java b/src/protocolwhisperer/drivers/DriveParameterProtocolHandler.java
new file mode 100644
index 0000000..d8b55e7
--- /dev/null
+++ b/src/protocolwhisperer/drivers/DriveParameterProtocolHandler.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 Matt Jamesson .
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package protocolwhisperer.drivers;
+import protocolwhisperer.*;
+import javax.swing.*;
+import java.awt.event.*;
+import java.util.ArrayList;
+
+/**
+ *
+ * @author Matt Jamesson
+ */
+public class DriveParameterProtocolHandler implements ProtocolHandler{
+ String[] incomingMenuNames = new String[] {"CIP Read Drive Parameter"};
+ String[] outgoingMenuNames = new String[] {};
+
+ public ProtocolRecord getNewProtocolRecord(int type, String calledMenuItem)
+ {
+ return new DriveParameterProtocolRecord(type, calledMenuItem);
+ }
+ public String[] getIncomingMenuNames()
+ {
+ return incomingMenuNames;
+ }
+ public String[] getOutgoingMenuNames()
+ {
+ return outgoingMenuNames;
+ }
+ public void configure(ProtocolRecord currentRecord, BridgeManager manager)
+ {
+ new DriveParameterConfigFrame((DriveParameterProtocolRecord)currentRecord, manager).setVisible(true);
+ }
+}
diff --git a/src/protocolwhisperer/drivers/DriveParameterProtocolRecord.java b/src/protocolwhisperer/drivers/DriveParameterProtocolRecord.java
new file mode 100644
index 0000000..e326d04
--- /dev/null
+++ b/src/protocolwhisperer/drivers/DriveParameterProtocolRecord.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 Matt Jamesson .
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package protocolwhisperer.drivers;
+
+/**
+ *
+ * @author Matt Jamesson
+ */
+public class DriveParameterProtocolRecord extends ProtocolRecord {
+ public static int PROTOCOL_TYPE_GETATTR = 1;
+ public static int PROTOCOL_TYPE_SETATTR = 2;
+ public String host = null;
+ public Class protocolHandler = DriveParameterProtocolHandler.class;
+ public DriveParameterProtocolRecord()
+ {
+
+ }
+ public Class getProtocolHandlerClass()
+ {
+ return protocolHandler;
+ }
+ public DriveParameterProtocolRecord(int aType, String calledMenuItem)
+ {
+ selectedItem = calledMenuItem;
+ type = aType;
+ }
+
+}
diff --git a/src/protocolwhisperer/drivers/DriveParameterTagRecord.java b/src/protocolwhisperer/drivers/DriveParameterTagRecord.java
new file mode 100644
index 0000000..333b6eb
--- /dev/null
+++ b/src/protocolwhisperer/drivers/DriveParameterTagRecord.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2021 Matt Jamesson .
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package protocolwhisperer.drivers;
+
+/**
+ *
+ * @author Matt Jamesson
+ */
+public class DriveParameterTagRecord extends TagRecord {
+ public int parameter = 0;
+ double value = 0;
+ public void setValue(double aValue)
+ {
+ value = aValue;
+ }
+ public double getValue()
+ {
+ return value;
+ }
+}