From 73251fdb47b0ed4b2a030e88f1676b9a0d4c71e4 Mon Sep 17 00:00:00 2001 From: alexandro-rezakhani <85354050+alexandro-rezakhani@users.noreply.github.com> Date: Mon, 24 Mar 2025 04:59:03 -0400 Subject: [PATCH 1/8] 1st attempt --- CSK_Module_Fieldbus/project.mf.xml | 165 +++++++------- .../scripts/CSK_Module_Fieldbus.lua | 24 +- .../Fieldbus/Fieldbus_Controller.lua | 11 + .../Communication/Fieldbus/Fieldbus_Model.lua | 214 +++++++++++++++++- .../FlowConfig/Fieldbus_FlowConfig.lua | 31 +++ .../Fieldbus/helper/checkAPIs.lua | 14 +- 6 files changed, 362 insertions(+), 97 deletions(-) create mode 100644 CSK_Module_Fieldbus/scripts/Communication/Fieldbus/FlowConfig/Fieldbus_FlowConfig.lua diff --git a/CSK_Module_Fieldbus/project.mf.xml b/CSK_Module_Fieldbus/project.mf.xml index 8c5cdf2..0ecaa3f 100644 --- a/CSK_Module_Fieldbus/project.mf.xml +++ b/CSK_Module_Fieldbus/project.mf.xml @@ -1,79 +1,86 @@ - - - - - This is an automatically generated CROWN (description not necessary). - - - released - Please fill in information regarding: What is the idea of this module and its features? + -How to use this module in general.... like: + -{empty} + -Typically the features of this module are used like this (check also main script of this module): + -**1) Setup** + -ToDo + -{empty} + -**2) Something else...** + - - - - Notify status if parameters should be loaded on app/device boot up. - - - - Notify status if features of CSK_PersistendData module are available. - - - - Event to call if module tried to load parameters and should be ready. - - - Notify name of persistent data parameter. - - - - Status of Operator userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Status of Maintenance userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Status of Service userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Status of Admin userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Function to set the name of the parameters if saved/loaded via the CSK_PersistentData module. - - - - Send parameters to CSK_PersistentData module if possible to save them. - - - Load parameters for this module from the CSK_PersistentData module if possible and use them. - - - Configure if this module should load its saved parameters at app/device boot up. - - - - Function to register "OnResume" of the module UI (only as helper function). - - - - - SICK AG - 0.1.0 - low - false - false - false - true - - - + + + + + This is an automatically generated CROWN (description not necessary). + + + released + Please fill in information regarding: What is the idea of this module and its features? + +How to use this module in general.... like: + +{empty} + +Typically the features of this module are used like this (check also main script of this module): + +**1) Setup** + +ToDo + +{empty} + +**2) Something else...** + + + + + Notify status if parameters should be loaded on app/device boot up. + + + + Notify status if features of CSK_PersistendData module are available. + + + + Event to call if module tried to load parameters and should be ready. + + + Notify name of persistent data parameter. + + + + Status of Operator userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Status of Maintenance userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Status of Service userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Status of Admin userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Notify UI style to use for CSK modules. + + + + Function to set the name of the parameters if saved/loaded via the CSK_PersistentData module. + + + + Send parameters to CSK_PersistentData module if possible to save them. + + + Load parameters for this module from the CSK_PersistentData module if possible and use them. + + + Configure if this module should load its saved parameters at app/device boot up. + + + + Function to register "OnResume" of the module UI (only as helper function). + + + + Function to clear FlowConfig relevant configurations. + + + + SICK AG + 0.1.0 + low + false + false + false + true + + + diff --git a/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua b/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua index ff8b407..e24c781 100644 --- a/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua +++ b/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua @@ -21,15 +21,14 @@ --SOFTWARE. ---@diagnostic disable: undefined-global, redundant-parameter, missing-parameter --- CreationTemplateVersion: 3.6.0 + --************************************************************************** --**********************Start Global Scope ********************************* --************************************************************************** -- If app property "LuaLoadAllEngineAPI" is FALSE, use this to load and check for required APIs -- This can improve performance of garbage collection - ---_G.availableAPIs = require('Communication/Fieldbus/helper/checkAPIs') -- can be used to adjust function scope of the module related on available APIs of the device +_G.availableAPIs = require('Communication/Fieldbus/helper/checkAPIs') -- can be used to adjust function scope of the module related on available APIs of the device ----------------------------------------------------------- -- Logger _G.logger = Log.SharedLogger.create('ModuleLogger') @@ -42,7 +41,22 @@ _G.logHandle:applyConfig() -- Loading script regarding Fieldbus_Model -- Check this script regarding Fieldbus_Model parameters and functions -_G.fieldbus_Model = require('Communication/Fieldbus/Fieldbus_Model') +_G.fieldbus_Model = require('Communication/Fieldbus/Fieldbus_Model') --AR - sometimes this is local scope ie MultiTCPIPServer? + +local fieldbus_Instances = {} -- Handle all instances + +-- Load script to communicate with the fieldbus_Model UI +-- Check / edit this script to see/edit functions which communicate with the UI +local fieldbusController = require('Communication/Fieldbus/Fieldbus_Controller') + +if _G.availableAPIs.default and _G.availableAPIs.specific then + local setInstanceHandle = require('Communication/Fieldbus/FlowConfig/Fieldbus_FlowConfig') + table.insert(fieldbus_Instances, fieldbus_Model.create(1)) --AR -- Create at least 1 instance + fieldbusController.setFieldbus_Instances_Handle(fieldbus_Instances) -- share handle of instances + setInstanceHandle(fieldbus_Instances) +else + _G.logger:warning("CSK_Fieldbus: Relevant CROWN(s) not available on device. Module is not supported...") +end --************************************************************************** --**********************End Global Scope *********************************** @@ -64,6 +78,8 @@ local function main() -- _G.fieldbus_Model.doSomething() -- if you want to start a function -- ... + fieldbusController.setFieldbus_Model_Handle(Fieldbus_Model) + CSK_Fieldbus.pageCalled() -- Update UI end diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua index 4092e0e..6b72d52 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua @@ -21,6 +21,8 @@ local fieldbus_Model -- ************************ UI Events Start ******************************** -- Script.serveEvent("CSK_Fieldbus.OnNewEvent", "Fieldbus_OnNewEvent") + +Script.serveEvent('CSK_Fieldbus.OnNewStatusCSKStyle', 'Fieldbus_OnNewStatusCSKStyle') Script.serveEvent("CSK_Fieldbus.OnNewStatusLoadParameterOnReboot", "Fieldbus_OnNewStatusLoadParameterOnReboot") Script.serveEvent("CSK_Fieldbus.OnPersistentDataModuleAvailable", "Fieldbus_OnPersistentDataModuleAvailable") Script.serveEvent("CSK_Fieldbus.OnNewParameterName", "Fieldbus_OnNewParameterName") @@ -126,6 +128,15 @@ local function pageCalled() end Script.serveFunction("CSK_Fieldbus.pageCalled", pageCalled) +local function clearFlowConfigRelevantConfiguration() + for i = 1, #fieldbus_Instances do + Script.notifyEvent('Fieldbus_OnNewProcessingParameter', selectedInstance, 'clearAll') + fieldbus_Instances[selectedInstance].parameters.clientBroadcasts.forwardEvents = {} + fieldbus_Instances[selectedInstance].parameters.forwardEvents = {} + end +end +Script.serveFunction('CSK_Fieldbus.clearFlowConfigRelevantConfiguration', clearFlowConfigRelevantConfiguration) + --[[ local function setSomething(value) _G.logger:info(nameOfModule .. ": Set new value = " .. value) diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua index a9886c7..8d7da81 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua @@ -31,23 +31,47 @@ setFieldbus_ModelHandle(fieldbus_Model) --Loading helper functions if needed fieldbus_Model.helperFuncs = require('Communication/Fieldbus/helper/funcs') +-- Create parameters / instances for this module +fieldbus_Model.isConnected = false +fieldbus_Model.reconnectionTimer = Timer.create() +fieldbus_Model.reconnectionTimer:setExpirationTime(5000) +fieldbus_Model.reconnectionTimer:setPeriodic(false) +fieldbus_Model.mode = 'RAW' + -- Optionally check if specific API was loaded via ---[[ -if _G.availableAPIs.specific then --- ... doSomething ... +if _G.availableAPIs.specific == true then + if (fieldbus_Model.mode == 'RAW' ) then + fieldbus_Model.fieldbus = FieldBus.create('EXPLICIT_OPEN') + fieldbus_Model.fieldbus:setMode('RAW') + fieldbus_Model.fieldbus:open() + end end -]] ---[[ --- Create parameters / instances for this module -fieldbus_Model.object = Image.create() -- Use any AppEngine CROWN -fieldbus_Model.counter = 1 -- Short docu of variable -fieldbus_Model.varA = 'value' -- Short docu of variable ---... -]] +fieldbus_Model.key = '1234567890123456' -- key to encrypt passwords, should be adapted! + +fieldbus_Model.messageLog = {} -- keep the latest 100 received messages + +fieldbus_Model.styleForUI = 'None' -- Optional parameter to set UI style +fieldbus_Model.version = Engine.getCurrentAppVersion() -- Version of module -- Parameters to be saved permanently if wanted fieldbus_Model.parameters = {} +fieldbus_Model.parameters.flowConfigPriority = CSK_FlowConfig ~= nil or false -- Status if FlowConfig should have priority for FlowConfig relevant configurations + +fieldbus_Model.parameters.connect = true -- Config if connection should be active +fieldbus_Model.parameters.fieldbusIP = '136.129.5.1' -- IP of the MQTT broker +fieldbus_Model.parameters.connectionTimeout = 5000 -- The timeout to wait initially until the client gets + + +-- List of events to register to and forward content to PLC +fieldbus_Model.parameters.forwardEvents = {} + +fieldbus_Model.parameters.useCredentials = true -- Enables/disables to use user credentials +fieldbus_Model.parameters.username = 'user' -- Username if using user credentials +if _G.availableAPIs.specific == true then + fieldbus_Model.parameters.password = Cipher.AES.encrypt('password', fieldbus_Model.key) -- Password if using user credentials +end + --fieldbus_Model.parameters.paramA = 'paramA' -- Short docu of variable --fieldbus_Model.parameters.paramB = 123 -- Short docu of variable --... @@ -68,6 +92,174 @@ end fieldbus_Model.doSomething = doSomething ]] +--- Function to react on UI style change +local function handleOnStyleChanged(theme) + fieldbus_Model.styleForUI = theme + Script.notifyEvent("Fieldbus_OnNewStatusCSKStyle", fieldbus_Model.styleForUI) +end +Script.register('CSK_PersistentData.OnNewStatusCSKStyle', handleOnStyleChanged) + + +--- Function to create and notify internal Fieldbus log messages +local function sendLog() + local tempLog2Send = '' + for i=#fieldbus_Model.messageLog, 1, -1 do + tempLog2Send = tempLog2Send .. fieldbus_Model.messageLog[i] .. '\n' + end + Script.notifyEvent('Fieldbus_OnNewLog', tempLog2Send) +end +fieldbus_Model.sendLog = sendLog + +--- Function to add new message to internal Fieldbus log messages +---@param msg string Message +local function addMessageLog(msg) + table.insert(fieldbus_Model.messageLog, 1, DateTime.getTime() .. ': ' .. msg) + if #fieldbus_Model.messageLog == 100 then + table.remove(fieldbus_Model.messageLog, 100) + end + sendLog() +end +fieldbus_Model.addMessageLog = addMessageLog + +--@setEthIP_Out(bit:int, value:Bool) +local function setEthIP_Out(bit, value) + if bit < 16 and bit >= 0 then + local bitWrite = 0 + if value then + bitWrite = 65535 + end + local bitMask = 2 ^ bit + FieldBus.writeControlBitsIn(fieldbus_Model.fieldbus, bitWrite, bitMask) + else + print("Warning: invalid bit chosen, doesn't exit") + end + + local function toBits(num, bits) + -- returns a table of bits, least significant first. + local t={} -- will contain the bits + bits = bits or 8 + local rest + while num > 0 do + rest = math.fmod(num,2) + t[#t+1] = rest + num = math.floor((num - rest) / 2) + end + for i = #t + 1, bits do -- fill empty bits with 0 + t[i] = 0 + end + return t + end + + local tempFieldBusBitsIn = FieldBus.readControlBitsIn(fieldbus_Model.fieldbus) + local bitTable = toBits(tempFieldBusBitsIn, 16) + for i = 1, #bitTable//2, 1 do + bitTable[i], bitTable[#bitTable - i + 1] = bitTable[#bitTable - i + 1], bitTable[i] + end + local reversedBTable = table.concat(bitTable) --[AR] + Script.notifyEvent("GuiUpdateCtrlBitOutput", bitTable) + _g_log('FINER', "setEthIP_Out: Bit ".. bit .. tostring(value) .."Value" .. DateTime.getDateTime(), '000') + +end + +--@newControlBitsOut(value:int) +local function newControlBitsOut(value) + _g_log('FINER', "Control bits in from PLC: " .. value .. DateTime.getDateTime(), '000') + for i = 0, 15 do + if value >= 2 ^ (15 - i) then + value = value - (2 ^ (15 - i)) + + if not ethIP_InBits[16 - i] and #ethIP_In_FunUP >= (16 - i) then + Script.notifyEvent(ethIP_In_FunUP[16 - i]) + end + + ethIP_InBits[16 - i] = true + else + if ethIP_InBits[16 - i] and #ethIP_In_FunDOWN >= (16 - i) then + Script.notifyEvent(ethIP_In_FunDOWN[16 - i]) + end + + ethIP_InBits[16 - i] = false + end + end + --local ctrlBitOutStr = string.format("%02X %02X", value&0x00FF, value>>8) + --print ("Ctrl.Bits from PLC: " .. ctrlBitOutStr) + local bitTable = FieldBusSettings.toBits(value, 16) + local reversedBTable = table.concat(FieldBusSettings.reverse(bitTable)) + Script.notifyEvent("GuiUpdateCtrlBitInput", reversedBTable) +end +--This event is thrown when the control bits set by the PLC have changed. +if _G.availableAPIs.default and _G.availableAPIs.specific == true then + FieldBus.register(fieldbus_Model.fieldbus, 'OnControlBitsOutChanged', newControlBitsOut) +end + +--- +---@param ctrlBits int Control bits set by the PLC have changed +local function handleOnControlBitsOutChanged(ctrlBits) + -- TODO: Insert your event handling code here. +end +--This event is thrown when the control bits set by the PLC have changed. +if _G.availableAPIs.default and _G.availableAPIs.specific == true then + FieldBus.register(fieldbus_Model.fieldbus, 'OnControlBitsOutChanged', handleOnControlBitsOutChanged) +end + +--- +---@param size int New size of the fieldbus input frame buffer. +local function handleOnInputSizeChanged(size) + -- TODO: Insert your event handling code here. +end +--This event is thrown when the size of the FieldBus input frame buffer changes. +if _G.availableAPIs.default and _G.availableAPIs.specific == true then + FieldBus.register(fieldbus_Model.fieldbus, 'OnInputSizeChanged', handleOnInputSizeChanged) +end + +--- +---@param data binary New data from the PLC +local function handleOnNewData(data) + local message = {string.unpack(FieldBusSettings.inputFormat, data)} + Script.notifyEvent('incomingData', message) + local datahex = FieldBusSettings.hexDumpBinData(data) + Script.notifyEvent('GuiUpdateDataInPut', datahex) + print (data) + print (datahex) +end +--This event is thrown when new data has been received from the PLC through the field bus. +if _G.availableAPIs.default and _G.availableAPIs.specific == true then + FieldBus.register(fieldbus_Model.fieldbus, 'OnNewData', handleOnNewData) +end + +--- +---@param size int New size of the fieldbus output frame buffer. +local function handleOnOutputSizeChanged(size) + -- TODO: Insert your event handling code here. +end +--This event is thrown when the control bits set by the PLC have changed. +if _G.availableAPIs.default and _G.availableAPIs.specific == true then + FieldBus.register(fieldbus_Model.fieldbus, 'OnOutputSizeChanged', handleOnOutputSizeChanged) +end + +--- +---@param status FieldBus.Status New state of the fieldbus communication. +local function handleOnStatusChanged(status) + _G.logger:info("FieldBus: OnStatusChanged event received, new status: " .. status) + Script.notifyEvent("onStatusChange", status) + if (status== "ONLINE") then + _G.logger:info(nameOfModule .. ": Connected to PLC.") + Script.notifyEvent('FieldBus_OnNewConnectionStatus', "Connected to PLC") + addMessageLog('Connected to PLC.') + fieldbus_Model.reconnectionTimer:stop() + fieldbus_Model.isConnected = true + Script.notifyEvent("FieldBus_OnNewStatusCurrentlyConnected", fieldbus_Model.isConnected) + elseif (status== "OFFLINE") then + fieldbus_Model.isConnected = false + end + setEthIP_Out(0, fieldbus_Model.isConnected) +end +--This event is thrown when the state of the FieldBus communication changes. +if _G.availableAPIs.default and _G.availableAPIs.specific == true then + FieldBus.register(fieldbus_Model.fieldbus, "OnStatusChanged", handleOnStatusChanged) +end + + --************************************************************************* --********************** End Function Scope ******************************* --************************************************************************* diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/FlowConfig/Fieldbus_FlowConfig.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/FlowConfig/Fieldbus_FlowConfig.lua new file mode 100644 index 0000000..9de3c7d --- /dev/null +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/FlowConfig/Fieldbus_FlowConfig.lua @@ -0,0 +1,31 @@ +--***************************************************************** +-- Here you will find all the required content to provide specific +-- features of this module via the 'CSK FlowConfig'. +--***************************************************************** + +require('Communication.Fieldbus.FlowConfig.Fieldbus_OnNewData') +require('Communication.Fieldbus.FlowConfig.Fieldbus_Transmit') + +-- Reference to the fieldbus_Instances handle +local fieldbus_Instances + +--- Function to react if FlowConfig was updated +local function handleOnClearOldFlow() + if _G.availableAPIs.default and _G.availableAPIs.specific then + for i = 1, #fieldbus_Instances do + if fieldbus_Instances[i].parameters.flowConfigPriority then + CSK_Fieldbus.clearFlowConfigRelevantConfiguration() + break + end + end + end +end +Script.register('CSK_FlowConfig.OnClearOldFlow', handleOnClearOldFlow) + +--- Function to get access to the fieldbus_Instances +---@param handle handle Handle of fieldbus_Instances object +local function setFieldbus_Instances_Handle(handle) + fieldbus_Instances = handle +end + +return setFieldbus_Instances_Handle \ No newline at end of file diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua index 929c733..3b74bbc 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua @@ -6,9 +6,10 @@ local availableAPIs = {} local function loadAPIs() - CSK_ModuleName = require 'API.CSK_ModuleName' + CSK_Fieldbus = require 'API.CSK_Fieldbus' Container = require 'API.Container' + DateTime = require 'API.DateTime' Engine = require 'API.Engine' Log = require 'API.Log' Log.Handler = require 'API.Log.Handler' @@ -23,14 +24,21 @@ local function loadAPIs() CSK_PersistentData = require 'API.CSK_PersistentData' elseif appList[i] == 'CSK_Module_UserManagement' then CSK_UserManagement = require 'API.CSK_UserManagement' + elseif appList[i] == 'CSK_Module_FlowConfig' then + CSK_FlowConfig = require 'API.CSK_FlowConfig' end end end local function loadSpecificAPIs() -- If you want to check for specific APIs/functions supported on the device the module is running, place relevant APIs here - -- e.g.: - -- NTPClient = require 'API.NTPClient' + FieldBus = require(API.FieldBus) + Cipher = {} + Cipher.AES = require 'API.Cipher.AES' + math = require 'API.math' + Script = require 'API.Script' + string = require 'API.string' + table = require 'API.table' end availableAPIs.default = xpcall(loadAPIs, debug.traceback) -- TRUE if all default APIs were loaded correctly From e8b15e2baf7aa19e0c00484e4fd6b44ac58f7a1f Mon Sep 17 00:00:00 2001 From: alexandro-rezakhani <85354050+alexandro-rezakhani@users.noreply.github.com> Date: Mon, 24 Mar 2025 21:32:30 -0400 Subject: [PATCH 2/8] Update README.md --- README.md | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 3c9d355..0778b78 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,27 @@ # CSK_Module_Fieldbus -## INFO: Draft version. Not further developed / tested so far! Check for available GitHub forks of this repository to see latest updates. +Module to provide fieldbus communication functionality. -Module / Application to provide [...] functionality. - -*If available, please also add a screenshot/gif of the UI of the module here placed within /docu/media/ (see code)* -![](https://github.com/SICKAppSpaceCodingStarterKit/[REPO_OF_MODULE]/blob/main/docu/media/UI_Screenshot.png) +![](./docu/media/UI_Screenshot.png) ## How to Run -[***...please fill with informations...***] -For further information check out the [documentation](https://raw.githack.com/SICKAppSpaceCodingStarterKit/[REPO_OF_MODULE]/main/docu/CSK_Module_[MODULENAME].html) [update link] in the folder "docu". +The app includes an intuitive GUI to setup the fieldbus communication. +For further information check out the [documentation](https://raw.githack.com/golluroSICKAG/CSK_Module_Fieldbus/main/docu/CSK_Module_Fieldbus.html) in the folder "docu". ## Information Tested on: -[Device] - [firmware] -... - -[***optionally***] -Following CSK modules are used for this application via Git subtrees and should NOT be further developed within this repository (see [contribution guideline](https://github.com/SICKAppSpaceCodingStarterKit/.github/blob/main/Contribution_Guideline.md) of this GitHub organization): - - * CSK_Module_XYZ (release/tag v1.2.3) - -This application / module is part of the SICK AppSpace Coding Starter Kit developing approach. -It is programmed in an object oriented way. Some of the modules use kind of "classes" in Lua to make it possible to reuse code / classes in other projects. -In general it is not neccessary to code this way, but the architecture of this app can serve as a sample to be used especially for bigger projects and to make it easier to share code. +|Device|Firmware|Module version +|--|--|--| +|SIM 2x00|V1.5.0|V0.1.0| +|SIM 2x00|V1.7.0|V1.0.0| + +This module is part of the SICK AppSpace Coding Starter Kit developing approach. +It is programmed in an object-oriented way. Some of the modules use kind of "classes" in Lua to make it possible to reuse code / classes in other projects. +In general, it is not neccessary to code this way, but the architecture of this app can serve as a sample to be used especially for bigger projects and to make it easier to share code. Please check the [documentation](https://github.com/SICKAppSpaceCodingStarterKit/.github/blob/main/docu/SICKAppSpaceCodingStarterKit_Documentation.md) of CSK for further information. ## Topics -Coding Starter Kit, CSK, Module, SICK-AppSpace, [key_words] +Coding Starter Kit, CSK, Module, SICK-AppSpace, Fieldbus, Profinet, EtherCat, Ethernet/IP, PLC From 9a176d96f347fa47b1cd1f889c479df36cc872a3 Mon Sep 17 00:00:00 2001 From: alexandro-rezakhani <85354050+alexandro-rezakhani@users.noreply.github.com> Date: Mon, 24 Mar 2025 21:33:50 -0400 Subject: [PATCH 3/8] Update CHANGELOG.md --- CHANGELOG.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 449f8ea..5535416 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,8 @@ # Changelog All notable changes to this project will be documented in this file. +## Release 0.1.1 +- FieldBus.Config.EthernetIP setup + ## Release 0.1.0 - Initial commit - -### New features -- ... - -### Improvements -- ... - -### Bugfix -- ... \ No newline at end of file From abc65cb57189e748101f03409cac9c36950a04cc Mon Sep 17 00:00:00 2001 From: alexandro-rezakhani <85354050+alexandro-rezakhani@users.noreply.github.com> Date: Mon, 24 Mar 2025 22:13:53 -0400 Subject: [PATCH 4/8] Ethernet/IP Interface Setup --- .../pages/assets/legacy/settings.json | 8 +- .../CSK_Module_Fieldbus.css | 11 +- .../CSK_Module_Fieldbus.html | 1789 ++++++++++++++++- CSK_Module_Fieldbus/project.mf.xml | 507 ++++- .../scripts/CSK_Module_Fieldbus.lua | 70 +- .../Fieldbus/Fieldbus_Controller.lua | 821 +++++++- .../Communication/Fieldbus/Fieldbus_Model.lua | 1025 ++++++++-- .../Fieldbus/helper/checkAPIs.lua | 16 +- .../Communication/Fieldbus/helper/funcs.lua | 417 ++++ 9 files changed, 4330 insertions(+), 334 deletions(-) diff --git a/CSK_Module_Fieldbus/pages/assets/legacy/settings.json b/CSK_Module_Fieldbus/pages/assets/legacy/settings.json index 939ec2a..a845df1 100644 --- a/CSK_Module_Fieldbus/pages/assets/legacy/settings.json +++ b/CSK_Module_Fieldbus/pages/assets/legacy/settings.json @@ -1,3 +1,9 @@ { -"showLoginButton": false + "canChangeLanguage": true, + "showLoginButton": false, + "defaultLanguage": "en", + "disableEditMode": true, + "showPageHistory": true, + "compactMode": false, + "canChangeCompactMode": false } \ No newline at end of file diff --git a/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.css b/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.css index d215c48..ec7cdb7 100644 --- a/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.css +++ b/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.css @@ -5,5 +5,14 @@ margin: 6px; } -.myCustomCssClass_CSK_Module_Fieldbus { +.myCustomMinHeight100p_CSK_Module_Fieldbus { + min-height: 100%; } + +.myCustomMarginBottom4px_CSK_Module_Fieldbus { + margin-bottom: 4px; +} + +.myCustomRedText_CSK_Module_Fieldbus { + color: crimson; +} \ No newline at end of file diff --git a/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.html b/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.html index 46565ab..3591309 100644 --- a/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.html +++ b/CSK_Module_Fieldbus/pages/pages/CSK_Module_Fieldbus/CSK_Module_Fieldbus.html @@ -2,85 +2,1714 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Load Config - - - - - - - - - Save Config - - - - - - - - + + +

Fieldbus

+ + + + + + + + + + + + + + + + + + + + + + + + + AUTOMATIC_OPEN + + + EXPLICIT_OPEN + + + + + + + + + + Open + + + + + + + + + + CONFIRMED_MESSAGING + + + RAW + + + + + + + + + + Close + + + + + + + + + + + + + + + + STATIC + + + BOOTP + + + DHCP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Get config + + + + + + + Set config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Remanent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Get DAP IM Data + + + + + Set DAP IM data + + + + + Store DAP I&M data + + + + + + + + + + + + + + + + + + + + + + + + + + + + DISABLED + + + ProfinetIO + + + EtherNet/IP + + + + + + + + + + Set / Restart + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Load Config + + + + + + + + + Save Config + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Refresh ControlBit Status + + + + + WriteCtrlBits + + + + + + + + + + + + + + + + + + + + + Data types +
+ PLC   <->   AppSpace +
+
+ BYTE   -   U_BYTE / U_INT1   (0 ... 255) +
+ WORD   -   U_INT2   (0 ... 65535) +
+ DWORD   -   U_INT4   (0 ... 4294967295) +
+ LWord   -   U_INT8   (0 ... 18446744073709551615) +
+
+ SINT   -   S_INT1   (-128 ... +127) +
+ INT   -   S_INT2   (-32768 ... +32767) +
+ DINT   -   S_INT4   (-2147483648 ... +2147483647) +
+ LINT   -   S_INT8   (-9223372036854775808 ... +9223372036854775807) +
+
+ USINT   -   U_BYTE / U_INT1   (0 ... 255) +
+ UINT   -   U_INT2   (0 ... 65535) +
+ UDINT   -   U_INT4   (0 ... 4294967295) +
+ ULINT   -   U_INT8   (0 ... 18446744073709551615) +
+
+ REAL   -   FLOAT   (-3.402823e+38 ... -1.175495e-38 / +1.175495e-38 ... +3.402823e+38) +
+ LREAL   -   DOUBLE   (-1.7976931348623158e+308 ... -2.2250738585072014e-308 / +2.2250738585072014e-308 ... +1.7976931348623158e+308) +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + Convert data + + + + + + + + + Big Endian + + + + + + + + + + CHAR + + + DOUBLE + + + FLOAT + + + S_BYTE + + + S_INT1 + + + S_INT2 + + + S_INT4 + + + S_INT8 + + + S_LONG + + + S_SHORT + + + U_BYTE + + + U_INT1 + + + U_INT2 + + + U_INT4 + + + U_INT8 + + + U_LONG + + + U_SHORT + + + + + + + + + + Add / Edit + + + + + + + Delete + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Up + + + + + + + Down + + + + + + + + + + + + + + + + + Set value + + + + + + + Reset All + + + + + + + + + +
+
+
+
+
+ + + + + + + + + + + + + Data types +
+ PLC   <->   AppSpace +
+
+ BYTE   -   U_BYTE / U_INT1   (0 ... 255) +
+ WORD   -   U_INT2   (0 ... 65535) +
+ DWORD   -   U_INT4   (0 ... 4294967295) +
+ LWord   -   U_INT8   (0 ... 18446744073709551615) +
+
+ SINT   -   S_INT1   (-128 ... +127) +
+ INT   -   S_INT2   (-32768 ... +32767) +
+ DINT   -   S_INT4   (-2147483648 ... +2147483647) +
+ LINT   -   S_INT8   (-9223372036854775808 ... +9223372036854775807) +
+
+ USINT   -   U_BYTE / U_INT1   (0 ... 255) +
+ UINT   -   U_INT2   (0 ... 65535) +
+ UDINT   -   U_INT4   (0 ... 4294967295) +
+ ULINT   -   U_INT8   (0 ... 18446744073709551615) +
+
+ REAL   -   FLOAT   (-3.402823e+38 ... -1.175495e-38 / +1.175495e-38 ... +3.402823e+38) +
+ LREAL   -   DOUBLE   (-1.7976931348623158e+308 ... -2.2250738585072014e-308 / +2.2250738585072014e-308 ... +1.7976931348623158e+308) +
+
+
+
+
+
+ + + + + + + + + + + + + + Convert data + + + + + + + + + Big Endian + + + + + + + + + + CHAR + + + DOUBLE + + + FLOAT + + + S_BYTE + + + S_INT1 + + + S_INT2 + + + S_INT4 + + + S_INT8 + + + S_LONG + + + S_SHORT + + + U_BYTE + + + U_INT1 + + + U_INT2 + + + U_INT4 + + + U_INT8 + + + U_LONG + + + U_SHORT + + + + + + + + + + Add / Edit + + + + + + + Delete + + + + + + + + + + + + + + + + + + + + + + + + + + + Up + + + + + + + Down + + + + + + + + + + + + + + + + Each data will be forwarded by a dynamically created event identified by its name like 'CSK_Fieldbus.OnNewData_[NAME]' + + + + + + +
+
+
+
+
+
+
+
+
+
@@ -100,7 +1729,5 @@
- - diff --git a/CSK_Module_Fieldbus/project.mf.xml b/CSK_Module_Fieldbus/project.mf.xml index 0ecaa3f..d8fc150 100644 --- a/CSK_Module_Fieldbus/project.mf.xml +++ b/CSK_Module_Fieldbus/project.mf.xml @@ -6,15 +6,71 @@ released - Please fill in information regarding: What is the idea of this module and its features? + -How to use this module in general.... like: + -{empty} + + Module to provide fieldbus (Profinet / EtherNet/IP) functionality. + +This module is helpful to forward data to/from other modules to communicate to a connected PLC. + +{empty} + Typically the features of this module are used like this (check also main script of this module): + -**1) Setup** + -ToDo + -{empty} + -**2) Something else...** + - +{empty} + +**1) Selecte protocol** + +Select a fieldbus protocol to use via 'setProtocol' and trigger a device reboot to activate the protocol via 'submitProtocol'. + +After the reboot open the connection via 'openCommunication'. + +{empty} + +**2) ControlBits** + +To read the currently active ControlBits use 'refreshControlBits' and the events 'OnNewStatusControlBitsIn', 'OnNewStatusControlBitsInTable', 'OnNewStatusControlBitsOut', 'OnNewStatusControlBitsOut'. + +It is possible to set the ControlBitsIn by presetting them via 'setControlBitsIn'/'setSpecificControlBit' and to send them via 'writeControlBitsInViaUI'. + +To set a bitmask for the ControlBitsIn make use of 'setBitMask' or 'setSpecificBitMaskBit'. + +{empty} + +**3) Data to transmit** + +It is possible to define the data structure and source of the transmitted data. + +To do this preconfigure the data entry via 'setDataNameTransmit', 'setRegisteredEventTransmit', 'setConvertDataTransmit', 'setBigEndianTransmit', 'setDataTypeTransmit' and after that add this data via 'addDataToTransmitViaUI'. + +Based on the data received by the configured event (see 'setRegisteredEventTransmit') it will forward this data via fieldbus communication. + +{empty} + +**4) Data to receive** + +It is possible to define the data structure of the data to receive from the PLC. + +To do this preconfigure the data entry via 'setDataNameReceive', 'setConvertDataReceive', 'setBigEndianReceive', 'setDataTypeReceive' and after that add this data via 'addDataToReceiveViaUI'. + +The received data values will be provided via dynamically created events (see 'CSK_Fieldbus.OnNewData_DATANAME') and the full data via event 'CSK_Fieldbus.OnNewStatusReceivedData'. + + + Fieldbus protocol. + PROFINET + EtherNet_IP + EtherCAT + + + Mode for calling Fieldbus 'create' function. + EXPLICIT_OPEN + AUTOMATIC_OPEN + + + Fieldbus TransmissionMode + RAW + CONFIRMED_MESSAGING + + + Addressing mode for the IP address assignment. + DHCP + BOOTP + STATIC + + + Types of data to transmit + S_INT2 + S_BYTE + U_INT2 + U_BYTE + S_SHORT + U_SHORT + U_INT1 + U_INT8 + U_INT4 + S_INT1 + S_INT4 + U_LONG + S_INT8 + DOUBLE + FLOAT + S_LONG + CHAR + Notify status if parameters should be loaded on app/device boot up. @@ -47,9 +103,218 @@ ToDo + Status of Admin userlevel. Used internally in combination with the CSK_UserManagement module if available. - - Notify UI style to use for CSK modules. - + + Notify current selected fieldbus protocol. + + + + Notify if Fieldbus features should be used. + + + + Notify fieldbus create mode. + + + + Notify fieldbus transmission mode. + + + + Notify preset data to be transmitted. + + + + Notify preset ControlBitsIn to write. + + + + Notify bit mask to use for preset control bits to write. + + + + Notify latest ControlBitsOut received from the PLC. + + + + Notify status of the fieldbus communication. + + + + Notify if fieldbus communication is currently 'OPENED' or 'ONLINE'. + + + + Notify info of fieldbus communication. + + + + Notify current value of the control bits transmitted to the PLC. + + + + Notify addressing mode for EtherNet/IP IP assignment. + + + + Notify IP address of EtherNet/IP network. + + + + Notfify subnet mask of EtherNet/IP network. + + + + Notfify gateway of EtherNet/IP network. + + + + Notfify primary name server of EtherNet/IP network. + + + + Notfify secondary name server of EtherNet/IP network. + + + + Notfify domain name of EtherNet/IP network. + + + + Notfify MAC address of specified interface of EtherNet/IP network. + + + + Notify name of the device in the Profinet network. + + + + Notify IP address of ProfinetIO network. + + + + Notfify subnet mask of ProfinetIO network. + + + + Notfify gateway of ProfinetIO network. + + + + Notfify if the ProfinetIO network configuration tool set the IP address settings permanently. + + + + Notfify MAC address of specified interface of ProfinetIO network. + + + + Notify descriptor as used for the ProfinetIO DAP’s I&M3 data. + + + + Notify hardware revision as used for the DAP used in the I&M0 data. + + + + Notify installation date as used for the DAP’s I&M2 data. + + + + Notify software revision for the DAP (device access point) used in the I&M0 data. + + + + Notify function tag as used for the DAP’s I&M1 data. + + + + Notify location tag as used for the DAP’s I&M1 data. + + + + Notify currently active fieldbus protocol. + + + + Notify if explicit mode is selected. + + + + Notify name of event to receive data to transmit. + + + + Notify name of preconfigured transmit data. + + + + Notify preconfigured status if data needs to be converted to binary before transmission. + + + + Notify if big endian should be used to convert data to transmit (otherwise little endian will be used). + + + + Notify preconfigured data type of data to transmit. + + + + Notify list of data entires to use for data transmission. + + + + Notify temporarily set data to transmit on selected data position. + + + + Notify fieldbus relevant log message. + + + + Notify ControlBitsOut as boolean table. + + + + Notify control bits IN as boolean table. + + + + Notify bitmask of control bits IN as boolean table. + + + + Notfiy received data. + + + + Notify name of preconfigured data to receive. + + + + Notify list of data entires to use for data receiving. + + + + Notify preconfigured status if data needs to be converted to binary after receiving. + + + + Notify if big endian should be used to convert received data (otherwise little endian will be used). + + + + Notify preconfigured data type of data to receive. + + + + Dynamically created event to provide received data from PLC via event. + +NAME will be replaced by data identifier (e.g. 'CSK_Fieldbus.OnNewData_Data1'). + + + + Notify info text to restart device. + Function to set the name of the parameters if saved/loaded via the CSK_PersistentData module. @@ -60,6 +325,7 @@ ToDo + Load parameters for this module from the CSK_PersistentData module if possible and use them. + Configure if this module should load its saved parameters at app/device boot up. @@ -69,18 +335,229 @@ ToDo + Function to register "OnResume" of the module UI (only as helper function). - - Function to clear FlowConfig relevant configurations. + + Function to set fiedlbus protocol to use. + + + + Function to open fieldbus communication. + + + + Function to close fieldbus communication. + + + Function to refresh data of ControlBitsIn/Out + + + Function to preset data to transmit. + + + + Function to transmit preset data (see 'setDataToTransmit'). + + + Function to preset controlBitsIn to write/transmit to PLC. + + + + Function to preset bitmask to use for preset ControlBitsIn to write. + + + + Function to write preset ControlBitsIn to the PLC. + + + Function to set create mode of fieldbus communication. + + + + Function to set transmission mode. + + + + Function to set preset fieldbus protocol (see 'setProtocol') and restart device. + + + Function to get EtherNetIP configuration. + + + Function to setup preconfigured EtherNet/IP config. + + + Function to set addressing mode of EtherNetIP communication. + + + + Function to preset IP for EtherNet/IP communication. + + + + Function to preset subnet mask for EtherNet/IP communication. + + + + Function to preset gateway for EtherNet/IP communication. + + + + Function to preset primary name server for EtherNet/IP communication. + + + + Function to preset secondary name server for EtherNet/IP communication. + + + + Function to preset domain name for EtherNet/IP communication. + + + + Function to preset ProfinetIO device name. + + + + Function to preset IP for ProfinetIO communication. + + + + Function to preset subnet mask for ProfinetIO communication. + + + + Function to preset gateway for ProfinetIO communication. + + + + Function to get ProfinetIO configuration. + + + Function apply ProfinetIO configuration. + + + Function to store ProfinetIO configuration. + + + Function to set ProfinetIO DAP IM configuration. + + + Function to get ProfinetIO DAP IM data. + + + Function to store ProfinetIO DAP I&M data. + + + Function to set descriptor for the DAPs I&M3 data. + + + + Function to set the installation date for the DAPs I&M2 data. + + + + Function to set the function tag for the DAPs I&M1 data. + + + + Function to set location tag for the DAPs I&M1 data. + + + + Function to set event to receive data to transmit via fieldbus for new/selected data entry. + + + + Function to add preconfigured data to transmit. + + + Function to preconfigure name of data entry to transmit. + + + + Function to preconfigure if internally received data (via event) needs to be converted before transmission. + + + + Function to preconfigure if data to transmit uses big endianness. Will use little endian per default. + + + + Function to preconfigure type of data to convert data before transmission. + + + + Function to select transmit data entry in UI. + + + + Function to delete preselected data entry. + + + Function to move the position of the transmit data about one position higher. + + + Function to move the position of the selected transmit data about one position lower. + + + Function to set temporarily data of in UI selected data postion to transmit. + + + + Function to set preconfigured data to in UI selected data position (see 'setTempTransmitData'). + +After that it will transmit the full data to the fieldbus. + + + Function to set specific ControlBitIn (bit range from 0-15). + + + + Function to set specific bit of bitmask (bit range from 0-15). + + + + Function to preconfigure name of data entry to receive. + + + + Function to preconfigure if received data form PLC needs to be converted before transmission. + + + + Function to preconfigure if received data uses big endianness. Will use little endian per default. + + + + Function to preconfigure type of data to convert received data. + + + + Function to add preconfigured data to receive. + + + Function to delete preselected data entry. + + + Function to move the position of the selected data to receive about one position lower. + + + Function to move the position of the data to receive about one position higher. + + + Function to select data entry in UI. + + + + Function to reset all data to transmit. SICK AG - 0.1.0 + 1.0.1 low false false false - true + false diff --git a/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua b/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua index e24c781..97d9e01 100644 --- a/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua +++ b/CSK_Module_Fieldbus/scripts/CSK_Module_Fieldbus.lua @@ -21,42 +21,28 @@ --SOFTWARE. ---@diagnostic disable: undefined-global, redundant-parameter, missing-parameter - +-- CreationTemplateVersion: 3.6.0 --************************************************************************** --**********************Start Global Scope ********************************* --************************************************************************** -- If app property "LuaLoadAllEngineAPI" is FALSE, use this to load and check for required APIs -- This can improve performance of garbage collection + _G.availableAPIs = require('Communication/Fieldbus/helper/checkAPIs') -- can be used to adjust function scope of the module related on available APIs of the device ----------------------------------------------------------- -- Logger _G.logger = Log.SharedLogger.create('ModuleLogger') _G.logHandle = Log.Handler.create() _G.logHandle:attachToSharedLogger('ModuleLogger') -_G.logHandle:setConsoleSinkEnabled(false) --> Set to TRUE if CSK_Logger module is not used +_G.logHandle:setConsoleSinkEnabled(true) --> Set to TRUE if CSK_Logger module is not used _G.logHandle:setLevel("ALL") _G.logHandle:applyConfig() ----------------------------------------------------------- -- Loading script regarding Fieldbus_Model -- Check this script regarding Fieldbus_Model parameters and functions -_G.fieldbus_Model = require('Communication/Fieldbus/Fieldbus_Model') --AR - sometimes this is local scope ie MultiTCPIPServer? - -local fieldbus_Instances = {} -- Handle all instances - --- Load script to communicate with the fieldbus_Model UI --- Check / edit this script to see/edit functions which communicate with the UI -local fieldbusController = require('Communication/Fieldbus/Fieldbus_Controller') - -if _G.availableAPIs.default and _G.availableAPIs.specific then - local setInstanceHandle = require('Communication/Fieldbus/FlowConfig/Fieldbus_FlowConfig') - table.insert(fieldbus_Instances, fieldbus_Model.create(1)) --AR -- Create at least 1 instance - fieldbusController.setFieldbus_Instances_Handle(fieldbus_Instances) -- share handle of instances - setInstanceHandle(fieldbus_Instances) -else - _G.logger:warning("CSK_Fieldbus: Relevant CROWN(s) not available on device. Module is not supported...") -end +_G.fieldbus_Model = require('Communication/Fieldbus/Fieldbus_Model') --************************************************************************** --**********************End Global Scope *********************************** @@ -76,20 +62,52 @@ local function main() -- Can be used e.g. like this ---------------------------------------------------------------------------------------- - -- _G.fieldbus_Model.doSomething() -- if you want to start a function -- ... - fieldbusController.setFieldbus_Model_Handle(Fieldbus_Model) - CSK_Fieldbus.pageCalled() -- Update UI + --[[ + CSK_Fieldbus.setDataNameReceive('Data1') + CSK_Fieldbus.setDataTypeReceive('U_INT2') + CSK_Fieldbus.addDataToReceiveViaUI() + + CSK_Fieldbus.setDataNameReceive('Data2') + CSK_Fieldbus.setDataTypeReceive('U_INT4') + CSK_Fieldbus.addDataToReceiveViaUI() + + CSK_Fieldbus.setDataTypeTransmit('U_BYTE') + for i=1, 6 do + CSK_Fieldbus.setDataNameTransmit('Data' ..tostring(i)) + CSK_Fieldbus.addDataToTransmitViaUI() + end + + CSK_Fieldbus.setDataTypeTransmit('S_INT2') + for i=7, 10 do + CSK_Fieldbus.setDataNameTransmit('Data' ..tostring(i)) + CSK_Fieldbus.addDataToTransmitViaUI() + end + + CSK_Fieldbus.setDataTypeTransmit('U_BYTE') + for i=11, 18 do + CSK_Fieldbus.setDataNameTransmit('Data' ..tostring(i)) + CSK_Fieldbus.addDataToTransmitViaUI() + end + + CSK_Fieldbus.setDataTypeTransmit('U_INT8') + for i=19, 31 do + CSK_Fieldbus.setDataNameTransmit('Data' ..tostring(i)) + CSK_Fieldbus.addDataToTransmitViaUI() + end + + CSK_Fieldbus.setDataTypeTransmit('U_BYTE') + for i=32, 33 do + CSK_Fieldbus.setDataNameTransmit('Data' ..tostring(i)) + CSK_Fieldbus.addDataToTransmitViaUI() + end +]] + end Script.register("Engine.OnStarted", main) ---OR - --- Call function after persistent data was loaded ---Script.register("CSK_Fieldbus.OnDataLoadedOnReboot", main) - --************************************************************************** --**********************End Function Scope ********************************* --************************************************************************** diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua index 6b72d52..24f62d3 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua @@ -15,14 +15,89 @@ local tmrFieldbus = Timer.create() tmrFieldbus:setExpirationTime(300) tmrFieldbus:setPeriodic(false) +-- Timer to wait for other modules to be ready to register to their events +local tmrWaitForSetupOfOtherModules = Timer.create() +tmrWaitForSetupOfOtherModules:setExpirationTime(1000) +tmrWaitForSetupOfOtherModules:setPeriodic(false) + -- Reference to global handle local fieldbus_Model -- ************************ UI Events Start ******************************** +-- Only to prevent WARNING messages, but these are only examples/placeholders for dynamically created events/functions +---------------------------------------------------------------- +Script.serveEvent('CSK_Fieldbus.OnNewData_NAME', 'Fieldbus_OnNewData_NAME') +---------------------------------------------------------------- + +-- Real events +-------------------------------------------------- +Script.serveEvent('CSK_Fieldbus.OnNewStatusLogMessage', 'Fieldbus_OnNewStatusLogMessage') +Script.serveEvent('CSK_Fieldbus.OnNewStatusRestartInfo', 'Fieldbus_OnNewStatusRestartInfo') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusReceivedData', 'Fieldbus_OnNewStatusReceivedData') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusActive', 'Fieldbus_OnNewStatusFieldbusActive') +Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusStatus', 'Fieldbus_OnNewStatusFieldbusStatus') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusActiveProtocol', 'Fieldbus_OnNewStatusActiveProtocol') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusProtocol', 'Fieldbus_OnNewStatusProtocol') +Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusFeatureActive', 'Fieldbus_OnNewStatusFieldbusFeatureActive') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusInfo', 'Fieldbus_OnNewStatusFieldbusInfo') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusCreateMode', 'Fieldbus_OnNewStatusCreateMode') +Script.serveEvent('CSK_Fieldbus.OnNewStatusExplicitModeActive', 'Fieldbus_OnNewStatusExplicitModeActive') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusTransmissionMode', 'Fieldbus_OnNewStatusTransmissionMode') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsIn', 'Fieldbus_OnNewStatusControlBitsIn') +Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsOut', 'Fieldbus_OnNewStatusControlBitsOut') +Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsOutTable', 'Fieldbus_OnNewStatusControlBitsOutTable') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsInToWrite', 'Fieldbus_OnNewStatusControlBitsInToWrite') +Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsInTable', 'Fieldbus_OnNewStatusControlBitsInTable') +Script.serveEvent('CSK_Fieldbus.OnNewStatusBitMask', 'Fieldbus_OnNewStatusBitMask') +Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsInBitMaskTable', 'Fieldbus_OnNewStatusControlBitsInBitMaskTable') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusDataTransmissionList', 'Fieldbus_OnNewStatusDataTransmissionList') +Script.serveEvent('CSK_Fieldbus.OnNewStatusRegisteredEventTransmit', 'Fieldbus_OnNewStatusRegisteredEventTransmit') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDataNameTransmit', 'Fieldbus_OnNewStatusDataNameTransmit') +Script.serveEvent('CSK_Fieldbus.OnNewStatusConvertDataTransmit', 'Fieldbus_OnNewStatusConvertDataTransmit') +Script.serveEvent('CSK_Fieldbus.OnNewStatusBigEndianTransmit', 'Fieldbus_OnNewStatusBigEndianTransmit') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDataTypeTransmit', 'Fieldbus_OnNewStatusDataTypeTransmit') +Script.serveEvent('CSK_Fieldbus.OnNewStatusTempDataTransmit', 'Fieldbus_OnNewStatusTempDataTransmit') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDataToTransmit', 'Fieldbus_OnNewStatusDataToTransmit') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusDataReceivingList', 'Fieldbus_OnNewStatusDataReceivingList') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDataNameReceive', 'Fieldbus_OnNewStatusDataNameReceive') +Script.serveEvent('CSK_Fieldbus.OnNewStatusConvertDataReceive', 'Fieldbus_OnNewStatusConvertDataReceive') +Script.serveEvent('CSK_Fieldbus.OnNewStatusBigEndianReceive', 'Fieldbus_OnNewStatusBigEndianReceive') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDataTypeReceive', 'Fieldbus_OnNewStatusDataTypeReceive') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPAddressingMode', 'Fieldbus_OnNewStatusEtherNetIPAddressingMode') +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPIPAddress', 'Fieldbus_OnNewStatusEtherNetIPIPAddress') +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPSubnetMask', 'Fieldbus_OnNewStatusEtherNetIPSubnetMask') +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPGateway', 'Fieldbus_OnNewStatusEtherNetIPGateway') +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPNameServer', 'Fieldbus_OnNewStatusEtherNetIPNameServer') +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPNameServer2', 'Fieldbus_OnNewStatusEtherNetIPNameServer2') +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPDomainName', 'Fieldbus_OnNewStatusEtherNetIPDomainName') +Script.serveEvent('CSK_Fieldbus.OnNewStatusEtherNetIPMACAddress', 'Fieldbus_OnNewStatusEtherNetIPMACAddress') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusProfinetIODeviceName', 'Fieldbus_OnNewStatusProfinetIODeviceName') +Script.serveEvent('CSK_Fieldbus.OnNewStatusProfinetIOIPAddress', 'Fieldbus_OnNewStatusProfinetIOIPAddress') +Script.serveEvent('CSK_Fieldbus.OnNewStatusProfinetIOSubnetMask', 'Fieldbus_OnNewStatusProfinetIOSubnetMask') +Script.serveEvent('CSK_Fieldbus.OnNewStatusProfinetIOGateway', 'Fieldbus_OnNewStatusProfinetIOGateway') +Script.serveEvent('CSK_Fieldbus.OnNewStatusProfinetIORemanent', 'Fieldbus_OnNewStatusProfinetIORemanent') +Script.serveEvent('CSK_Fieldbus.OnNewStatusProfinetIOMACAddress', 'Fieldbus_OnNewStatusProfinetIOMACAddress') + +Script.serveEvent('CSK_Fieldbus.OnNewStatusDAPIMDescriptor', 'Fieldbus_OnNewStatusDAPIMDescriptor') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDAPIMHardwareRev', 'Fieldbus_OnNewStatusDAPIMHardwareRev') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDAPIMInstallationDate', 'Fieldbus_OnNewStatusDAPIMInstallationDate') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDAPIMSoftwareRev', 'Fieldbus_OnNewStatusDAPIMSoftwareRev') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDAPIMTagFunction', 'Fieldbus_OnNewStatusDAPIMTagFunction') +Script.serveEvent('CSK_Fieldbus.OnNewStatusDAPIMTagLocation', 'Fieldbus_OnNewStatusDAPIMTagLocation') --- Script.serveEvent("CSK_Fieldbus.OnNewEvent", "Fieldbus_OnNewEvent") - -Script.serveEvent('CSK_Fieldbus.OnNewStatusCSKStyle', 'Fieldbus_OnNewStatusCSKStyle') Script.serveEvent("CSK_Fieldbus.OnNewStatusLoadParameterOnReboot", "Fieldbus_OnNewStatusLoadParameterOnReboot") Script.serveEvent("CSK_Fieldbus.OnPersistentDataModuleAvailable", "Fieldbus_OnPersistentDataModuleAvailable") Script.serveEvent("CSK_Fieldbus.OnNewParameterName", "Fieldbus_OnNewParameterName") @@ -33,18 +108,7 @@ Script.serveEvent('CSK_Fieldbus.OnUserLevelMaintenanceActive', 'Fieldbus_OnUserL Script.serveEvent('CSK_Fieldbus.OnUserLevelServiceActive', 'Fieldbus_OnUserLevelServiceActive') Script.serveEvent('CSK_Fieldbus.OnUserLevelAdminActive', 'Fieldbus_OnUserLevelAdminActive') --- ... - -- ************************ UI Events End ********************************** - ---[[ ---- Some internal code docu for local used function -local function functionName() - -- Do something - -end -]] - --************************************************************************** --********************** End Global Scope ********************************** --************************************************************************** @@ -105,17 +169,97 @@ local function updateUserLevel() end end +--TODO not needed? +--[[ +local function checkExplicitMode() + if fieldbus_Model.parameters.createMode == 'EXPLICIT_OPEN' then + Script.notifyEvent("Fieldbus_OnNewStatusExplicitModeActive", true) + else + Script.notifyEvent("Fieldbus_OnNewStatusExplicitModeActive", false) + end +end +]] + --- Function to send all relevant values to UI on resume local function handleOnExpiredTmrFieldbus() updateUserLevel() - -- Script.notifyEvent("Fieldbus_OnNewEvent", false) + fieldbus_Model.boolControlBitsToWrite = fieldbus_Model.boolControlBitsOut + + Script.notifyEvent("Fieldbus_OnNewStatusActiveProtocol", fieldbus_Model.fbMode) + + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusStatus", fieldbus_Model.currentStatus) + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusActive", fieldbus_Model.opened) + Script.notifyEvent("Fieldbus_OnNewStatusRestartInfo", '') + + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) + Script.notifyEvent("Fieldbus_OnNewStatusProtocol", fieldbus_Model.parameters.protocol) + + Script.notifyEvent("Fieldbus_OnNewStatusDataTransmissionList", fieldbus_Model.helperFuncs.createJsonListTransmissionData(fieldbus_Model.parameters.dataNamesTransmit, fieldbus_Model.parameters.registeredEventsTransmit, fieldbus_Model.parameters.dataTypesTransmit, fieldbus_Model.parameters.convertDataTypesTransmit, fieldbus_Model.parameters.bigEndiansTransmit, fieldbus_Model.readableDataToTransmit, fieldbus_Model.selectedDataTransmit)) + Script.notifyEvent("Fieldbus_OnNewStatusDataNameTransmit", fieldbus_Model.dataNameTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusRegisteredEventTransmit", fieldbus_Model.registerEventTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusConvertDataTransmit", fieldbus_Model.convertDataTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusBigEndianTransmit", fieldbus_Model.bigEndianTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusDataTypeTransmit", fieldbus_Model.dataTypeTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusTempDataTransmit", tostring(fieldbus_Model.tempDataTransmit)) + + Script.notifyEvent("Fieldbus_OnNewStatusDataReceivingList", fieldbus_Model.helperFuncs.createJsonListReceiveData(fieldbus_Model.parameters.dataNamesReceive, fieldbus_Model.parameters.dataTypesReceive, fieldbus_Model.parameters.convertDataTypesReceive, fieldbus_Model.parameters.bigEndiansReceive, fieldbus_Model.dataReceived, fieldbus_Model.selectedDataReceive)) + Script.notifyEvent("Fieldbus_OnNewStatusDataNameReceive", fieldbus_Model.dataNameReceive) + Script.notifyEvent("Fieldbus_OnNewStatusConvertDataReceive", fieldbus_Model.convertDataReceive) + Script.notifyEvent("Fieldbus_OnNewStatusBigEndianReceive", fieldbus_Model.bigEndianReceive) + Script.notifyEvent("Fieldbus_OnNewStatusDataTypeReceive", fieldbus_Model.dataTypeReceive) + + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsIn", fieldbus_Model.controlBitsIn) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsOut", fieldbus_Model.controlBitsOut) + + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsOutTable", fieldbus_Model.boolControlBitsOut) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInTable", fieldbus_Model.boolControlBitsIn) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInBitMaskTable", fieldbus_Model.boolBitMask) + + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInToWrite", fieldbus_Model.controlBitsToWrite) + Script.notifyEvent("Fieldbus_OnNewStatusBitMask", fieldbus_Model.bitMask) + + if fieldbus_Model.fbMode == 'DISABLED' then + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusFeatureActive", false) + else + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusFeatureActive", true) + + Script.notifyEvent("Fieldbus_OnNewStatusCreateMode", fieldbus_Model.parameters.createMode) + --checkExplicitMode() + + Script.notifyEvent("Fieldbus_OnNewStatusTransmissionMode", fieldbus_Model.parameters.transmissionMode) + + if fieldbus_Model.fbMode == 'EtherNetIP' then + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPAddressingMode", fieldbus_Model.parameters.etherNetIP.addressingMode) + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPIPAddress", fieldbus_Model.parameters.etherNetIP.ipAddress) + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPSubnetMask", fieldbus_Model.parameters.etherNetIP.netmask) + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPGateway", fieldbus_Model.parameters.etherNetIP.gateway) + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer", fieldbus_Model.parameters.etherNetIP.nameServer) + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer2", fieldbus_Model.parameters.etherNetIP.nameServer2) + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPDomainName", fieldbus_Model.parameters.etherNetIP.domainName) + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPMACAddress", fieldbus_Model.parameters.etherNetIP.macAddress) + + elseif fieldbus_Model.fbMode == 'ProfinetIO' then + Script.notifyEvent("Fieldbus_OnNewStatusProfinetIODeviceName", fieldbus_Model.parameters.profinetIO.deviceName) + Script.notifyEvent("Fieldbus_OnNewStatusProfinetIOIPAddress", fieldbus_Model.parameters.profinetIO.ipAddress) + Script.notifyEvent("Fieldbus_OnNewStatusProfinetIOSubnetMask", fieldbus_Model.parameters.profinetIO.netmask) + Script.notifyEvent("Fieldbus_OnNewStatusProfinetIOGateway", fieldbus_Model.parameters.profinetIO.gateway) + Script.notifyEvent("Fieldbus_OnNewStatusProfinetIORemanent", fieldbus_Model.parameters.profinetIO.remanent) + Script.notifyEvent("Fieldbus_OnNewStatusProfinetIOMACAddress", fieldbus_Model.parameters.profinetIO.macAddress) + + Script.notifyEvent("Fieldbus_OnNewStatusDAPIMDescriptor", fieldbus_Model.parameters.profinetIO.dapImDescriptor) + Script.notifyEvent("Fieldbus_OnNewStatusDAPIMHardwareRev", fieldbus_Model.parameters.profinetIO.dapImHardwareRev) + Script.notifyEvent("Fieldbus_OnNewStatusDAPIMInstallationDate", fieldbus_Model.parameters.profinetIO.dapImInstallDate) + Script.notifyEvent("Fieldbus_OnNewStatusDAPIMSoftwareRev", fieldbus_Model.parameters.profinetIO.dapImSoftwareRevPrefix .. '.' .. tostring(fieldbus_Model.parameters.profinetIO.dapImSoftwareRevFuncEnhancement) .. '.' .. tostring(fieldbus_Model.parameters.profinetIO.dapImSoftwareRevBugFix) .. '.' .. tostring(fieldbus_Model.parameters.profinetIO.dapImSoftwareRevInternalChange)) + Script.notifyEvent("Fieldbus_OnNewStatusDAPIMTagFunction", fieldbus_Model.parameters.profinetIO.dapImTagFunction) + Script.notifyEvent("Fieldbus_OnNewStatusDAPIMTagLocation", fieldbus_Model.parameters.profinetIO.dapImTagLocation) + end + end Script.notifyEvent("Fieldbus_OnNewStatusLoadParameterOnReboot", fieldbus_Model.parameterLoadOnReboot) Script.notifyEvent("Fieldbus_OnPersistentDataModuleAvailable", fieldbus_Model.persistentModuleAvailable) Script.notifyEvent("Fieldbus_OnNewParameterName", fieldbus_Model.parametersName) - -- ... end Timer.register(tmrFieldbus, "OnExpired", handleOnExpiredTmrFieldbus) @@ -128,29 +272,602 @@ local function pageCalled() end Script.serveFunction("CSK_Fieldbus.pageCalled", pageCalled) -local function clearFlowConfigRelevantConfiguration() - for i = 1, #fieldbus_Instances do - Script.notifyEvent('Fieldbus_OnNewProcessingParameter', selectedInstance, 'clearAll') - fieldbus_Instances[selectedInstance].parameters.clientBroadcasts.forwardEvents = {} - fieldbus_Instances[selectedInstance].parameters.forwardEvents = {} +local function setProtocol(protocol) + _G.logger:fine(nameOfModule .. ": Set protocol to: " .. tostring(protocol)) + fieldbus_Model.parameters.protocol = protocol + handleOnExpiredTmrFieldbus() + + if (fieldbus_Model.parameters.protocol == 'ProfinetIO' and Parameters.get('FBmode') ~= 1) or (fieldbus_Model.parameters.protocol == 'EtherNetIP' and Parameters.get('FBmode') ~= 2) or (fieldbus_Model.parameters.protocol == 'DISABLED' and Parameters.get('FBmode') ~= 0) then + Script.notifyEvent("Fieldbus_OnNewStatusRestartInfo", 'Device restart needed to activate new protocol!') + else + Script.notifyEvent("Fieldbus_OnNewStatusRestartInfo", '') end end -Script.serveFunction('CSK_Fieldbus.clearFlowConfigRelevantConfiguration', clearFlowConfigRelevantConfiguration) +Script.serveFunction('CSK_Fieldbus.setProtocol', setProtocol) ---[[ -local function setSomething(value) - _G.logger:info(nameOfModule .. ": Set new value = " .. value) - fieldbus_Model.varA = value +local function restartDevice() + Parameters.savePermanent() + if CSK_PersistentData then + CSK_Fieldbus.sendParameters() + end + Engine.reboot('Change fieldbus protocol.') end -Script.serveFunction("CSK_Fieldbus.setSomething", setSomething) -]] + +local function submitProtocol() + if fieldbus_Model.parameters.protocol == 'ProfinetIO' and Parameters.get('FBmode') ~= 1 then + Parameters.set('FBmode', 1) + restartDevice() + elseif fieldbus_Model.parameters.protocol == 'EtherNetIP' and Parameters.get('FBmode') ~= 2 then + Parameters.set('FBmode', 2) + restartDevice() + elseif fieldbus_Model.parameters.protocol == 'DISABLED' and Parameters.get('FBmode') ~= 0 then + Parameters.set('FBmode', 0) + restartDevice() + end +end +Script.serveFunction('CSK_Fieldbus.submitProtocol', submitProtocol) + +local function setCreateMode(mode) + if fieldbus_Model.currentStatus == 'CLOSED' then + fieldbus_Model.parameters.createMode = mode + if mode == 'AUTOMATIC_OPEN' then + fieldbus_Model.parameters.transmissionMode = 'CONFIRMED_MESSAGING' + Script.notifyEvent("Fieldbus_OnNewStatusTransmissionMode", fieldbus_Model.parameters.transmissionMode) + end + else + _G.logger:info("Connection needs to be closed to configure the create mode.") + Script.notifyEvent("Fieldbus_OnNewStatusCreateMode", fieldbus_Model.parameters.createMode) + end + --checkExplicitMode() +end +Script.serveFunction('CSK_Fieldbus.setCreateMode', setCreateMode) + +local function setTransmissionMode(mode) + if fieldbus_Model.parameters.createMode == 'EXPLICIT_OPEN' then + fieldbus_Model.setTransmissionMode(mode) + else + _G.logger:info("Transmission mode only configurable if 'create mode' is 'EXPLICIT_OPEN'.") + Script.notifyEvent("Fieldbus_OnNewStatusTransmissionMode", fieldbus_Model.parameters.transmissionMode) + end +end +Script.serveFunction('CSK_Fieldbus.setTransmissionMode', setTransmissionMode) + +local function openCommunication() + local success = false + if fieldbus_Model.currentStatus == 'CLOSED' then + _G.logger:info(nameOfModule .. ": Open communciation.") + success = fieldbus_Model.openCommunication() + else + _G.logger:fine("Connection already active.") + end + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) + return success +end +Script.serveFunction('CSK_Fieldbus.openCommunication', openCommunication) + +local function closeCommunication() + _G.logger:info(nameOfModule .. ": Close communication.") + fieldbus_Model.closeCommunication() + + fieldbus_Model.info = 'No info available.' + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.info) +end +Script.serveFunction('CSK_Fieldbus.closeCommunication', closeCommunication) + +local function refreshControlBits() + fieldbus_Model.readControlBitsIn() + fieldbus_Model.readControlBitsOut() +end +Script.serveFunction('CSK_Fieldbus.refreshControlBits', refreshControlBits) + +local function setDataToTransmit(data) + _G.logger:fine(nameOfModule .. ": Set data to transmit to: " .. tostring(data)) + fieldbus_Model.dataToTransmit = data +end +Script.serveFunction('CSK_Fieldbus.setDataToTransmit', setDataToTransmit) + +local function transmitViaUI() + fieldbus_Model.transmit(fieldbus_Model.dataToTransmit) +end +Script.serveFunction('CSK_Fieldbus.transmitViaUI', transmitViaUI) + +local function setControlBitsIn(controlBits) + _G.logger:fine(nameOfModule .. ": Set controlBits to: " .. tostring(controlBits)) + fieldbus_Model.controlBitsToWrite = controlBits + fieldbus_Model.boolControlBitsToWrite = fieldbus_Model.helperFuncs.toBits(fieldbus_Model.controlBitsToWrite) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInTable", fieldbus_Model.boolControlBitsToWrite) +end +Script.serveFunction('CSK_Fieldbus.setControlBitsIn', setControlBitsIn) + +local function setSpecificControlBitIn(values) + local value = false + local pos = tonumber(values[2]) + if values[1] == 'true' then + value = true + end + if pos then + fieldbus_Model.boolControlBitsToWrite[pos+1] = value + fieldbus_Model.controlBitsToWrite = fieldbus_Model.helperFuncs.toNumber(fieldbus_Model.boolControlBitsToWrite) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInToWrite", fieldbus_Model.controlBitsToWrite) + --print(fieldbus_Model.controlBitsToWrite) + end +end +Script.serveFunction('CSK_Fieldbus.setSpecificControlBitIn', setSpecificControlBitIn) + +local function setBitMask(bitMask) + _G.logger:fine(nameOfModule .. ": Set bitMask to: " .. tostring(bitMask)) + fieldbus_Model.bitMask = bitMask + fieldbus_Model.boolBitMask = fieldbus_Model.helperFuncs.toBits(fieldbus_Model.bitMask) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInBitMaskTable", fieldbus_Model.boolBitMask) +end +Script.serveFunction('CSK_Fieldbus.setBitMask', setBitMask) + +local function setSpecificBitMaskBit(values) + local value = false + local pos = tonumber(values[2]) + if values[1] == 'true' then + value = true + end + if pos then + fieldbus_Model.boolBitMask[pos+1] = value + fieldbus_Model.bitMask = fieldbus_Model.helperFuncs.toNumber(fieldbus_Model.boolBitMask) + Script.notifyEvent("Fieldbus_OnNewStatusBitMask", fieldbus_Model.bitMask) + --print(fieldbus_Model.bitMask) + end +end +Script.serveFunction('CSK_Fieldbus.setSpecificBitMaskBit', setSpecificBitMaskBit) + +local function writeControlBitsInViaUI() + fieldbus_Model.writeControlBitsIn(fieldbus_Model.controlBitsToWrite, fieldbus_Model.bitMask) +end +Script.serveFunction('CSK_Fieldbus.writeControlBitsInViaUI', writeControlBitsInViaUI) + +-- EtherNet/IP relevant +local function setAddressingMode(mode) + _G.logger:fine(nameOfModule .. ": Preset Addressing mode to: " .. tostring(mode)) + fieldbus_Model.parameters.etherNetIP.addressingMode = mode +end +Script.serveFunction('CSK_Fieldbus.setAddressingMode', setAddressingMode) + +local function setEtherNetIPIP(ip) + _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP IP to: " .. tostring(ip)) + fieldbus_Model.parameters.etherNetIP.ipAddress = ip +end +Script.serveFunction('CSK_Fieldbus.setEtherNetIPIP', setEtherNetIPIP) + +local function setEtherNetIPSubnetMask(netmask) + _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP subnet mask: " .. tostring(netmask)) + fieldbus_Model.parameters.etherNetIP.netmask = netmask +end +Script.serveFunction('CSK_Fieldbus.setEtherNetIPSubnetMask', setEtherNetIPSubnetMask) + +local function setEtherNetIPGateway(gateway) + _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP gateway: " .. tostring(gateway)) + fieldbus_Model.parameters.etherNetIP.gateway = gateway +end +Script.serveFunction('CSK_Fieldbus.setEtherNetIPGateway', setEtherNetIPGateway) + +local function setEtherNetIPNameServer(nameServer) + _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP primary name server: " .. tostring(nameServer)) + fieldbus_Model.parameters.etherNetIP.nameServer = nameServer +end +Script.serveFunction('CSK_Fieldbus.setEtherNetIPNameServer', setEtherNetIPNameServer) + +local function setEtherNetIPNameServer2(nameServer) + _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP secondary name server: " .. tostring(nameServer)) + fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer +end +Script.serveFunction('CSK_Fieldbus.setEtherNetIPNameServer2', setEtherNetIPNameServer2) + +local function setEtherNetIPDomainName(domainName) + _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP domain name: " .. tostring(domainName)) + fieldbus_Model.parameters.etherNetIP.domainName = domainName +end +Script.serveFunction('CSK_Fieldbus.setEtherNetIPDomainName', setEtherNetIPDomainName) + +local function getEtherNetIPConfig() + _G.logger:fine(nameOfModule .. ": Get EtherNet/IP configuration.") + fieldbus_Model.getEtherNetIPConfig() +end +Script.serveFunction('CSK_Fieldbus.getEtherNetIPConfig', getEtherNetIPConfig) + +local function setEtherNetIPConfig() + _G.logger:fine(nameOfModule .. ": Activate preset EtherNet/IP configuration") + fieldbus_Model.setEtherNetIPConfig() +end +Script.serveFunction('CSK_Fieldbus.setEtherNetIPConfig', setEtherNetIPConfig) + +-- ProfinetIO + +local function setProfinetIODeviceName(name) + _G.logger:fine(nameOfModule .. ": Preset device name to: " .. tostring(name)) + fieldbus_Model.parameters.profinetIO.deviceName = name +end +Script.serveFunction('CSK_Fieldbus.setProfinetIODeviceName', setProfinetIODeviceName) + +local function setProfinetIOIP(ip) + _G.logger:fine(nameOfModule .. ": Preset ProfinetIO IP to: " .. tostring(ip)) + fieldbus_Model.parameters.profinetIO.ipAddress = ip +end +Script.serveFunction('CSK_Fieldbus.setProfinetIOIP', setProfinetIOIP) + +local function setProfinetIOSubnetMask(netmask) + _G.logger:fine(nameOfModule .. ": Preset ProfinetIO subnet mask: " .. tostring(netmask)) + fieldbus_Model.parameters.profinetIO.netmask = netmask +end +Script.serveFunction('CSK_Fieldbus.setProfinetIOSubnetMask', setProfinetIOSubnetMask) + +local function setProfinetIOGateway(gateway) + _G.logger:fine(nameOfModule .. ": Preset ProfinetIO gateway: " .. tostring(gateway)) + fieldbus_Model.parameters.profinetIO.gateway = gateway +end +Script.serveFunction('CSK_Fieldbus.setProfinetIOGateway', setProfinetIOGateway) + +local function getProfinetIOConfig() + _G.logger:fine(nameOfModule .. ": Get ProfinetIO configuration.") + fieldbus_Model.getProfinetIOConfigInfo() +end +Script.serveFunction('CSK_Fieldbus.getProfinetIOConfig', getProfinetIOConfig) + +local function applyProfinetIOConfig() + _G.logger:fine(nameOfModule .. ": Activate preset ProfinetIO configuration.") + fieldbus_Model.applyProfinetIOConfig() +end +Script.serveFunction('CSK_Fieldbus.applyProfinetIOConfig', applyProfinetIOConfig) + +local function storeProfinetIOConfig() + _G.logger:fine(nameOfModule .. ": Store ProfinetIO configuration.") + fieldbus_Model.storeProfinetIOConfig() +end +Script.serveFunction('CSK_Fieldbus.storeProfinetIOConfig', storeProfinetIOConfig) + +local function setDAPIMDescriptor(descriptor) + _G.logger:fine(nameOfModule .. ": Preset DAP IM descriptoer to: " .. tostring(descriptor)) + fieldbus_Model.parameters.profinetIO.dapImDescriptor = descriptor +end +Script.serveFunction('CSK_Fieldbus.setDAPIMDescriptor', setDAPIMDescriptor) + +local function setDAPIMInstallationDate(date) + _G.logger:fine(nameOfModule .. ": Preset DAP IM installation date to: " .. tostring(date)) + fieldbus_Model.parameters.profinetIO.dapImInstallDate = date +end +Script.serveFunction('CSK_Fieldbus.setDAPIMInstallationDate', setDAPIMInstallationDate) + +local function setDAPIMTagFunction(tag) + _G.logger:fine(nameOfModule .. ": Preset DAP IM function tag to: " .. tostring(tag)) + fieldbus_Model.parameters.profinetIO.tagFunction = tag +end +Script.serveFunction('CSK_Fieldbus.setDAPIMTagFunction', setDAPIMTagFunction) + +local function setDAPIMTagLocation(location) + _G.logger:fine(nameOfModule .. ": Preset DAP IM location tag to: " .. tostring(location)) + fieldbus_Model.parameters.profinetIO.tagLocation = location +end +Script.serveFunction('CSK_Fieldbus.setDAPIMTagLocation', setDAPIMTagLocation) + +local function getDAPIMConfig() + _G.logger:fine(nameOfModule .. ": Get ProfinetIO DAP I&M data.") + fieldbus_Model.getDapImConfigInfo() +end +Script.serveFunction('CSK_Fieldbus.getDAPIMConfig', getDAPIMConfig) + +local function setDAPIMConfig() + _G.logger:fine(nameOfModule .. ": Set ProfinetIO DAP I&M data.") + fieldbus_Model.setDapImConfig() +end +Script.serveFunction('CSK_Fieldbus.setDAPIMConfig', setDAPIMConfig) + +local function storeDAPIMData() + _G.logger:fine(nameOfModule .. ": Store DAP I&M data.") + fieldbus_Model.storeDapImData() +end +Script.serveFunction('CSK_Fieldbus.storeDAPIMData', storeDAPIMData) + +local function setDataNameTransmit(name) + _G.logger:fine(nameOfModule .. ": Preset DataName to transmit: " .. tostring(name)) + fieldbus_Model.dataNameTransmit = name +end +Script.serveFunction('CSK_Fieldbus.setDataNameTransmit', setDataNameTransmit) + +local function setDataNameReceive(name) + _G.logger:fine(nameOfModule .. ": Preset DataName to receive: " .. tostring(name)) + fieldbus_Model.dataNameReceive = name +end +Script.serveFunction('CSK_Fieldbus.setDataNameReceive', setDataNameReceive) + +local function setRegisteredEventTransmit(eventName) + _G.logger:fine(nameOfModule .. ": Preset event to register for transmit data to: " .. tostring(eventName)) + fieldbus_Model.registerEventTransmit = eventName +end +Script.serveFunction('CSK_Fieldbus.setRegisteredEventTransmit', setRegisteredEventTransmit) + +local function setConvertDataTransmit(status) + _G.logger:fine(nameOfModule .. ": Preset status to convert transmit data to: " .. tostring(status)) + fieldbus_Model.convertDataTransmit = status +end +Script.serveFunction('CSK_Fieldbus.setConvertDataTransmit', setConvertDataTransmit) + +local function setConvertDataReceive(status) + _G.logger:fine(nameOfModule .. ": Preset status to convert received data to: " .. tostring(status)) + fieldbus_Model.convertDataReceive = status +end +Script.serveFunction('CSK_Fieldbus.setConvertDataReceive', setConvertDataReceive) + +local function setBigEndianTransmit(status) + _G.logger:fine(nameOfModule .. ": Preset status of big endian of transmit data to: " .. tostring(status)) + fieldbus_Model.bigEndianTransmit = status +end +Script.serveFunction('CSK_Fieldbus.setBigEndianTransmit', setBigEndianTransmit) + +local function setBigEndianReceive(status) + _G.logger:fine(nameOfModule .. ": Preset status of big endian of received data to: " .. tostring(status)) + fieldbus_Model.bigEndianReceive = status +end +Script.serveFunction('CSK_Fieldbus.setBigEndianReceive', setBigEndianReceive) + +local function setDataTypeTransmit(dataType) + _G.logger:fine(nameOfModule .. ": Preset data type of transmit to: " .. tostring(dataType)) + fieldbus_Model.dataTypeTransmit = dataType +end +Script.serveFunction('CSK_Fieldbus.setDataTypeTransmit', setDataTypeTransmit) + +local function setDataTypeReceive(dataType) + _G.logger:fine(nameOfModule .. ": Preset type or received data to: " .. tostring(dataType)) + fieldbus_Model.dataTypeReceive = dataType +end +Script.serveFunction('CSK_Fieldbus.setDataTypeReceive', setDataTypeReceive) + +local function editDataToTransfer(dataName) + + Script.deregister(fieldbus_Model.parameters.registeredEventsTransmit[dataName], fieldbus_Model.dataUpdateFunctions[dataName]) + + fieldbus_Model.parameters.registeredEventsTransmit[dataName] = fieldbus_Model.registerEventTransmit + fieldbus_Model.parameters.convertDataTypesTransmit[dataName] = fieldbus_Model.convertDataTransmit + fieldbus_Model.parameters.bigEndiansTransmit[dataName] = fieldbus_Model.bigEndianTransmit + fieldbus_Model.parameters.dataTypesTransmit[dataName] = fieldbus_Model.dataTypeTransmit + + fieldbus_Model.registerToEvent(fieldbus_Model.parameters.registeredEventsTransmit[dataName], tonumber(fieldbus_Model.selectedDataTransmit), dataName) + + fieldbus_Model.totalDataSizeTransmit = fieldbus_Model.helperFuncs.getDataSize(fieldbus_Model.parameters.dataTypesTransmit) + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "New transmit data size = " .. tostring(fieldbus_Model.totalDataSizeTransmit)) +end + +local function addDataToTransmitViaUI() + if fieldbus_Model.selectedDataTransmit == '' then + if not fieldbus_Model.parameters.registeredEventsTransmit[fieldbus_Model.dataNameTransmit] then + _G.logger:fine(nameOfModule .. ": Add data to transmit.") + fieldbus_Model.addDataTransmit(fieldbus_Model.dataNameTransmit, fieldbus_Model.registerEventTransmit, fieldbus_Model.convertDataTransmit, fieldbus_Model.dataTypeTransmit, fieldbus_Model.bigEndianTransmit) + else + _G.logger:warning(nameOfModule .. ": Transmit data with this name already exists.") + end + else + local posName = fieldbus_Model.parameters.dataNamesTransmit[tonumber(fieldbus_Model.selectedDataTransmit)] + if posName == fieldbus_Model.dataNameTransmit then + _G.logger:fine(nameOfModule .. ": Edit data to transmit.") + editDataToTransfer(posName) + else + _G.logger:info(nameOfModule .. ": Not possible to rename transmit data. Delete first and add new one...") + fieldbus_Model.dataNameTransmit = fieldbus_Model.parameters.dataNamesTransmit[tonumber(fieldbus_Model.selectedDataTransmit)] + Script.notifyEvent("Fieldbus_OnNewStatusDataNameTransmit", fieldbus_Model.dataNameTransmit) + end + end + fieldbus_Model.totalDataSizeTransmit = fieldbus_Model.helperFuncs.getDataSize(fieldbus_Model.parameters.dataTypesTransmit) + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "New transmit data size = " .. tostring(fieldbus_Model.totalDataSizeTransmit)) + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.addDataToTransmitViaUI', addDataToTransmitViaUI) + +local function deleteDataToTransmitViaUI() + if fieldbus_Model.selectedDataTransmit ~= '' and tonumber(fieldbus_Model.selectedDataTransmit) then + _G.logger:fine(nameOfModule .. ": Delete data entry no." .. fieldbus_Model.selectedDataTransmit) + fieldbus_Model.removeDataTransmit(tonumber(fieldbus_Model.selectedDataTransmit)) + fieldbus_Model.selectedDataTransmit = '' + end + fieldbus_Model.totalDataSizeTransmit = fieldbus_Model.helperFuncs.getDataSize(fieldbus_Model.parameters.dataTypesTransmit) + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "New transmit data size = " .. tostring(fieldbus_Model.totalDataSizeTransmit)) + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.deleteDataToTransmitViaUI', deleteDataToTransmitViaUI) + +local function dataTransmitPositionUp() + if fieldbus_Model.selectedDataTransmit ~= '' and tonumber(fieldbus_Model.selectedDataTransmit) then + fieldbus_Model.dataTransmitPositionUp(tonumber(fieldbus_Model.selectedDataTransmit)) + end + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.dataTransmitPositionUp', dataTransmitPositionUp) + +local function dataTransmitPositionDown() + if fieldbus_Model.selectedDataTransmit ~= '' and tonumber(fieldbus_Model.selectedDataTransmit) then + fieldbus_Model.dataTransmitPositionDown(tonumber(fieldbus_Model.selectedDataTransmit)) + end + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.dataTransmitPositionDown', dataTransmitPositionDown) + +--- Function to edit data to receive +---@param dataName string Name/identifier of data to update +local function editDataToReceive(dataName) + + fieldbus_Model.parameters.convertDataTypesReceive[dataName] = fieldbus_Model.convertDataReceive + fieldbus_Model.parameters.bigEndiansReceive[dataName] = fieldbus_Model.bigEndianReceive + fieldbus_Model.parameters.dataTypesReceive[dataName] = fieldbus_Model.dataTypeReceive + + fieldbus_Model.totalDataSizeReceive = fieldbus_Model.helperFuncs.getDataSize(fieldbus_Model.parameters.dataTypesReceive) + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "New data size to receive = " .. tostring(fieldbus_Model.totalDataSizeReceive)) +end + +local function addDataToReceiveViaUI() + if fieldbus_Model.selectedDataReceive == '' then + if not fieldbus_Model.parameters.convertDataTypesReceive[fieldbus_Model.dataNameReceive] then + _G.logger:fine(nameOfModule .. ": Add data to receive.") + fieldbus_Model.addDataReceive(fieldbus_Model.dataNameReceive, fieldbus_Model.convertDataReceive, fieldbus_Model.dataTypeReceive, fieldbus_Model.bigEndianReceive) + else + _G.logger:warning(nameOfModule .. ": Data with this name already exists.") + end + else + local posName = fieldbus_Model.parameters.dataNamesReceive[tonumber(fieldbus_Model.selectedDataReceive)] + if posName == fieldbus_Model.dataNameReceive then + _G.logger:fine(nameOfModule .. ": Edit data to receive.") + editDataToReceive(posName) + else + _G.logger:info(nameOfModule .. ": Not possible to rename data. Delete first and add new one...") + fieldbus_Model.dataNameReceive = fieldbus_Model.parameters.dataNamesReceive[tonumber(fieldbus_Model.selectedDataReceive)] + Script.notifyEvent("Fieldbus_OnNewStatusDataNameReceive", fieldbus_Model.dataNameReceive) + end + end + fieldbus_Model.totalDataSizeReceive = fieldbus_Model.helperFuncs.getDataSize(fieldbus_Model.parameters.dataTypesReceive) + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "New data size to receive = " .. tostring(fieldbus_Model.totalDataSizeReceive)) + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.addDataToReceiveViaUI', addDataToReceiveViaUI) + +local function deleteDataToReceiveViaUI() + if fieldbus_Model.selectedDataReceive ~= '' and tonumber(fieldbus_Model.selectedDataReceive) then + _G.logger:fine(nameOfModule .. ": Delete receive data entry no." .. fieldbus_Model.selectedDataReceive) + fieldbus_Model.removeDataReceive(tonumber(fieldbus_Model.selectedDataReceive)) + fieldbus_Model.selectedDataReceive = '' + end + fieldbus_Model.totalDataSizeReceive = fieldbus_Model.helperFuncs.getDataSize(fieldbus_Model.parameters.dataTypesReceive) + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "New data size to receive = " .. tostring(fieldbus_Model.totalDataSizeReceive)) + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.deleteDataToReceiveViaUI', deleteDataToReceiveViaUI) + +local function dataReceivePositionUp() + if fieldbus_Model.selectedDataReceive ~= '' and tonumber(fieldbus_Model.selectedDataReceive) then + fieldbus_Model.dataReceivePositionUp(tonumber(fieldbus_Model.selectedDataReceive)) + end + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.dataReceivePositionUp', dataReceivePositionUp) + +local function dataReceivePositionDown() + if fieldbus_Model.selectedDataReceive ~= '' and tonumber(fieldbus_Model.selectedDataReceive) then + fieldbus_Model.dataReceivePositionDown(tonumber(fieldbus_Model.selectedDataReceive)) + end + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.dataReceivePositionDown', dataReceivePositionDown) + +--- Function to check if selection in UIs DynamicTable can find related pattern +---@param selection string Full text of selection +---@param pattern string Pattern to search for +local function checkSelection(selection, pattern) + if selection ~= "" then + local _, pos = string.find(selection, pattern) + if pos == nil then + else + pos = tonumber(pos) + if pattern ~= '"selected":true' then + local endPos = string.find(selection, '"', pos+1) + local tempSelection = string.sub(selection, pos+1, endPos-1) + if tempSelection ~= nil and tempSelection ~= '-' then + return tempSelection + end + else + return '' + end + end + end + return nil +end + +local function selectDataTransmitViaUI(selection) + local tempSelection = checkSelection(selection, '"DTC_IDTransmit":"') + if tempSelection then + local isSelected = checkSelection(selection, '"selected":true') + if isSelected then + _G.logger:fine(nameOfModule .. ": Selected data no." .. tostring(tempSelection)) + fieldbus_Model.selectedDataTransmit = tempSelection + + local tempName = fieldbus_Model.parameters.dataNamesTransmit[tonumber(tempSelection)] + + fieldbus_Model.dataNameTransmit = tempName + fieldbus_Model.registerEventTransmit = fieldbus_Model.parameters.registeredEventsTransmit[tempName] + fieldbus_Model.convertDataTransmit = fieldbus_Model.parameters.convertDataTypesTransmit[tempName] + fieldbus_Model.bigEndianTransmit = fieldbus_Model.parameters.bigEndiansTransmit[tempName] + fieldbus_Model.dataTypeTransmit = fieldbus_Model.parameters.dataTypesTransmit[tempName] + + Script.notifyEvent("Fieldbus_OnNewStatusDataNameTransmit", fieldbus_Model.dataNameTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusRegisteredEventTransmit", fieldbus_Model.registerEventTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusConvertDataTransmit", fieldbus_Model.convertDataTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusBigEndianTransmit", fieldbus_Model.bigEndianTransmit) + Script.notifyEvent("Fieldbus_OnNewStatusDataTypeTransmit", fieldbus_Model.dataTypeTransmit) + else + fieldbus_Model.selectedDataTransmit = '' + end + handleOnExpiredTmrFieldbus() + end +end +Script.serveFunction('CSK_Fieldbus.selectDataTransmitViaUI', selectDataTransmitViaUI) + +local function selectDataReceiveViaUI(selection) + local tempSelection = checkSelection(selection, '"DTC_IDReceive":"') + if tempSelection then + local isSelected = checkSelection(selection, '"selected":true') + if isSelected then + _G.logger:fine(nameOfModule .. ": Selected receive data no." .. tostring(tempSelection)) + fieldbus_Model.selectedDataReceive = tempSelection + + local tempName = fieldbus_Model.parameters.dataNamesReceive[tonumber(tempSelection)] + + fieldbus_Model.dataNameReceive = tempName + fieldbus_Model.convertDataReceive = fieldbus_Model.parameters.convertDataTypesReceive[tempName] + fieldbus_Model.bigEndianReceive = fieldbus_Model.parameters.bigEndiansReceive[tempName] + fieldbus_Model.dataTypeReceive = fieldbus_Model.parameters.dataTypesReceive[tempName] + + Script.notifyEvent("Fieldbus_OnNewStatusDataNameReceive", fieldbus_Model.dataNameReceive) + Script.notifyEvent("Fieldbus_OnNewStatusConvertDataReceive", fieldbus_Model.convertDataReceive) + Script.notifyEvent("Fieldbus_OnNewStatusBigEndianReceive", fieldbus_Model.bigEndianReceive) + Script.notifyEvent("Fieldbus_OnNewStatusDataTypeReceive", fieldbus_Model.dataTypeReceive) + else + fieldbus_Model.selectedDataReceive = '' + end + handleOnExpiredTmrFieldbus() + end +end +Script.serveFunction('CSK_Fieldbus.selectDataReceiveViaUI', selectDataReceiveViaUI) + +local function setTempTransmitData(data) + fieldbus_Model.tempDataTransmit = data +end +Script.serveFunction('CSK_Fieldbus.setTempTransmitData', setTempTransmitData) + +local function triggerTempDataViaUI() + if fieldbus_Model.selectedDataTransmit ~= '' then + + local value + if fieldbus_Model.parameters.dataTypesTransmit[fieldbus_Model.dataNameTransmit] == 'CHAR' or fieldbus_Model.parameters.dataTypesTransmit[fieldbus_Model.dataNameTransmit] == 'STRING' then + value = fieldbus_Model.tempDataTransmit + else + value = tonumber(fieldbus_Model.tempDataTransmit) + end + + -- Temporarily activate conversion + local tempConvertStatus = fieldbus_Model.parameters.convertDataTypesTransmit[fieldbus_Model.dataNameTransmit] + fieldbus_Model.parameters.convertDataTypesTransmit[fieldbus_Model.dataNameTransmit] = true + fieldbus_Model.dataUpdateFunctions[fieldbus_Model.dataNameTransmit](value) + fieldbus_Model.parameters.convertDataTypesTransmit[fieldbus_Model.dataNameTransmit] = tempConvertStatus + else + _G.logger:fine(nameOfModule .. ": No data position selected.") + end + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.triggerTempDataViaUI', triggerTempDataViaUI) + +local function resetTransmitData() + fieldbus_Model.resetTransmitData() + handleOnExpiredTmrFieldbus() +end +Script.serveFunction('CSK_Fieldbus.resetTransmitData', resetTransmitData) -- ***************************************************************** -- Following function can be adapted for CSK_PersistentData module usage -- ***************************************************************** local function setParameterName(name) - _G.logger:info(nameOfModule .. ": Set parameter name: " .. tostring(name)) + _G.logger:fine(nameOfModule .. ": Set parameter name: " .. tostring(name)) fieldbus_Model.parametersName = name end Script.serveFunction("CSK_Fieldbus.setParameterName", setParameterName) @@ -159,7 +876,7 @@ local function sendParameters() if fieldbus_Model.persistentModuleAvailable then CSK_PersistentData.addParameter(fieldbus_Model.helperFuncs.convertTable2Container(fieldbus_Model.parameters), fieldbus_Model.parametersName) CSK_PersistentData.setModuleParameterName(nameOfModule, fieldbus_Model.parametersName, fieldbus_Model.parameterLoadOnReboot) - _G.logger:info(nameOfModule .. ": Send Fieldbus parameters with name '" .. fieldbus_Model.parametersName .. "' to CSK_PersistentData module.") + _G.logger:fine(nameOfModule .. ": Send Fieldbus parameters with name '" .. fieldbus_Model.parametersName .. "' to CSK_PersistentData module.") CSK_PersistentData.saveData() else _G.logger:warning(nameOfModule .. ": CSK_PersistentData module not available.") @@ -167,15 +884,44 @@ local function sendParameters() end Script.serveFunction("CSK_Fieldbus.sendParameters", sendParameters) -local function loadParameters() +--- Function to register on events provided e.g. by other modules (optionally react on timer started after loading of persistent parameters) +local function registerToEvents() + for key, value in ipairs(fieldbus_Model.parameters.dataNamesTransmit) do + fieldbus_Model.addEmptySpace(fieldbus_Model.parameters.dataTypesTransmit[value]) + fieldbus_Model.registerToEvent(fieldbus_Model.parameters.registeredEventsTransmit[value], key, value) + end +end +Timer.register(tmrWaitForSetupOfOtherModules, 'OnExpired', registerToEvents) + +local function loadParameters(wait) if fieldbus_Model.persistentModuleAvailable then local data = CSK_PersistentData.getParameter(fieldbus_Model.parametersName) if data then _G.logger:info(nameOfModule .. ": Loaded parameters from CSK_PersistentData module.") fieldbus_Model.parameters = fieldbus_Model.helperFuncs.convertContainer2Table(data) - -- If something needs to be configured/activated with new loaded data, place this here: - -- ... - -- ... + + -- If something needs to be configured/activated with new loaded data, place this here + local fbMode = Parameters.get('FBmode') + if (fbMode == 0 and fieldbus_Model.fbMode ~= 'DISABLED') or (fbMode == 1 and fieldbus_Model.fbMode ~= 'ProfinetIO') or ( fbMode == 2 and fieldbus_Model.fbMode ~= 'EtherNetIP') then + _G.logger:warning(nameOfModule .. ": Current fieldbus protocol of device differs from parameter setup. Please restart device.") + return + end + + fieldbus_Model.deregisterAllEvents() + + if not wait then + registerToEvents() + end + + fieldbus_Model.dataReceived = {} + for key, value in ipairs(fieldbus_Model.parameters.dataNamesReceive) do + fieldbus_Model.dataReceived[value] = '-' + fieldbus_Model.serveReceiveEvent(value) + end + + if fieldbus_Model.parameters.active == true then + fieldbus_Model.openCommunication() + end CSK_Fieldbus.pageCalled() else @@ -189,7 +935,7 @@ Script.serveFunction("CSK_Fieldbus.loadParameters", loadParameters) local function setLoadOnReboot(status) fieldbus_Model.parameterLoadOnReboot = status - _G.logger:info(nameOfModule .. ": Set new status to load setting on reboot: " .. tostring(status)) + _G.logger:fine(nameOfModule .. ": Set new status to load setting on reboot: " .. tostring(status)) end Script.serveFunction("CSK_Fieldbus.setLoadOnReboot", setLoadOnReboot) @@ -208,10 +954,13 @@ local function handleOnInitialDataLoaded() if parameterName then fieldbus_Model.parametersName = parameterName fieldbus_Model.parameterLoadOnReboot = loadOnReboot + else + fieldbus_Model.create() end if fieldbus_Model.parameterLoadOnReboot then - loadParameters() + tmrWaitForSetupOfOtherModules:start() -- Start timer to wait for events which could be provided by other modules + loadParameters(true) end Script.notifyEvent('Fieldbus_OnDataLoadedOnReboot') end diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua index 8d7da81..18ee75e 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua @@ -31,50 +31,130 @@ setFieldbus_ModelHandle(fieldbus_Model) --Loading helper functions if needed fieldbus_Model.helperFuncs = require('Communication/Fieldbus/helper/funcs') --- Create parameters / instances for this module -fieldbus_Model.isConnected = false -fieldbus_Model.reconnectionTimer = Timer.create() -fieldbus_Model.reconnectionTimer:setExpirationTime(5000) -fieldbus_Model.reconnectionTimer:setPeriodic(false) -fieldbus_Model.mode = 'RAW' +-- Check if specific API was loaded via +fieldbus_Model.moduleActive = _G.availableAPIs.specific --- Optionally check if specific API was loaded via -if _G.availableAPIs.specific == true then - if (fieldbus_Model.mode == 'RAW' ) then - fieldbus_Model.fieldbus = FieldBus.create('EXPLICIT_OPEN') - fieldbus_Model.fieldbus:setMode('RAW') - fieldbus_Model.fieldbus:open() - end +-- Check if needed CROWN is available on device +if FieldBus == nil then + fieldbus_Model.moduleActive = false + _G.logger:warning(nameOfModule .. ': CROWN is not available. Module is not supported...') end -fieldbus_Model.key = '1234567890123456' -- key to encrypt passwords, should be adapted! - -fieldbus_Model.messageLog = {} -- keep the latest 100 received messages +local fbMode = Parameters.get('FBmode') +if fbMode == 1 then + fieldbus_Model.fbMode = 'ProfinetIO' +elseif fbMode == 2 then + fieldbus_Model.fbMode = 'EtherNetIP' +else + fieldbus_Model.fbMode = 'DISABLED' +end -fieldbus_Model.styleForUI = 'None' -- Optional parameter to set UI style -fieldbus_Model.version = Engine.getCurrentAppVersion() -- Version of module +fieldbus_Model.handle = nil -- Fieldbus handle +fieldbus_Model.opened = false -- Status if fieldbus handle was opended. +fieldbus_Model.currentStatus = 'CLOSED' -- Current status of the fieldbus communication. +fieldbus_Model.info = 'No info available.' -- Information of the fieldbus component. + +fieldbus_Model.controlBitsIn = 0 -- Current value of the control bits transmitted to the PLC. +fieldbus_Model.boolControlBitsIn = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false} -- Status of ControlBitsIN as boolean table +fieldbus_Model.controlBitsOut = 0 -- Current value of the control bits received from the PLC. +fieldbus_Model.boolControlBitsOut = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false} -- Status of ControlBitsOUT as boolean table +fieldbus_Model.controlBitsToWrite = 0 -- Preset control bits to write. +fieldbus_Model.boolControlBitsToWrite = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false} -- Status of ControlBitsIN to write as boolean table +fieldbus_Model.bitMask = 65535 -- Preset bitMask to use for controlBits. +fieldbus_Model.boolBitMask = {true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true} -- Status of mask of ControlBitsIN to write as boolean table + +fieldbus_Model.port = 'P1' -- Fieldbus port, e.g. 'P2' + +fieldbus_Model.dataUpdateFunctions = {} -- Functions to update transmit data +fieldbus_Model.transmissionDataList = '' -- List of data entries for transmission + +fieldbus_Model.selectedDataTransmit = '' -- Number of selected data entry in UI table +fieldbus_Model.selectedDataReceive = '' -- Number of selected data entry in UI table +fieldbus_Model.tempDataTransmit = '' -- Data to temporarily set for selected transmit data + +fieldbus_Model.dataToTransmit = {} -- Preset data to transmit (binary) +fieldbus_Model.readableDataToTransmit = {} -- Readbale preset data to transmit +fieldbus_Model.fullDataToTransmit = '' -- Full binary string including all data to transmit +fieldbus_Model.dataNameTransmit = 'DataName' -- Preconfigured name of data to setup for transmission +fieldbus_Model.registerEventTransmit = 'OtherModule.OnNewEvent' -- Preconfigured event to register to receive transmit data +fieldbus_Model.convertDataTransmit = true -- Preconfigured status if received data should be converted before transmission +fieldbus_Model.bigEndianTransmit = true -- Preconfigured status of endianness for data to transmit, little endian per default +fieldbus_Model.dataTypeTransmit = 'U_INT1' -- Preconfigured data type of data to setup for transmission +fieldbus_Model.totalDataSizeTransmit = 0 -- Sum of data size to transmit + +fieldbus_Model.dataReceived = {} -- Holding received values per data entry +fieldbus_Model.dataNameReceive = 'DataName' -- Preconfigured name of data to setup for receiving +fieldbus_Model.convertDataReceive = true -- Preconfigured status if received data should be converted before transmission +fieldbus_Model.bigEndianReceive = true -- Preconfigured status of endianness for data to transmit, little endian per default +fieldbus_Model.dataTypeReceive = 'U_INT1' -- Preconfigured data type of data to setup for transmission +fieldbus_Model.totalDataSizeReceive = 0 -- Sum of data size to transmit -- Parameters to be saved permanently if wanted fieldbus_Model.parameters = {} -fieldbus_Model.parameters.flowConfigPriority = CSK_FlowConfig ~= nil or false -- Status if FlowConfig should have priority for FlowConfig relevant configurations - -fieldbus_Model.parameters.connect = true -- Config if connection should be active -fieldbus_Model.parameters.fieldbusIP = '136.129.5.1' -- IP of the MQTT broker -fieldbus_Model.parameters.connectionTimeout = 5000 -- The timeout to wait initially until the client gets - - --- List of events to register to and forward content to PLC -fieldbus_Model.parameters.forwardEvents = {} - -fieldbus_Model.parameters.useCredentials = true -- Enables/disables to use user credentials -fieldbus_Model.parameters.username = 'user' -- Username if using user credentials -if _G.availableAPIs.specific == true then - fieldbus_Model.parameters.password = Cipher.AES.encrypt('password', fieldbus_Model.key) -- Password if using user credentials +fieldbus_Model.parameters.protocol = 'DISABLED' -- Type of fieldbus communication, e.g. 'DISABLED' (0) / 'ProfinetIO' (1) / 'EtherNetIP' (2) / 'ETHERCAT' (not available yet) +fieldbus_Model.parameters.createMode = 'EXPLICIT_OPEN' -- or 'EXPLICIT_OPEN', AUTOMATIC_OPEN +fieldbus_Model.parameters.transmissionMode = 'RAW' -- or 'RAW', CONFIRMED_MESSAGING +fieldbus_Model.parameters.active = false -- Status if fieldbus connection should be established + +fieldbus_Model.parameters.dataNamesTransmit = {} -- List of names/identifiers of data entries to transmit +fieldbus_Model.parameters.registeredEventsTransmit = {} -- List of names of event to receive data to transmit +fieldbus_Model.parameters.convertDataTypesTransmit = {} -- Status if received data needs to be converted to binary or is already binary +fieldbus_Model.parameters.dataTypesTransmit = {} -- Data types of values to transmit +fieldbus_Model.parameters.bigEndiansTransmit = {} -- Little endian per default + +fieldbus_Model.parameters.dataNamesReceive = {} -- List of names/identifiers of data entries to transmit +fieldbus_Model.parameters.convertDataTypesReceive = {} -- Status if received data needs to be converted to binary or is already binary +fieldbus_Model.parameters.dataTypesReceive = {} -- Data types of values to transmit +fieldbus_Model.parameters.bigEndiansReceive = {} -- Little endian per default + +fieldbus_Model.parameters.etherNetIP = {} +fieldbus_Model.parameters.etherNetIP.storageRequestDataPath = '/public/FieldBus/EtherNetIP/StorageData.dat' -- Path to store fieldbus storage data. +fieldbus_Model.parameters.etherNetIP.addressingMode = 'STATIC' -- or 'DHCP' / 'BOOTP' +fieldbus_Model.parameters.etherNetIP.ipAddress = '192.168.0.1' -- IP address +fieldbus_Model.parameters.etherNetIP.netmask = '255.255.255.0' -- Subnet mask +fieldbus_Model.parameters.etherNetIP.gateway = '0.0.0.0' -- Gateway address +fieldbus_Model.parameters.etherNetIP.nameServer = '0.0.0.0' -- Primary name server +fieldbus_Model.parameters.etherNetIP.nameServer2 = '0.0.0.0' -- Secondary name server +fieldbus_Model.parameters.etherNetIP.domainName = '0.0.0.0' -- Domain name +fieldbus_Model.parameters.etherNetIP.macAddress = '00:00:00:00:00:00' -- MAC address of fieldbus implementation. + +fieldbus_Model.parameters.profinetIO = {} +fieldbus_Model.parameters.profinetIO.storageRequestDataPath = '/public/FieldBus/ProfinetIO/StorageData.dat' -- Path to store fieldbus storage data. +fieldbus_Model.parameters.profinetIO.deviceName = '' -- Device name +fieldbus_Model.parameters.profinetIO.remanent = false -- Status if the network configuration tool sets the current name of the device permanently (true), that is, it will be reloaded after a restart of the device. +fieldbus_Model.parameters.profinetIO.ipAddress = '192.168.0.1' -- IP address +fieldbus_Model.parameters.profinetIO.netmask = '255.255.255.0' -- Subnet mask +fieldbus_Model.parameters.profinetIO.gateway = '0.0.0.0' -- Gateway address +fieldbus_Model.parameters.profinetIO.macAddress = '00:00:00:00:00:00' -- MAC address of fieldbus implementation. + +fieldbus_Model.parameters.profinetIO.dapImDescriptor = 'Descriptor' -- The descriptor (a.k.a. 'comment') as used for the DAP’s (device access point) I&M3 data. +fieldbus_Model.parameters.profinetIO.dapImHardwareRev = 0 -- Hardware revision as used for the DAP (device access point) used in the I&M0 data. +fieldbus_Model.parameters.profinetIO.dapImInstallDate = 'YYYY-MM-DD' -- Installation date as used for the DAP’s (device access point) I&M2 data. + +-- Software revision for the DAP (device access point) used in the I&M0 data. +fieldbus_Model.parameters.profinetIO.dapImSoftwareRevPrefix = 'Prefix' -- Prefix character of the software revision of this I&M0 data. +fieldbus_Model.parameters.profinetIO.dapImSoftwareRevFuncEnhancement = 0 -- Functional enhancement identifier of the software revision of this I&M0 data. +fieldbus_Model.parameters.profinetIO.dapImSoftwareRevBugFix = 0 -- Bug fix identifier of the software revision of this I&M0 data. +fieldbus_Model.parameters.profinetIO.dapImSoftwareRevInternalChange = 0 -- Internal change identifier of the software revision of this I&M0 data. + +fieldbus_Model.parameters.profinetIO.dapImTagFunction = 'PlantDesignation' -- Function tag (a.k.a. 'plant designation') as used for the DAP’s (device access point) I&M1 data. +fieldbus_Model.parameters.profinetIO.dapImTagLocation = 'LocationIdentifier' -- Location tag (a.k.a. 'location identifier') as used for the DAP’s (device access point) I&M1 data. + +--- Function to create folder if it does not exists +---@param folder string Name of folder to create if it does not exists already +local function createFolder(folder) + local folderExists = File.isdir(folder) + if not folderExists then + local suc = File.mkdir(folder) + if not suc then + _G.logger:warning(nameOfModule .. ': Not possible to create folder on device.') + end + end end - ---fieldbus_Model.parameters.paramA = 'paramA' -- Short docu of variable ---fieldbus_Model.parameters.paramB = 123 -- Short docu of variable ---... +-- Create default folders for the module +createFolder('/public/FieldBus') +createFolder('/public/FieldBus/EtherNetIP') +createFolder('/public/FieldBus/ProfinetIO') --************************************************************************** --********************** End Global Scope ********************************** @@ -82,183 +162,796 @@ end --**********************Start Function Scope ******************************* --************************************************************************** +----------------------- +-- EtherNet/IP relevant +----------------------- + +local function getEtherNetIPConfig() + local ipAddress, netmask, gateway, nameServer, nameServer2, domainName = FieldBus.Config.EtherNetIP.getInterfaceConfig() + _G.logger:fine("New EtherNet/IP interface config:") + fieldbus_Model.parameters.etherNetIP.ipAddress = ipAddress + _G.logger:fine("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + fieldbus_Model.parameters.etherNetIP.netmask = netmask + _G.logger:fine("Gateway = " .. tostring(gateway)) + fieldbus_Model.parameters.etherNetIP.gateway = gateway + _G.logger:fine("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) + fieldbus_Model.parameters.etherNetIP.nameServer = nameServer + fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 + _G.logger:fine("DomainName = " .. tostring(domainName)) + fieldbus_Model.parameters.etherNetIP.domainName = domainName + local macAddress = FieldBus.Config.EtherNetIP.getMACAddress() + _G.logger:fine("MAC Address = " .. tostring(macAddress)) + fieldbus_Model.parameters.etherNetIP.macAddress = macAddress + CSK_Fieldbus.pageCalled() +end +fieldbus_Model.getEtherNetIPConfig = getEtherNetIPConfig + +-- Function to set EtherNet/IP config +local function setEtherNetIPConfig() + if fieldbus_Model.parameters.etherNetIP.addressingMode == 'DHCP' or fieldbus_Model.parameters.etherNetIP.addressingMode == 'BOOTP' then + local suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) + if suc then + _G.logger:fine(string.format("ENIP: Setting addressing mode to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.addressingMode)) + end + elseif fieldbus_Model.parameters.etherNetIP.ipAddress ~= '0.0.0.0' then + suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) + if suc then + local ipAddress = fieldbus_Model.parameters.etherNetIP.ipAddress + local netmask = fieldbus_Model.parameters.etherNetIP.netmask + local gateway = fieldbus_Model.parameters.etherNetIP.gateway + local nameServer = fieldbus_Model.parameters.etherNetIP.nameServer + local nameServer2 = fieldbus_Model.parameters.etherNetIP.nameServer2 + local domainName = fieldbus_Model.parameters.etherNetIP.domainName + suc = FieldBus.Config.EtherNetIP.setInterfaceConfig(ipAddress, netmask, gateway, nameServer, nameServer2, domainName) + if suc then + _G.logger:fine(string.format("ENIP: Setting IP Address to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.ipAddress)) + --_G.logger:finer(string.format("ENIP: Setting NetMask to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.netmask)) + --_G.logger:finer(string.format("ENIP: Setting Gateway IP Address to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.gateway)) + --_G.logger:finer(string.format("ENIP: Setting Name Server 1 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer)) + --_G.logger:finer(string.format("ENIP: Setting Name Server 2 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer2)) + --_G.logger:finer(string.format("ENIP: Setting Domain Name Server to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.domainName)) + else + _G.logger:severe(string.format("ENIP: Setting IP Address to '%s' failed", fieldbus_Model.parameters.etherNetIP.ipAddress)) + --_G.logger:severe(string.format("ENIP: Setting NetMask to '%s' failed", fieldbus_Model.parameters.etherNetIP.netmask)) + --_G.logger:severe(string.format("ENIP: Setting Gateway IP Address to '%s' failed", fieldbus_Model.parameters.etherNetIP.gateway)) + --_G.logger:severe(string.format("ENIP: Setting Name Server 1 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer)) + --_G.logger:severe(string.format("ENIP: Setting Name Server 2 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer2)) + --_G.logger:severe(string.format("ENIP: Setting Domain Name Server to '%s' failed", fieldbus_Model.parameters.etherNetIP.domainName)) + end + end + end + CSK_Fieldbus.pageCalled() + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) +end +fieldbus_Model.setEtherNetIPConfig = setEtherNetIPConfig + + +-- Function to react on received EtherNet/IP addressing mode +---@param addressingMode FieldBus.Config.EtherNetIP.AddressingMode Addressing mode for the ip parameters. +local function handleOnAddressingModeChanged(addressingMode) + _G.logger:finer("New EtherNet/IP AdressingMode = " .. tostring(addressingMode)) +end + +-- Function to react on received EtherNet/IP interface config. +---@param ipAddress string IP address. +---@param netmask string Subnetmask. +---@param gateway string Gateway IP address. +---@param nameServer? string Primary name server. +---@param nameServer2? string Secondary name server. +---@param domainName? string Default domain name. +local function handleOnEthernetIPInterfaceConfigChanged(ipAddress, netmask, gateway, nameServer, nameServer2, domainName) + _G.logger:fine("New EtherNet/IP interface config:") + _G.logger:finer("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + _G.logger:finer("Gateway = " .. tostring(gateway)) + _G.logger:finer("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) + _G.logger:finer("DomainName = " .. tostring(domainName)) +end + +-- Function to react on FieldbusStoreRequest +---@param storageHandle FieldBus.StorageRequest Object containing the data to be saved or loaded +local function handleOnEtherNetIPFieldbusStorageRequest(storageHandle) + local operation = FieldBus.StorageRequest.getOperation(storageHandle) + _G.logger:fine('StorageRequest operation = ' .. tostring(operation)) + if operation == 'LOAD' then + + -- Check if file exists + local dataFile = File.open(fieldbus_Model.parameters.etherNetIP.storageRequestDataPath, 'rb') + local setSuc = false + + if dataFile then + local data = File.read(dataFile) + File.close(dataFile) + if FieldBus.StorageRequest.setData(storageHandle, data) then + _G.logger:fine("Setting data = " .. tostring(true)) + else + _G.logger:info("Setting data = " .. tostring(false)) + getEtherNetIPConfig() + end + else + _G.logger:info("Not able to LOAD data.") + end + + --[[if setSuc then + FieldBus.StorageRequest.notifyResult(storageHandle, true) + else + FieldBus.StorageRequest.notifyResult(storageHandle, false) + end]] + + elseif operation == 'SAVE' then + local data = FieldBus.StorageRequest.getData(storageHandle) + local dataFile = File.open(fieldbus_Model.parameters.etherNetIP.storageRequestDataPath, 'wb') + local suc = File.write(dataFile, data) + if suc then + FieldBus.StorageRequest.notifyResult(storageHandle, true) + else + FieldBus.StorageRequest.notifyResult(storageHandle, false) + end + File.close(dataFile) + _G.logger:fine("Result to write SR = " .. tostring(suc)) + CSK_Fieldbus.pageCalled() + end +end + +----------------------- +-- ProfinetIO relevant +----------------------- + +--- Function to apply ProfinetIO config +local function applyProfinetIOConfig() + local suc = FieldBus.Config.ProfinetIO.applyConfig() + _G.logger:fine("Success of ApplyConfig = " .. tostring(suc)) +end +fieldbus_Model.applyProfinetIOConfig = applyProfinetIOConfig + +--- Function to store ProfinetIO config +local function storeProfinetIOConfig() + local suc = FieldBus.Config.ProfinetIO.storeConfig() + _G.logger:fine('Store config = ' .. tostring(suc)) +end +fieldbus_Model.storeProfinetIOConfig = storeProfinetIOConfig + +--- Function to react on received ProfinetIO DeviceName. +---@param deviceName string Currently active name of the device +---@param remanent bool True if the network configuration tool sets the current name of the device permanently, that is, it will be reloaded after a restart of the device. +local function handleOnDeviceNameChanged(deviceName, remanent) + _G.logger:fine("Received DeviceName info!") + _G.logger:fine("Name = " .. tostring(deviceName)) + _G.logger:fine("Remanent = " .. tostring(remanent)) + + fieldbus_Model.parameters.profinetIO.deviceName = deviceName + fieldbus_Model.parameters.profinetIO.remanent = remanent + + FieldBus.Config.ProfinetIO.setDeviceName(fieldbus_Model.parameters.profinetIO.deviceName) + applyProfinetIOConfig() + + if remanent == true then + storeProfinetIOConfig() + end + + CSK_Fieldbus.pageCalled() + +end + +-- Function to react on received ProfinetIO interface config. +---@param ipAddress string Currently active (applied) IP address +---@param subnetMask string Currently active (applied) subnet mask +---@param gateway string Currently active (applied) gateway address +---@param remanent bool True if the network configuration tool sets the current IP address settings permanently, that is, it will be reloaded after a restart of the device. +local function handleOnProfinetIOInterfaceConfigChanged(ipAddress, subnetMask, gateway, remanent) + _G.logger:fine("New ProfinetIO interface config:") + _G.logger:fine("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(subnetMask)) + _G.logger:fine("Gateway = " .. tostring(gateway)) + _G.logger:fine("Remanent = " .. tostring(remanent)) + + fieldbus_Model.parameters.profinetIO.ipAddress = ipAddress + fieldbus_Model.parameters.profinetIO.subnetMask = subnetMask + fieldbus_Model.parameters.profinetIO.gateway = gateway + fieldbus_Model.parameters.profinetIO.remanent = remanent + + FieldBus.Config.ProfinetIO.setInterfaceConfig(fieldbus_Model.parameters.profinetIO.ipAddress, fieldbus_Model.parameters.profinetIO.subnetMask, fieldbus_Model.parameters.profinetIO.gateway) + + applyProfinetIOConfig() + + if remanent == true then + storeProfinetIOConfig() + end + CSK_Fieldbus.pageCalled() + +end + +--- Function to get DAP I&M Config info +local function getDapImConfigInfo() + fieldbus_Model.parameters.profinetIO.dapImDescriptor = FieldBus.Config.ProfinetIO.getDapImDescriptor() + fieldbus_Model.parameters.profinetIO.dapImHardwareRev = FieldBus.Config.ProfinetIO.getDapImHardwareRev() + fieldbus_Model.parameters.profinetIO.dapImInstallDate = FieldBus.Config.ProfinetIO.getDapImInstallDate() + fieldbus_Model.parameters.profinetIO.dapImSoftwareRevPrefix, fieldbus_Model.parameters.profinetIO.dapImSoftwareRevFuncEnhancement, fieldbus_Model.parameters.profinetIO.dapImSoftwareRevBugFix, fieldbus_Model.parameters.profinetIO.dapImSoftwareRevInternalChange = FieldBus.Config.ProfinetIO.getDapImSoftwareRev() + fieldbus_Model.parameters.profinetIO.tagFunction = FieldBus.Config.ProfinetIO.getDapImTagFunction() + fieldbus_Model.parameters.profinetIO.tagLocation = FieldBus.Config.ProfinetIO.getDapImTagLocation() +end +fieldbus_Model.getDapImConfigInfo = getDapImConfigInfo + +--- Function to set DAP I&M config +local function setDapImConfig() + FieldBus.Config.ProfinetIO.setDapImDescriptor(fieldbus_Model.parameters.profinetIO.dapImDescriptor) + FieldBus.Config.ProfinetIO.setDapImInstallDate(fieldbus_Model.parameters.profinetIO.dapImInstallDate) + FieldBus.Config.ProfinetIO.setDapImTagFunction(fieldbus_Model.parameters.profinetIO.tagFunction) + FieldBus.Config.ProfinetIO.setDapImTagLocation(fieldbus_Model.parameters.profinetIO.tagLocation) +end +fieldbus_Model.setDapImConfig = setDapImConfig + +--- Function to store DAP I&M config +local function storeDapImData() + local suc = FieldBus.Config.ProfinetIO.storeDapImData() +end +fieldbus_Model.storeDapImData = storeDapImData + +--- Function to get DAP I&M config +local function getProfinetIOConfigInfo() + fieldbus_Model.parameters.profinetIO.deviceName = FieldBus.Config.ProfinetIO.getDeviceName() + fieldbus_Model.parameters.profinetIO.ipAddress, fieldbus_Model.parameters.profinetIO.subnetMask, fieldbus_Model.parameters.profinetIO.gateway, fieldbus_Model.parameters.profinetIO.remanent = FieldBus.Config.ProfinetIO.getInterfaceConfig() + + local macAddress = FieldBus.Config.ProfinetIO.getMACAddress('INTERFACE') + if macAddress then + fieldbus_Model.parameters.profinetIO.macAddress = macAddress + else + fieldbus_Model.parameters.profinetIO.macAddress = '' + end + getDapImConfigInfo() + + CSK_Fieldbus.pageCalled() + +end +fieldbus_Model.getProfinetIOConfigInfo = getProfinetIOConfigInfo + +--- Function to react on FieldbusStoreRequest +---@param storageHandle FieldBus.StorageRequest Object containing the data to be saved or loaded +local function handleOnProfinetIOFieldbusStorageRequest(storageHandle) + local operation = FieldBus.StorageRequest.getOperation(storageHandle) + _G.logger:fine('StorageRequest operation = ' .. tostring(operation)) + if operation == 'LOAD' then + -- Check if file exists + local dataFile = File.open(fieldbus_Model.parameters.profinetIO.storageRequestDataPath, 'rb') + local setSuc = false + + if dataFile then + local data = File.read(dataFile) + File.close(dataFile) + setSuc = FieldBus.StorageRequest.setData(storageHandle, data) + _G.logger:fine("Setting data = " .. tostring(setSuc)) + getProfinetIOConfigInfo() + else + _G.logger:info("Not able to LOAD data.") + end + + if setSuc then + FieldBus.StorageRequest.notifyResult(storageHandle, true) + else + FieldBus.StorageRequest.notifyResult(storageHandle, false) + end + + elseif operation == 'SAVE' then + local data = FieldBus.StorageRequest.getData(storageHandle) + local dataFile = File.open(fieldbus_Model.parameters.profinetIO.storageRequestDataPath, 'wb') + + local suc = File.write(dataFile, data) + File.close(dataFile) + _G.logger:fine("Result to write SR = " .. tostring(suc)) + + if suc then + FieldBus.StorageRequest.notifyResult(storageHandle, true) + else + FieldBus.StorageRequest.notifyResult(storageHandle, false) + end + CSK_Fieldbus.pageCalled() + end +end + +--TODO only for SIM2000Eco... +-------------------------------------- --[[ --- Some internal code docu for local used function to do something ----@param content auto Some info text if function is not already served -local function doSomething(content) - _G.logger:info(nameOfModule .. ": Do something") - fieldbus_Model.counter = fieldbus_Model.counter + 1 +local function getProtocolInfo() + protocol = FieldBus.Config.getProtocol() end -fieldbus_Model.doSomething = doSomething +fieldbus_Model.getProtocolInfo = getProtocolInfo + +local function setProtocolConfig() + Fieldbus_Controller.Config.setProtocol() +end +fieldbus_Model.setProtocolConfig = setProtocolConfig ]] +-------------------------------------- + +----------------------- +-- General functions -- +----------------------- + +-- Function to react on received data of PLC. +---@param data binary Received data. +local function handleOnNewData(data) + local dataSize = #data + _G.logger:fine("Received " .. tostring(dataSize) .. " Bytes = " .. tostring(data)) + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "Received " .. tostring(dataSize) .. " Bytes") + Script.notifyEvent("Fieldbus_OnNewStatusReceivedData", data) + + local startPos = 1 + for _, value in ipairs(fieldbus_Model.parameters.dataNamesReceive) do + local dataSize = fieldbus_Model.helperFuncs.getTypeSize(fieldbus_Model.parameters.dataTypesReceive[value]) + if dataSize ~= nil then + local dataPart = string.sub(data, startPos, startPos+dataSize-1) + + -- check if value needs to be unpacked first + if fieldbus_Model.parameters.convertDataTypesReceive[value] and dataPart ~= nil then + dataPart = fieldbus_Model.helperFuncs.convertFromBinary(dataPart, fieldbus_Model.parameters.dataTypesReceive[value], fieldbus_Model.parameters.bigEndiansReceive[value]) + end + + fieldbus_Model.dataReceived[value] = dataPart + Script.notifyEvent('Fieldbus_OnNewData_' .. value, dataPart) + startPos = startPos + dataSize + else + break + end + end + Script.notifyEvent("Fieldbus_OnNewStatusDataReceivingList", fieldbus_Model.helperFuncs.createJsonListReceiveData(fieldbus_Model.parameters.dataNamesReceive, fieldbus_Model.parameters.dataTypesReceive, fieldbus_Model.parameters.convertDataTypesReceive, fieldbus_Model.parameters.bigEndiansReceive, fieldbus_Model.dataReceived, fieldbus_Model.selectedDataReceive)) +end ---- Function to react on UI style change -local function handleOnStyleChanged(theme) - fieldbus_Model.styleForUI = theme - Script.notifyEvent("Fieldbus_OnNewStatusCSKStyle", fieldbus_Model.styleForUI) +--- Function to react on received ctrl bits of PLC. +---@param ctrlBits int ctrl bits out +local function handleOnControlBitsOutChanged(ctrlBits) + _G.logger:fine("New CtrlBitsOut = " .. tostring(ctrlBits)) + fieldbus_Model.controlBitsOut = ctrlBits + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsOut", fieldbus_Model.controlBitsOut) + fieldbus_Model.boolControlBitsOut = fieldbus_Model.helperFuncs.toBits(fieldbus_Model.controlBitsOut) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsOutTable", fieldbus_Model.boolControlBitsOut) end -Script.register('CSK_PersistentData.OnNewStatusCSKStyle', handleOnStyleChanged) +--- Function to get various information about the fieldbus, its componentes and internals. +local function getInfo() + fieldbus_Model.info = FieldBus.getInfo(fieldbus_Model.handle) + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) +end +fieldbus_Model.getInfo = getInfo ---- Function to create and notify internal Fieldbus log messages -local function sendLog() - local tempLog2Send = '' - for i=#fieldbus_Model.messageLog, 1, -1 do - tempLog2Send = tempLog2Send .. fieldbus_Model.messageLog[i] .. '\n' +--- Function to get status information about the fieldbus. +local function getStatus() + fieldbus_Model.currentStatus = FieldBus.getStatus(fieldbus_Model.handle) + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusStatus", fieldbus_Model.currentStatus) +end +fieldbus_Model.getStatus = getStatus + +--TODO +local function deregisterFieldbusEvents() + if fieldbus_Model.handle then + --FieldBus.deregister(fieldbus_Model.handle, 'OnStatusChanged', handleOnStatusChanged) + FieldBus.deregister(fieldbus_Model.handle, 'OnNewData', handleOnNewData) + FieldBus.deregister(fieldbus_Model.handle, 'OnControlBitsOutChanged', handleOnControlBitsOutChanged) end - Script.notifyEvent('Fieldbus_OnNewLog', tempLog2Send) + Script.deregister('FieldBus.Config.EtherNetIP.OnFieldbusStorageRequest', handleOnEtherNetIPFieldbusStorageRequest) + Script.deregister('FieldBus.Config.EtherNetIP.OnAddressingModeChanged', handleOnAddressingModeChanged) + Script.deregister('FieldBus.Config.EtherNetIP.OnInterfaceConfigChanged', handleOnEthernetIPInterfaceConfigChanged) + Script.deregister('FieldBus.Config.ProfinetIO.OnFieldbusStorageRequest', handleOnProfinetIOFieldbusStorageRequest) + Script.deregister('FieldBus.Config.ProfinetIO.OnDeviceNameChanged', handleOnDeviceNameChanged) + Script.deregister('FieldBus.Config.ProfinetIO.OnInterfaceConfigChanged', handleOnProfinetIOInterfaceConfigChanged) end -fieldbus_Model.sendLog = sendLog ---- Function to add new message to internal Fieldbus log messages ----@param msg string Message -local function addMessageLog(msg) - table.insert(fieldbus_Model.messageLog, 1, DateTime.getTime() .. ': ' .. msg) - if #fieldbus_Model.messageLog == 100 then - table.remove(fieldbus_Model.messageLog, 100) +-- Function to react on new state of the fieldbus communication. +---@param status FieldBus.Status New state of the fieldbus communication. +local function handleOnStatusChanged(status) + _G.logger:info("New status = " .. tostring(status)) + fieldbus_Model.currentStatus = status + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusStatus", fieldbus_Model.currentStatus) + getInfo() + + if fieldbus_Model.currentStatus == 'CLOSED' then + deregisterFieldbusEvents() + Script.releaseObject(fieldbus_Model.handle) + fieldbus_Model.handle = nil + collectgarbage() end - sendLog() + + if status == 'OPENED' or status == 'ONLINE' then + fieldbus_Model.opened = true + elseif status == 'OFFLINE' or status == 'ERROR' or status == 'CLOSED' then + fieldbus_Model.opened = false + end + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusActive", fieldbus_Model.opened) end -fieldbus_Model.addMessageLog = addMessageLog ---@setEthIP_Out(bit:int, value:Bool) -local function setEthIP_Out(bit, value) - if bit < 16 and bit >= 0 then - local bitWrite = 0 - if value then - bitWrite = 65535 +--- Function to create fieldbus communication handle +local function create() + if fieldbus_Model.fbMode ~= 'DISABLED' then + if not fieldbus_Model.handle then + fieldbus_Model.handle = FieldBus.create(fieldbus_Model.parameters.createMode) + if fieldbus_Model.handle then + FieldBus.setMode(fieldbus_Model.handle, fieldbus_Model.parameters.transmissionMode) + _G.logger:fine("Successfully created Fieldbus handle.") + getInfo() + getStatus() + + deregisterFieldbusEvents() + FieldBus.register(fieldbus_Model.handle, 'OnStatusChanged', handleOnStatusChanged) + FieldBus.register(fieldbus_Model.handle, 'OnNewData', handleOnNewData) + FieldBus.register(fieldbus_Model.handle, 'OnControlBitsOutChanged', handleOnControlBitsOutChanged) + if fieldbus_Model.fbMode == 'EtherNetIP' then + Script.register('FieldBus.Config.EtherNetIP.OnFieldbusStorageRequest', handleOnEtherNetIPFieldbusStorageRequest) + Script.register('FieldBus.Config.EtherNetIP.OnAddressingModeChanged', handleOnAddressingModeChanged) + Script.register('FieldBus.Config.EtherNetIP.OnInterfaceConfigChanged', handleOnEthernetIPInterfaceConfigChanged) + + elseif fieldbus_Model.fbMode == 'ProfinetIO' then + Script.register('FieldBus.Config.ProfinetIO.OnFieldbusStorageRequest', handleOnProfinetIOFieldbusStorageRequest) + Script.register('FieldBus.Config.ProfinetIO.OnDeviceNameChanged', handleOnDeviceNameChanged) + Script.register('FieldBus.Config.ProfinetIO.OnInterfaceConfigChanged', handleOnProfinetIOInterfaceConfigChanged) + + end + else + _G.logger:warning("Not able to create Fieldbus handle.") + end + else + _G.logger:fine("Handle already exists.") + Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) + end + end +end +fieldbus_Model.create = create + +--- Function to set transmission mode +---@param mode string Mode to use +local function setTransmissionMode(mode) + if fieldbus_Model.opened == false then + if fieldbus_Model.parameters.createMode == 'EXPLICIT_OPEN' and fieldbus_Model.opened ~= true then + fieldbus_Model.parameters.transmissionMode = mode + if fieldbus_Model.handle then + FieldBus.setMode(fieldbus_Model.handle, fieldbus_Model.parameters.transmissionMode) + end + else + _G.logger:info("Transmission mode only selectable if create mode is 'EXPLICIT_OPEN'.") end - local bitMask = 2 ^ bit - FieldBus.writeControlBitsIn(fieldbus_Model.fieldbus, bitWrite, bitMask) else - print("Warning: invalid bit chosen, doesn't exit") - end - - local function toBits(num, bits) - -- returns a table of bits, least significant first. - local t={} -- will contain the bits - bits = bits or 8 - local rest - while num > 0 do - rest = math.fmod(num,2) - t[#t+1] = rest - num = math.floor((num - rest) / 2) + _G.logger:info("Cannot set mode of fieldbus, it is already open.") + end + Script.notifyEvent("Fieldbus_OnNewStatusTransmissionMode", fieldbus_Model.parameters.transmissionMode) +end +fieldbus_Model.setTransmissionMode = setTransmissionMode + +--- Function to open fieldbus communication +local function openCommunication() + local success = false + create() + fieldbus_Model.parameters.active = true + if fieldbus_Model.handle then + if fieldbus_Model.parameters.createMode == 'EXPLICIT_OPEN' then + fieldbus_Model.handle:open() end - for i = #t + 1, bits do -- fill empty bits with 0 - t[i] = 0 + success = true + else + _G.logger:warning("Not able to open fieldbus communication.") + end + return success +end +fieldbus_Model.openCommunication = openCommunication + +--- Function to close fieldbus communication +local function closeCommunication() + if fieldbus_Model.handle then + fieldbus_Model.handle:close() + fieldbus_Model.parameters.active = false + end +end +fieldbus_Model.closeCommunication = closeCommunication + +--- Function to read controlBitsIn +local function readControlBitsIn() + if fieldbus_Model.handle then + fieldbus_Model.controlBitsIn = fieldbus_Model.handle:readControlBitsIn() + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsIn", fieldbus_Model.controlBitsIn) + fieldbus_Model.boolControlBitsIn = fieldbus_Model.helperFuncs.toBits(fieldbus_Model.controlBitsIn) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInTable", fieldbus_Model.boolControlBitsIn) + end +end +fieldbus_Model.readControlBitsIn = readControlBitsIn + +--- Function to read controlBitsOut +local function readControlBitsOut() + if fieldbus_Model.handle then + fieldbus_Model.controlBitsOut = fieldbus_Model.handle:readControlBitsOut() + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsOut", fieldbus_Model.controlBitsOut) + fieldbus_Model.boolControlBitsOut = fieldbus_Model.helperFuncs.toBits(fieldbus_Model.controlBitsOut) + Script.notifyEvent("Fieldbus_OnNewStatusControlBitsOutTable", fieldbus_Model.boolControlBitsOut) + end +end +fieldbus_Model.readControlBitsOut = readControlBitsOut + +--- Function to transmit data +---@param data binary Data content to transmit +local function transmit(data) + if fieldbus_Model.handle then + local numberOfBytes = fieldbus_Model.handle:transmit(data) + if numberOfBytes ~= 0 then + _G.logger:fine("Send " .. tostring(numberOfBytes) .. " data Bytes.") + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "Send " .. tostring(numberOfBytes) .. " data Bytes.") + else + _G.logger:warning("Transmit error.") + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "Transmit error.") end - return t + else + _G.logger:info("No connection available to transmit.") + Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', "No connection available to transmit.") + end +end +fieldbus_Model.transmit = transmit + +--- Function to write controlBitsIn +---@param controlBits int Bits to write +---@param bitMask int Mask to use for bits +local function writeControlBitsIn(controlBits, bitMask) + if fieldbus_Model.handle then + _G.logger:fine("Send controlBits") + fieldbus_Model.handle:writeControlBitsIn(controlBits, bitMask) + end +end +fieldbus_Model.writeControlBitsIn = writeControlBitsIn + +--- Function to write data to table to transmit +---@param pos int Position of data to update +---@param data auto Data content to set +local function updateTransmitData(pos, data) + --_G.logger:fine("Set data" .. tostring(pos) .. ' with data = ' .. tostring(data)) --DEBUG + fieldbus_Model.dataToTransmit[pos] = data + + fieldbus_Model.fullDataToTransmit = '' + for key, value in ipairs(fieldbus_Model.dataToTransmit) do + fieldbus_Model.fullDataToTransmit = fieldbus_Model.fullDataToTransmit .. value end - local tempFieldBusBitsIn = FieldBus.readControlBitsIn(fieldbus_Model.fieldbus) - local bitTable = toBits(tempFieldBusBitsIn, 16) - for i = 1, #bitTable//2, 1 do - bitTable[i], bitTable[#bitTable - i + 1] = bitTable[#bitTable - i + 1], bitTable[i] + --DEBUG + --[[ + local readableTransmitData = '' + for key, value in ipairs(fieldbus_Model.readableDataToTransmit) do + if readableTransmitData == '' then + readableTransmitData = value + else + readableTransmitData = readableTransmitData .. ',' .. value + end end - local reversedBTable = table.concat(bitTable) --[AR] - Script.notifyEvent("GuiUpdateCtrlBitOutput", bitTable) - _g_log('FINER', "setEthIP_Out: Bit ".. bit .. tostring(value) .."Value" .. DateTime.getDateTime(), '000') + _G.logger:fine("Send: " .. readableTransmitData) + + -- Additional debugging + --_G.logger:fine(fieldbus_Model.fullDataToTransmit) + --_G.logger:fine(#fieldbus_Model.fullDataToTransmit) + --Script.notifyEvent('Fieldbus_OnNewStatusLogMessage', tostring(fieldbus_Model.fullDataToTransmit) .. ', Send data bytes = ' .. tostring(#fieldbus_Model.fullDataToTransmit)) + --Script.notifyEvent("Fieldbus_OnNewStatusDataToTransmit", fieldbus_Model.dataToTransmit) + ]] + --TODO + --print(fieldbus_Model.fullDataToTransmit) + --print(#fieldbus_Model.fullDataToTransmit) + + if fieldbus_Model.currentStatus == 'ONLINE' then + transmit(fieldbus_Model.fullDataToTransmit) + end end +fieldbus_Model.updateTransmitData = updateTransmitData ---@newControlBitsOut(value:int) -local function newControlBitsOut(value) - _g_log('FINER', "Control bits in from PLC: " .. value .. DateTime.getDateTime(), '000') - for i = 0, 15 do - if value >= 2 ^ (15 - i) then - value = value - (2 ^ (15 - i)) +--- Function to register to event of (other) module to receive data and to transmit/forward it +---@param eventName int Name of event to register +---@param dataPosition auto Position of data +---@param dataName string Identifier of data +local function registerToEvent(eventName, dataPosition, dataName) - if not ethIP_InBits[16 - i] and #ethIP_In_FunUP >= (16 - i) then - Script.notifyEvent(ethIP_In_FunUP[16 - i]) - end + local emptyData = fieldbus_Model.helperFuncs.getEmptyBinaryContent(fieldbus_Model.parameters.dataTypesTransmit[dataName]) + if fieldbus_Model.dataToTransmit[dataPosition] then + fieldbus_Model.dataToTransmit[dataPosition] = emptyData + else + table.insert(fieldbus_Model.dataToTransmit, emptyData) + end - ethIP_InBits[16 - i] = true - else - if ethIP_InBits[16 - i] and #ethIP_In_FunDOWN >= (16 - i) then - Script.notifyEvent(ethIP_In_FunDOWN[16 - i]) - end + if fieldbus_Model.readableDataToTransmit[dataPosition] then + fieldbus_Model.readableDataToTransmit[dataPosition] = 'empty' + else + table.insert(fieldbus_Model.readableDataToTransmit, 'empty') + end + + local function updateData(data) + _G.logger:fine("Set data" .. tostring(dataPosition) .. ' with data = ' .. tostring(data)) + fieldbus_Model.readableDataToTransmit[dataPosition] = data - ethIP_InBits[16 - i] = false + if fieldbus_Model.parameters.convertDataTypesTransmit[dataName] then + data = fieldbus_Model.helperFuncs.convertToBinary(data, fieldbus_Model.parameters.dataTypesTransmit[dataName], fieldbus_Model.parameters.bigEndiansTransmit[dataName]) end + updateTransmitData(dataPosition, data) end - --local ctrlBitOutStr = string.format("%02X %02X", value&0x00FF, value>>8) - --print ("Ctrl.Bits from PLC: " .. ctrlBitOutStr) - local bitTable = FieldBusSettings.toBits(value, 16) - local reversedBTable = table.concat(FieldBusSettings.reverse(bitTable)) - Script.notifyEvent("GuiUpdateCtrlBitInput", reversedBTable) + fieldbus_Model.dataUpdateFunctions[dataName] = updateData + + Script.register(eventName, fieldbus_Model.dataUpdateFunctions[dataName]) end ---This event is thrown when the control bits set by the PLC have changed. -if _G.availableAPIs.default and _G.availableAPIs.specific == true then - FieldBus.register(fieldbus_Model.fieldbus, 'OnControlBitsOutChanged', newControlBitsOut) +fieldbus_Model.registerToEvent = registerToEvent + +--- Function to deregister from all events for data to transmit +local function deregisterAllEvents() + for key, value in pairs(fieldbus_Model.parameters.dataNamesTransmit) do + Script.deregister(fieldbus_Model.parameters.registeredEventsTransmit[value], fieldbus_Model.dataUpdateFunctions[value]) + end + fieldbus_Model.dataToTransmit = {} + fieldbus_Model.readableDataToTransmit = {} end +fieldbus_Model.deregisterAllEvents = deregisterAllEvents ---- ----@param ctrlBits int Control bits set by the PLC have changed -local function handleOnControlBitsOutChanged(ctrlBits) - -- TODO: Insert your event handling code here. +--- Function to register all events for data to transmit +local function registerAllEvents() + for key, value in ipairs(fieldbus_Model.parameters.dataNamesTransmit) do + registerToEvent(fieldbus_Model.parameters.registeredEventsTransmit[value], key, value) + end +end +fieldbus_Model.registerAllEvents = registerAllEvents + +--- Function to add empty value (but with correct byte size) for data to transmit +---@param dataType string Type of data +local function addEmptySpace(dataType) + -- Insert empty spaces according to dataType... + local emptyData = fieldbus_Model.helperFuncs.getEmptyBinaryContent(dataType) + table.insert(fieldbus_Model.dataToTransmit, emptyData) + table.insert(fieldbus_Model.readableDataToTransmit, 'empty') end ---This event is thrown when the control bits set by the PLC have changed. -if _G.availableAPIs.default and _G.availableAPIs.specific == true then - FieldBus.register(fieldbus_Model.fieldbus, 'OnControlBitsOutChanged', handleOnControlBitsOutChanged) +fieldbus_Model.addEmptySpace = addEmptySpace + +--- Function to add new data entry to transmit +---@param dataName string Name/identifier of data +---@param eventName string Name of event to register +---@param convert bool Status if incoming value needs to be converted to binary +---@param dataType string Type of data +---@param bigEndian bool Type of endianess +local function addDataTransmit(dataName, eventName, convert, dataType, bigEndian) + table.insert(fieldbus_Model.parameters.dataNamesTransmit, dataName) + addEmptySpace(dataType) + + fieldbus_Model.parameters.dataTypesTransmit[dataName] = dataType + fieldbus_Model.parameters.registeredEventsTransmit[dataName] = eventName + fieldbus_Model.parameters.convertDataTypesTransmit[dataName] = convert + fieldbus_Model.parameters.bigEndiansTransmit[dataName] = bigEndian + + registerToEvent(eventName, #fieldbus_Model.parameters.dataNamesTransmit, dataName) end +fieldbus_Model.addDataTransmit = addDataTransmit ---- ----@param size int New size of the fieldbus input frame buffer. -local function handleOnInputSizeChanged(size) - -- TODO: Insert your event handling code here. +--- Function to serve events to notify for received values +---@param dataName string Name/identifier of data +local function serveReceiveEvent(dataName) + if not Script.isServedAsEvent('CSK_Fieldbus.OnNewData_' .. dataName) then + Script.serveEvent('CSK_Fieldbus.OnNewData_' .. dataName, 'Fieldbus_OnNewData_' .. dataName, 'auto:?') + end end ---This event is thrown when the size of the FieldBus input frame buffer changes. -if _G.availableAPIs.default and _G.availableAPIs.specific == true then - FieldBus.register(fieldbus_Model.fieldbus, 'OnInputSizeChanged', handleOnInputSizeChanged) +fieldbus_Model.serveReceiveEvent = serveReceiveEvent + +--- Function to add new data entry to receive +---@param dataName string Name/identifier of data +---@param convert bool Status if incoming value needs to be converted to binary +---@param dataType string Type of data +---@param bigEndian bool Type of endianess +local function addDataReceive(dataName, convert, dataType, bigEndian) + table.insert(fieldbus_Model.parameters.dataNamesReceive, dataName) + + fieldbus_Model.parameters.dataTypesReceive[dataName] = dataType + fieldbus_Model.parameters.convertDataTypesReceive[dataName] = convert + fieldbus_Model.parameters.bigEndiansReceive[dataName] = bigEndian + fieldbus_Model.dataReceived[dataName] = '-' + + serveReceiveEvent(dataName) + end +fieldbus_Model.addDataReceive = addDataReceive ---- ----@param data binary New data from the PLC -local function handleOnNewData(data) - local message = {string.unpack(FieldBusSettings.inputFormat, data)} - Script.notifyEvent('incomingData', message) - local datahex = FieldBusSettings.hexDumpBinData(data) - Script.notifyEvent('GuiUpdateDataInPut', datahex) - print (data) - print (datahex) +--- Function to remove data entry to transmit +---@param dataNo int Number of data entry +local function removeDataTransmit(dataNo) + local dataName = fieldbus_Model.parameters.dataNamesTransmit[dataNo] + + deregisterAllEvents() + + fieldbus_Model.parameters.dataTypesTransmit[dataName] = nil + fieldbus_Model.parameters.registeredEventsTransmit[dataName] = nil + fieldbus_Model.parameters.convertDataTypesTransmit[dataName] = nil + fieldbus_Model.parameters.bigEndiansTransmit[dataName] = nil + + table.remove(fieldbus_Model.parameters.dataNamesTransmit, dataNo) + registerAllEvents() + collectgarbage() end ---This event is thrown when new data has been received from the PLC through the field bus. -if _G.availableAPIs.default and _G.availableAPIs.specific == true then - FieldBus.register(fieldbus_Model.fieldbus, 'OnNewData', handleOnNewData) +fieldbus_Model.removeDataTransmit = removeDataTransmit + +--- Function to remove data entry to receive +---@param dataNo int Number of data entry +local function removeDataReceive(dataNo) + local dataName = fieldbus_Model.parameters.dataNamesReceive[dataNo] + + fieldbus_Model.parameters.dataTypesReceive[dataName] = nil + fieldbus_Model.parameters.convertDataTypesReceive[dataName] = nil + fieldbus_Model.parameters.bigEndiansReceive[dataName] = nil + fieldbus_Model.dataReceived[dataName] = nil + + table.remove(fieldbus_Model.parameters.dataNamesReceive, dataNo) end +fieldbus_Model.removeDataReceive = removeDataReceive + +--- Function to move the position of the transmit data about one position higher +---@param dataNo int Position of data +local function dataTransmitPositionUp(dataNo) + if dataNo ~= 1 then + deregisterAllEvents() ---- ----@param size int New size of the fieldbus output frame buffer. -local function handleOnOutputSizeChanged(size) - -- TODO: Insert your event handling code here. + local tempDataName = fieldbus_Model.parameters.dataNamesTransmit[dataNo] + table.insert(fieldbus_Model.parameters.dataNamesTransmit, dataNo-1, tempDataName) + table.remove(fieldbus_Model.parameters.dataNamesTransmit, dataNo+1) + collectgarbage() + + registerAllEvents() + fieldbus_Model.selectedDataTransmit = tostring(dataNo-1) + end end ---This event is thrown when the control bits set by the PLC have changed. -if _G.availableAPIs.default and _G.availableAPIs.specific == true then - FieldBus.register(fieldbus_Model.fieldbus, 'OnOutputSizeChanged', handleOnOutputSizeChanged) +fieldbus_Model.dataTransmitPositionUp = dataTransmitPositionUp + +--- Function to move the position of the data to receive about one position higher +---@param dataNo int Position of data +local function dataReceivePositionUp(dataNo) + if dataNo ~= 1 then + + local tempDataName = fieldbus_Model.parameters.dataNamesReceive[dataNo] + table.insert(fieldbus_Model.parameters.dataNamesReceive, dataNo-1, tempDataName) + table.remove(fieldbus_Model.parameters.dataNamesReceive, dataNo+1) + collectgarbage() + + fieldbus_Model.selectedDataReceive = tostring(dataNo-1) + end end +fieldbus_Model.dataReceivePositionUp = dataReceivePositionUp ---- ----@param status FieldBus.Status New state of the fieldbus communication. -local function handleOnStatusChanged(status) - _G.logger:info("FieldBus: OnStatusChanged event received, new status: " .. status) - Script.notifyEvent("onStatusChange", status) - if (status== "ONLINE") then - _G.logger:info(nameOfModule .. ": Connected to PLC.") - Script.notifyEvent('FieldBus_OnNewConnectionStatus', "Connected to PLC") - addMessageLog('Connected to PLC.') - fieldbus_Model.reconnectionTimer:stop() - fieldbus_Model.isConnected = true - Script.notifyEvent("FieldBus_OnNewStatusCurrentlyConnected", fieldbus_Model.isConnected) - elseif (status== "OFFLINE") then - fieldbus_Model.isConnected = false +--- Function to move the position of the data to transmit about one position lower +---@param dataNo int Position of data +local function dataTransmitPositionDown(dataNo) + if dataNo ~= #fieldbus_Model.parameters.dataNamesTransmit then + deregisterAllEvents() + + local tempDataName = fieldbus_Model.parameters.dataNamesTransmit[dataNo] + table.remove(fieldbus_Model.parameters.dataNamesTransmit, dataNo) + table.insert(fieldbus_Model.parameters.dataNamesTransmit, dataNo+1, tempDataName) + collectgarbage() + + registerAllEvents() + fieldbus_Model.selectedDataTransmit = tostring(dataNo+1) end - setEthIP_Out(0, fieldbus_Model.isConnected) end ---This event is thrown when the state of the FieldBus communication changes. -if _G.availableAPIs.default and _G.availableAPIs.specific == true then - FieldBus.register(fieldbus_Model.fieldbus, "OnStatusChanged", handleOnStatusChanged) +fieldbus_Model.dataTransmitPositionDown = dataTransmitPositionDown + +--- Function to move the position of the data to receive about one position lower +---@param dataNo int Position of data +local function dataReceivePositionDown(dataNo) + if dataNo ~= #fieldbus_Model.parameters.dataNamesReceive then + + local tempDataName = fieldbus_Model.parameters.dataNamesReceive[dataNo] + table.remove(fieldbus_Model.parameters.dataNamesReceive, dataNo) + table.insert(fieldbus_Model.parameters.dataNamesReceive, dataNo+1, tempDataName) + collectgarbage() + + fieldbus_Model.selectedDataReceive = tostring(dataNo+1) + end end +fieldbus_Model.dataReceivePositionDown = dataReceivePositionDown + +--- Function to reset all data to transmit +local function resetTransmitData() + for key, value in ipairs(fieldbus_Model.parameters.dataNamesTransmit) do + local emptyData = fieldbus_Model.helperFuncs.getEmptyBinaryContent(fieldbus_Model.parameters.dataTypesTransmit[value]) + fieldbus_Model.dataToTransmit[key] = emptyData + fieldbus_Model.readableDataToTransmit[key] = 'empty' + end + if fieldbus_Model.currentStatus == 'ONLINE' then + fieldbus_Model.fullDataToTransmit = '' + for key, value in ipairs(fieldbus_Model.dataToTransmit) do + fieldbus_Model.fullDataToTransmit = fieldbus_Model.fullDataToTransmit .. value + end + transmit(fieldbus_Model.fullDataToTransmit) + end +end +fieldbus_Model.resetTransmitData = resetTransmitData --************************************************************************* --********************** End Function Scope ******************************* diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua index 3b74bbc..a835693 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua @@ -9,12 +9,13 @@ local function loadAPIs() CSK_Fieldbus = require 'API.CSK_Fieldbus' Container = require 'API.Container' - DateTime = require 'API.DateTime' Engine = require 'API.Engine' + File = require 'API.File' Log = require 'API.Log' Log.Handler = require 'API.Log.Handler' Log.SharedLogger = require 'API.Log.SharedLogger' Object = require 'API.Object' + Parameters = require 'API.Parameters' Timer = require 'API.Timer' -- Check if related CSK modules are available to be used @@ -32,13 +33,12 @@ end local function loadSpecificAPIs() -- If you want to check for specific APIs/functions supported on the device the module is running, place relevant APIs here - FieldBus = require(API.FieldBus) - Cipher = {} - Cipher.AES = require 'API.Cipher.AES' - math = require 'API.math' - Script = require 'API.Script' - string = require 'API.string' - table = require 'API.table' + -- e.g.: + FieldBus = require 'API.FieldBus' + FieldBus.Config = require 'API.FieldBus.Config' + FieldBus.Config.EtherNetIP = require 'API.FieldBus.Config.EtherNetIP' + FieldBus.Config.ProfinetIO = require 'API.FieldBus.Config.ProfinetIO' + FieldBus.StorageRequest = require 'API.FieldBus.StorageRequest' end availableAPIs.default = xpcall(loadAPIs, debug.traceback) -- TRUE if all default APIs were loaded correctly diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua index b1c30bf..07b32f3 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua @@ -142,6 +142,423 @@ local function createStringListBySimpleTable(content) end funcs.createStringListBySimpleTable = createStringListBySimpleTable +--- Function to convert value out of binary string +---@param value binary Binary string +---@param format string Format the value is packed +---@param bigEndian ?bool Status if big endian is used. Otherwise little endian is active +---@return auto result Converted value +local function convertFromBinary(value, format, bigEndian) + local result + local endianness = '<' -- little endian per default + if bigEndian == true then + endianness = '>' + end + + if format == 'DOUBLE' then + result = string.unpack(endianness .. 'd', value) + elseif format == 'FLOAT' then + result = string.unpack(endianness .. 'f', value) + elseif format == 'S_BYTE' then + result = string.unpack(endianness .. 'b', value) + elseif format == 'S_INT1' then + result = string.unpack(endianness .. 'i1', value) + elseif format == 'S_INT2' then + result = string.unpack(endianness .. 'i2', value) + elseif format == 'S_INT4' then + result = string.unpack(endianness .. 'i4', value) + elseif format == 'S_INT8' then + result = string.unpack(endianness .. 'i8', value) + elseif format == 'S_LONG' then + result = string.unpack(endianness .. 'l', value) + elseif format == 'S_SHORT' then + result = string.unpack(endianness .. 'h', value) + elseif format == 'U_BYTE' then + result = string.unpack(endianness .. 'B', value) + elseif format == 'U_INT1' then + result = string.unpack(endianness .. 'I1', value) + elseif format == 'U_INT2' then + result = string.unpack(endianness .. 'I2', value) + elseif format == 'U_INT4' then + result = string.unpack(endianness .. 'I4', value) + elseif format == 'U_INT8' then + result = string.unpack(endianness .. 'I8', value) + elseif format == 'U_LONG' then + result = string.unpack(endianness .. 'L', value) + elseif format == 'U_SHORT' then + result = string.unpack(endianness .. 'H', value) + elseif format == 'CHAR' then + result = string.unpack(endianness .. 'c1', value) + --elseif format == 'STRING' then + --result = string.unpack(endianness .. 'c14xx', value) + --result = string.unpack(endianness .. 's2', value) + end + return result +end +funcs.convertFromBinary = convertFromBinary + +--- Function to convert value to binary string +---@param value auto Value to convert +---@param format string Format the value is packed +---@param bigEndian? bool Status if big endian is used. Otherwise little endian is active +---@return binary result Converted value +local function convertToBinary(value, format, bigEndian) + local result + local endianness = '<' -- little endian per default + if bigEndian == true then + endianness = '>' + end + + if format == 'DOUBLE' then + result = string.pack(endianness .. 'd', value) + elseif format == 'FLOAT' then + result = string.pack(endianness .. 'f', value) + elseif format == 'S_BYTE' then + result = string.pack(endianness .. 'b', value) + elseif format == 'S_INT1' then + result = string.pack(endianness .. 'i1', value) + elseif format == 'S_INT2' then + result = string.pack(endianness .. 'i2', value) + elseif format == 'S_INT4' then + result = string.pack(endianness .. 'i4', value) + elseif format == 'S_INT8' then + result = string.pack(endianness .. 'i8', value) + elseif format == 'S_LONG' then + result = string.pack(endianness .. 'l', value) + elseif format == 'S_SHORT' then + result = string.pack(endianness .. 'h', value) + elseif format == 'U_BYTE' then + result = string.pack(endianness .. 'B', value) + elseif format == 'U_INT1' then + result = string.pack(endianness .. 'I1', value) + elseif format == 'U_INT2' then + result = string.pack(endianness .. 'I2', value) + elseif format == 'U_INT4' then + result = string.pack(endianness .. 'I4', value) + elseif format == 'U_INT8' then + result = string.pack(endianness .. 'I8', value) + elseif format == 'U_LONG' then + result = string.pack(endianness .. 'L', value) + elseif format == 'U_SHORT' then + result = string.pack(endianness .. 'H', value) + elseif format == 'CHAR' then + if #value >= 2 then + value = string.sub(value, 1, 1) + end + result = string.pack(endianness .. 'c1', value) + --elseif format == 'STRING' then + -- if #value >= 15 then + -- value = string.sub(value, 1, 14) + -- end + -- result = string.pack(endianness .. 's2', value) + end + return result +end +funcs.convertToBinary = convertToBinary + +--- Function to create binary string with size of related format and value '0' +---@param format string Format the value is packed +---@return binary result Empty value +local function getEmptyBinaryContent(format) + local result + + if format == 'DOUBLE' then + result = string.pack('d', 0) + elseif format == 'FLOAT' then + result = string.pack('f', 0) + elseif format == 'S_BYTE' then + result = string.pack('b', 0) + elseif format == 'S_INT1' then + result = string.pack('i1', 0) + elseif format == 'S_INT2' then + result = string.pack('i2', 0) + elseif format == 'S_INT4' then + result = string.pack('i4', 0) + elseif format == 'S_INT8' then + result = string.pack('i8', 0) + elseif format == 'S_LONG' then + result = string.pack('l', 0) + elseif format == 'S_SHORT' then + result = string.pack('h', 0) + elseif format == 'U_BYTE' then + result = string.pack('B', 0) + elseif format == 'U_INT1' then + result = string.pack('I1', 0) + elseif format == 'U_INT2' then + result = string.pack('I2', 0) + elseif format == 'U_INT4' then + result = string.pack('I4', 0) + elseif format == 'U_INT8' then + result = string.pack('I8', 0) + elseif format == 'U_LONG' then + result = string.pack('L', 0) + elseif format == 'U_SHORT' then + result = string.pack('H', 0) + elseif format == 'CHAR' then + result = string.pack('x', '') + --elseif format == 'STRING' then + -- result = string.pack('s2', '') + end + + return result +end +funcs.getEmptyBinaryContent = getEmptyBinaryContent + +--- Function to create a json string out of data transmission entries +---@param dataName string[] Table with names of data entries +---@param registerEvent string[] Table with names of registered events of data entries +---@param dataType string[] Table with data types of data entries +---@param convertData string[] Table with info if data needs to be converted +---@param bigEndian string[] Table with info about endianness of data entries +---@param values string[] Table with values to transmit +---@param selectedParam string Currently selected parameter +---@return string jsonstring JSON string +local function createJsonListTransmissionData(dataName, registerEvent, dataType, convertData, bigEndian, values, selectedParam) + + local list = {} + if dataName == nil then + list = {{DTC_IDTransmit = '-', DTC_NameTransmit = '-', DTC_EventTransmit = '-', DTC_DataTypeTransmit = '-', DTC_ConvertTransmit = '-', DTC_BigEndianTransmit = '-', DTC_ValueTransmit = '-'},} + else + + for key, value in ipairs(dataName) do + local isSelected = false + if tostring(key) == selectedParam then + isSelected = true + end + table.insert(list, {DTC_IDTransmit = tostring(key), DTC_NameTransmit = value, DTC_EventTransmit = registerEvent[value], DTC_DataTypeTransmit = dataType[value], DTC_ConvertTransmit = convertData[value], DTC_BigEndianTransmit = bigEndian[value], DTC_ValueTransmit = tostring(values[key]), selected = isSelected}) + end + + if #list == 0 then + list = {{DTC_IDTransmit = '-', DTC_NameTransmit = '-', DTC_EventTransmit = '-', DTC_DataTypeTransmit = '-', DTC_ConvertTransmit = '-', DTC_BigEndianTransmit = '-', DTC_ValueTransmit = '-'},} + end + end + + local jsonstring = funcs.json.encode(list) + return jsonstring +end +funcs.createJsonListTransmissionData = createJsonListTransmissionData + +--- Function to create a json string out of data receive entries +---@param dataName string[] Table with names of data entries +---@param dataType string[] Table with data types of data entries +---@param convertData string[] Table with info if data needs to be converted +---@param bigEndian string[] Table with info about endianness of data entries +---@param values string[] Table with received values +---@param selectedParam string Currently selected parameter +---@return string jsonstring JSON string +local function createJsonListReceiveData(dataName, dataType, convertData, bigEndian, values, selectedParam) + + local list = {} + if dataName == nil then + list = {{DTC_IDReceive = '-', DTC_NameReceive = '-', DTC_DataTypeReceive = '-', DTC_ConvertReceive = '-', DTC_BigEndianReceive = '-', DTC_ValueReceive = '-'},} + else + + for key, value in ipairs(dataName) do + local isSelected = false + if tostring(key) == selectedParam then + isSelected = true + end + table.insert(list, {DTC_IDReceive = tostring(key), DTC_NameReceive = value, DTC_DataTypeReceive = dataType[value], DTC_ConvertReceive = convertData[value], DTC_BigEndianReceive = bigEndian[value], DTC_ValueReceive = tostring(values[value]), selected = isSelected}) + end + + if #list == 0 then + list = {{DTC_IDReceive = '-', DTC_NameReceive = '-', DTC_DataTypeReceive = '-', DTC_ConvertReceive = '-', DTC_BigEndianReceive = '-', DTC_ValueReceive = '-'},} + end + end + + local jsonstring = funcs.json.encode(list) + return jsonstring +end +funcs.createJsonListReceiveData = createJsonListReceiveData + +--- Function to convert number to related bit table +---@param num int Number to convert +---@return bool[]? allValues Table of boolean values per bit +local function toBits(num) + local res = '' + local allValues = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false} + for i = 16, 1, -1 do + local temp = math.fmod(num, 2) + if temp == 1 then + allValues[(16+1)-i] = true + end + num = math.floor((num - temp)/2) + end + if num == 0 then + return allValues + else + return nil + end +end +funcs.toBits = toBits + +--- Function to convert bit values to related number +---@param values bool[]? Bit structure to convert +---@return int result Number +local function toNumber(values) + local result = 0 + for key, value in ipairs(values) do + if value == true then + result = result + 2^(key -1) + end + end + return result +end +funcs.toNumber = toNumber + +--- Function to get info about the total data size +---@param data string[] Table with info about data types to use +---@return int size Sum of all bytes of data types +local function getDataSize(data) + local size = 0 + for key, value in pairs(data) do + if value == 'DOUBLE' then + size = size + 8 + elseif value == 'FLOAT' then + size = size + 4 + elseif value == 'S_BYTE' then + size = size + 1 + elseif value == 'S_INT1' then + size = size + 1 + elseif value == 'S_INT2' then + size = size + 2 + elseif value == 'S_INT4' then + size = size + 4 + elseif value == 'S_INT8' then + size = size + 8 + elseif value == 'S_LONG' then + size = size + 4 + elseif value == 'S_SHORT' then + size = size + 2 + elseif value == 'U_BYTE' then + size = size + 1 + elseif value == 'U_INT1' then + size = size + 1 + elseif value == 'U_INT2' then + size = size + 2 + elseif value == 'U_INT4' then + size = size + 4 + elseif value == 'U_INT8' then + size = size + 8 + elseif value == 'U_LONG' then + size = size + 4 + elseif value == 'U_SHORT' then + size = size + 2 + elseif value == 'CHAR' then + size = size + 1 + --elseif value == 'STRING' then + -- size = size + 16 + end + end + return size +end +funcs.getDataSize = getDataSize + +--- Function to get info about the data size of a specific data type +---@param dataType string Data type to use +---@return int? result Amount of bytes of data type +local function getTypeSize(dataType) + if dataType == 'DOUBLE' then + return 8 + elseif dataType == 'FLOAT' then + return 4 + elseif dataType == 'S_BYTE' then + return 1 + elseif dataType == 'S_INT1' then + return 1 + elseif dataType == 'S_INT2' then + return 2 + elseif dataType == 'S_INT4' then + return 4 + elseif dataType == 'S_INT8' then + return 8 + elseif dataType == 'S_LONG' then + return 4 + elseif dataType == 'S_SHORT' then + return 2 + elseif dataType == 'U_BYTE' then + return 1 + elseif dataType == 'U_INT1' then + return 1 + elseif dataType == 'U_INT2' then + return 2 + elseif dataType == 'U_INT4' then + return 4 + elseif dataType == 'U_INT8' then + return 8 + elseif dataType == 'U_LONG' then + return 4 + elseif dataType == 'U_SHORT' then + return 2 + elseif dataType == 'CHAR' then + return 1 + --elseif dataType == 'STRING' then + -- return 16 + else + return nil + end +end +funcs.getTypeSize = getTypeSize + +local function addTabs(str, tab) + if tab > 0 then + for _=1, tab do + str = '\t' .. str + end + end + return str +end +local function min(arr) + if #arr == 0 then + return nil + end + table.sort(arr) + return arr[1] +end + +local function jsonLine2Table(intiStr, startInd, tab, resStr) + if not intiStr then return '' end + if not startInd then startInd = 1 end + if not tab then tab = 0 end + if not resStr then resStr = '' end + local compArray = {} + local nextSqBrOp = string.find(intiStr, '%[', startInd) + if nextSqBrOp then table.insert(compArray, nextSqBrOp) end + local nextSqBrCl = string.find(intiStr, '%]', startInd) + if nextSqBrCl then table.insert(compArray, nextSqBrCl) end + local nextCuBrCl = string.find(intiStr, '}', startInd) + if nextCuBrCl then table.insert(compArray, nextCuBrCl) end + local nextCuBrOp = string.find(intiStr, '{', startInd) + if nextCuBrOp then table.insert(compArray, nextCuBrOp) end + local nextComma = string.find(intiStr, ',', startInd) + if nextComma then table.insert(compArray, nextComma) end + local minVal = min(compArray) + if minVal then + local currentSymbol = string.sub(intiStr, minVal, minVal) + local content = '' + if startInd < minVal then + content = string.sub(intiStr, startInd, minVal-1) + end + if minVal == nextCuBrOp or minVal == nextSqBrOp then + resStr = resStr .. addTabs(content .. currentSymbol .. '\n', tab) + tab = tab + 1 + + elseif minVal == nextCuBrCl or minVal == nextSqBrCl then + resStr = resStr .. addTabs(content, tab) .. '\n' + tab = tab - 1 + resStr = resStr .. addTabs(currentSymbol, tab) + elseif nextComma and minVal == nextComma then + if content == '' then + resStr = resStr.. currentSymbol .. '\n' + else + resStr = resStr .. addTabs(content .. currentSymbol .. '\n', tab) + end + end + resStr = jsonLine2Table(intiStr, minVal+1, tab, resStr) + end + return resStr +end +funcs.jsonLine2Table = jsonLine2Table + return funcs --************************************************************************** From b8b26e139480448d0d67d9259412dd11a26b7b4a Mon Sep 17 00:00:00 2001 From: alexandro-rezakhani <85354050+alexandro-rezakhani@users.noreply.github.com> Date: Wed, 26 Mar 2025 01:54:40 -0400 Subject: [PATCH 5/8] Add files via upload --- .../Fieldbus/Fieldbus_Controller.lua | 28 ++- .../Communication/Fieldbus/Fieldbus_Model.lua | 178 ++++++++++-------- 2 files changed, 124 insertions(+), 82 deletions(-) diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua index 24f62d3..c44607c 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua @@ -49,6 +49,7 @@ Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusInfo', 'Fieldbus_OnNewStatusF Script.serveEvent('CSK_Fieldbus.OnNewStatusCreateMode', 'Fieldbus_OnNewStatusCreateMode') Script.serveEvent('CSK_Fieldbus.OnNewStatusExplicitModeActive', 'Fieldbus_OnNewStatusExplicitModeActive') +Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusMode', 'Fieldbus_OnNewStatusFieldbusMode') Script.serveEvent('CSK_Fieldbus.OnNewStatusTransmissionMode', 'Fieldbus_OnNewStatusTransmissionMode') Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsIn', 'Fieldbus_OnNewStatusControlBitsIn') @@ -228,6 +229,7 @@ local function handleOnExpiredTmrFieldbus() Script.notifyEvent("Fieldbus_OnNewStatusCreateMode", fieldbus_Model.parameters.createMode) --checkExplicitMode() + Script.notifyEvent("Fieldbus_OnNewStatusTransmissionMode", fieldbus_Model.parameters.transmissionMode) if fieldbus_Model.fbMode == 'EtherNetIP' then @@ -238,7 +240,9 @@ local function handleOnExpiredTmrFieldbus() Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer", fieldbus_Model.parameters.etherNetIP.nameServer) Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer2", fieldbus_Model.parameters.etherNetIP.nameServer2) Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPDomainName", fieldbus_Model.parameters.etherNetIP.domainName) - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPMACAddress", fieldbus_Model.parameters.etherNetIP.macAddress) + if fieldbus_Model.parameters.etherNetIP.macAddress then + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPMACAddress", fieldbus_Model.parameters.etherNetIP.macAddress) + end elseif fieldbus_Model.fbMode == 'ProfinetIO' then Script.notifyEvent("Fieldbus_OnNewStatusProfinetIODeviceName", fieldbus_Model.parameters.profinetIO.deviceName) @@ -341,7 +345,7 @@ local function openCommunication() _G.logger:fine("Connection already active.") end Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) - return success + return success end Script.serveFunction('CSK_Fieldbus.openCommunication', openCommunication) @@ -389,7 +393,7 @@ local function setSpecificControlBitIn(values) fieldbus_Model.boolControlBitsToWrite[pos+1] = value fieldbus_Model.controlBitsToWrite = fieldbus_Model.helperFuncs.toNumber(fieldbus_Model.boolControlBitsToWrite) Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInToWrite", fieldbus_Model.controlBitsToWrite) - --print(fieldbus_Model.controlBitsToWrite) + _G.logger:severe('fieldbus_Model.controlBitsToWrite') --Is this needed? end end Script.serveFunction('CSK_Fieldbus.setSpecificControlBitIn', setSpecificControlBitIn) @@ -412,7 +416,7 @@ local function setSpecificBitMaskBit(values) fieldbus_Model.boolBitMask[pos+1] = value fieldbus_Model.bitMask = fieldbus_Model.helperFuncs.toNumber(fieldbus_Model.boolBitMask) Script.notifyEvent("Fieldbus_OnNewStatusBitMask", fieldbus_Model.bitMask) - --print(fieldbus_Model.bitMask) + _G.logger:severe('fieldbus_Model.bitMask') --Is this needed? end end Script.serveFunction('CSK_Fieldbus.setSpecificBitMaskBit', setSpecificBitMaskBit) @@ -425,43 +429,57 @@ Script.serveFunction('CSK_Fieldbus.writeControlBitsInViaUI', writeControlBitsInV -- EtherNet/IP relevant local function setAddressingMode(mode) _G.logger:fine(nameOfModule .. ": Preset Addressing mode to: " .. tostring(mode)) - fieldbus_Model.parameters.etherNetIP.addressingMode = mode + local suc = FieldBus.Config.EtherNetIP.setAddressingMode(mode) + if suc then + fieldbus_Model.parameters.etherNetIP.addressingMode = FieldBus.Config.EtherNetIP.getAddressingMode() + if fieldbus_Model.parameters.etherNetIP.addressingMode == mode then + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPAddressingMode", fieldbus_Model.parameters.etherNetIP.addressingMode) + else + _G.logger:severe(nameOfModule .. ": Set Addressing mode error:" .. tostring(mode)) + end + end end Script.serveFunction('CSK_Fieldbus.setAddressingMode', setAddressingMode) local function setEtherNetIPIP(ip) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP IP to: " .. tostring(ip)) fieldbus_Model.parameters.etherNetIP.ipAddress = ip + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPIPAddress", fieldbus_Model.parameters.etherNetIP.ipAddress) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPIP', setEtherNetIPIP) local function setEtherNetIPSubnetMask(netmask) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP subnet mask: " .. tostring(netmask)) fieldbus_Model.parameters.etherNetIP.netmask = netmask + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPSubnetMask", fieldbus_Model.parameters.etherNetIP.netmask) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPSubnetMask', setEtherNetIPSubnetMask) local function setEtherNetIPGateway(gateway) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP gateway: " .. tostring(gateway)) fieldbus_Model.parameters.etherNetIP.gateway = gateway + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPGateway", fieldbus_Model.parameters.etherNetIP.gateway) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPGateway', setEtherNetIPGateway) local function setEtherNetIPNameServer(nameServer) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP primary name server: " .. tostring(nameServer)) fieldbus_Model.parameters.etherNetIP.nameServer = nameServer + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer", fieldbus_Model.parameters.etherNetIP.nameServer) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPNameServer', setEtherNetIPNameServer) local function setEtherNetIPNameServer2(nameServer) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP secondary name server: " .. tostring(nameServer)) fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer2", fieldbus_Model.parameters.etherNetIP.nameServer2) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPNameServer2', setEtherNetIPNameServer2) local function setEtherNetIPDomainName(domainName) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP domain name: " .. tostring(domainName)) fieldbus_Model.parameters.etherNetIP.domainName = domainName + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPDomainName", fieldbus_Model.parameters.etherNetIP.domainName) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPDomainName', setEtherNetIPDomainName) diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua index 18ee75e..1158ec8 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua @@ -167,21 +167,27 @@ createFolder('/public/FieldBus/ProfinetIO') ----------------------- local function getEtherNetIPConfig() + fieldbus_Model.parameters.etherNetIP.addressingMode = FieldBus.Config.EtherNetIP.getAddressingMode() + _G.logger:fine("Addressing Mode: " .. fieldbus_Model.parameters.etherNetIP.addressingMode) local ipAddress, netmask, gateway, nameServer, nameServer2, domainName = FieldBus.Config.EtherNetIP.getInterfaceConfig() - _G.logger:fine("New EtherNet/IP interface config:") - fieldbus_Model.parameters.etherNetIP.ipAddress = ipAddress - _G.logger:fine("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) - fieldbus_Model.parameters.etherNetIP.netmask = netmask - _G.logger:fine("Gateway = " .. tostring(gateway)) - fieldbus_Model.parameters.etherNetIP.gateway = gateway - _G.logger:fine("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) - fieldbus_Model.parameters.etherNetIP.nameServer = nameServer - fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 - _G.logger:fine("DomainName = " .. tostring(domainName)) - fieldbus_Model.parameters.etherNetIP.domainName = domainName - local macAddress = FieldBus.Config.EtherNetIP.getMACAddress() - _G.logger:fine("MAC Address = " .. tostring(macAddress)) - fieldbus_Model.parameters.etherNetIP.macAddress = macAddress + if fieldbus_Model.parameters.etherNetIP.addressingMode == 'STATIC' and ipAddress ~= '0.0.0.0' and netmask ~= '0.0.0.0' then + _G.logger:fine("New EtherNet/IP interface config:") + fieldbus_Model.parameters.etherNetIP.ipAddress = ipAddress + _G.logger:fine("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + fieldbus_Model.parameters.etherNetIP.netmask = netmask + _G.logger:fine("Gateway = " .. tostring(gateway)) + fieldbus_Model.parameters.etherNetIP.gateway = gateway + _G.logger:fine("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) + fieldbus_Model.parameters.etherNetIP.nameServer = nameServer + fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 + _G.logger:fine("DomainName = " .. tostring(domainName)) + fieldbus_Model.parameters.etherNetIP.domainName = domainName + local macAddress = FieldBus.Config.EtherNetIP.getMACAddress() + _G.logger:fine("MAC Address = " .. tostring(macAddress)) + fieldbus_Model.parameters.etherNetIP.macAddress = macAddress + elseif not fieldbus_Model.parameters.etherNetIP.addressingMode == 'STATIC' then + _G.logger:warning("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + end CSK_Fieldbus.pageCalled() end fieldbus_Model.getEtherNetIPConfig = getEtherNetIPConfig @@ -189,37 +195,38 @@ fieldbus_Model.getEtherNetIPConfig = getEtherNetIPConfig -- Function to set EtherNet/IP config local function setEtherNetIPConfig() if fieldbus_Model.parameters.etherNetIP.addressingMode == 'DHCP' or fieldbus_Model.parameters.etherNetIP.addressingMode == 'BOOTP' then - local suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) - if suc then - _G.logger:fine(string.format("ENIP: Setting addressing mode to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.addressingMode)) - end - elseif fieldbus_Model.parameters.etherNetIP.ipAddress ~= '0.0.0.0' then - suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) - if suc then +-- local suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) +-- if suc then +-- _G.logger:fine(string.format("ENIP: Setting addressing mode to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.addressingMode)) +-- end + elseif fieldbus_Model.parameters.etherNetIP.ipAddress ~= '0.0.0.0' and fieldbus_Model.parameters.etherNetIP.netmask ~= '0.0.0.0' then +-- _G.logger:fine(string.format("ENIP: Setting addressing mode to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.addressingMode)) +-- local suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) +-- if suc then local ipAddress = fieldbus_Model.parameters.etherNetIP.ipAddress local netmask = fieldbus_Model.parameters.etherNetIP.netmask local gateway = fieldbus_Model.parameters.etherNetIP.gateway local nameServer = fieldbus_Model.parameters.etherNetIP.nameServer local nameServer2 = fieldbus_Model.parameters.etherNetIP.nameServer2 local domainName = fieldbus_Model.parameters.etherNetIP.domainName - suc = FieldBus.Config.EtherNetIP.setInterfaceConfig(ipAddress, netmask, gateway, nameServer, nameServer2, domainName) + local suc = FieldBus.Config.EtherNetIP.setInterfaceConfig(ipAddress, netmask, gateway, nameServer, nameServer2, domainName) if suc then _G.logger:fine(string.format("ENIP: Setting IP Address to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.ipAddress)) - --_G.logger:finer(string.format("ENIP: Setting NetMask to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.netmask)) - --_G.logger:finer(string.format("ENIP: Setting Gateway IP Address to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.gateway)) - --_G.logger:finer(string.format("ENIP: Setting Name Server 1 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer)) - --_G.logger:finer(string.format("ENIP: Setting Name Server 2 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer2)) - --_G.logger:finer(string.format("ENIP: Setting Domain Name Server to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.domainName)) +-- _G.logger:finer(string.format("ENIP: Setting NetMask to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.netmask)) +-- _G.logger:finer(string.format("ENIP: Setting Gateway IP Address to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.gateway)) +-- _G.logger:finer(string.format("ENIP: Setting Name Server 1 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer)) +-- _G.logger:finer(string.format("ENIP: Setting Name Server 2 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer2)) +-- _G.logger:finer(string.format("ENIP: Setting Domain Name Server to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.domainName)) else _G.logger:severe(string.format("ENIP: Setting IP Address to '%s' failed", fieldbus_Model.parameters.etherNetIP.ipAddress)) - --_G.logger:severe(string.format("ENIP: Setting NetMask to '%s' failed", fieldbus_Model.parameters.etherNetIP.netmask)) - --_G.logger:severe(string.format("ENIP: Setting Gateway IP Address to '%s' failed", fieldbus_Model.parameters.etherNetIP.gateway)) - --_G.logger:severe(string.format("ENIP: Setting Name Server 1 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer)) - --_G.logger:severe(string.format("ENIP: Setting Name Server 2 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer2)) - --_G.logger:severe(string.format("ENIP: Setting Domain Name Server to '%s' failed", fieldbus_Model.parameters.etherNetIP.domainName)) +-- _G.logger:severe(string.format("ENIP: Setting NetMask to '%s' failed", fieldbus_Model.parameters.etherNetIP.netmask)) +-- _G.logger:severe(string.format("ENIP: Setting Gateway IP Address to '%s' failed", fieldbus_Model.parameters.etherNetIP.gateway)) +-- _G.logger:severe(string.format("ENIP: Setting Name Server 1 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer)) +-- _G.logger:severe(string.format("ENIP: Setting Name Server 2 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer2)) +-- _G.logger:severe(string.format("ENIP: Setting Domain Name Server to '%s' failed", fieldbus_Model.parameters.etherNetIP.domainName)) end end - end +-- end CSK_Fieldbus.pageCalled() Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) end @@ -229,7 +236,12 @@ fieldbus_Model.setEtherNetIPConfig = setEtherNetIPConfig -- Function to react on received EtherNet/IP addressing mode ---@param addressingMode FieldBus.Config.EtherNetIP.AddressingMode Addressing mode for the ip parameters. local function handleOnAddressingModeChanged(addressingMode) - _G.logger:finer("New EtherNet/IP AdressingMode = " .. tostring(addressingMode)) + _G.logger:finer("New EtherNet/IP Adressing Mode = " .. tostring(addressingMode)) + if fieldbus_Model.parameters.etherNetIP.addressingMode == addressingMode then + _G.logger:severe('error: how can this happen?') + else + fieldbus_Model.parameters.etherNetIP.addressingMode = addressingMode + end end -- Function to react on received EtherNet/IP interface config. @@ -240,11 +252,34 @@ end ---@param nameServer2? string Secondary name server. ---@param domainName? string Default domain name. local function handleOnEthernetIPInterfaceConfigChanged(ipAddress, netmask, gateway, nameServer, nameServer2, domainName) - _G.logger:fine("New EtherNet/IP interface config:") - _G.logger:finer("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) - _G.logger:finer("Gateway = " .. tostring(gateway)) - _G.logger:finer("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) - _G.logger:finer("DomainName = " .. tostring(domainName)) + if ipAddress ~= '0.0.0.0' and netmask ~= '0.0.0.0' then + _G.logger:fine("New EtherNet/IP interface config:") + _G.logger:finer("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + fieldbus_Model.parameters.etherNetIP.ipAddress = ipAddress + fieldbus_Model.parameters.etherNetIP.netmask = netmask + _G.logger:finer("Gateway = " .. tostring(gateway)) + fieldbus_Model.parameters.etherNetIP.gateway = gateway + if nameServer and nameServer2 then + _G.logger:finer("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) + fieldbus_Model.parameters.etherNetIP.nameServer = nameServer + fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 + else + if nameServer then + _G.logger:finer("Nameserver 1 = " .. tostring(nameServer)) + fieldbus_Model.parameters.etherNetIP.nameServer = nameServer + end + if nameServer2 then + _G.logger:finer("Nameserver 2 = " .. tostring(nameServer2)) + fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 + end + end + if domainName then + _G.logger:finer("DomainName = " .. tostring(domainName)) + fieldbus_Model.parameters.etherNetIP.domainName = domainName + end + else + _G.logger:warning("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + end end -- Function to react on FieldbusStoreRequest @@ -252,44 +287,34 @@ end local function handleOnEtherNetIPFieldbusStorageRequest(storageHandle) local operation = FieldBus.StorageRequest.getOperation(storageHandle) _G.logger:fine('StorageRequest operation = ' .. tostring(operation)) - if operation == 'LOAD' then - - -- Check if file exists - local dataFile = File.open(fieldbus_Model.parameters.etherNetIP.storageRequestDataPath, 'rb') - local setSuc = false - - if dataFile then - local data = File.read(dataFile) - File.close(dataFile) - if FieldBus.StorageRequest.setData(storageHandle, data) then - _G.logger:fine("Setting data = " .. tostring(true)) - else - _G.logger:info("Setting data = " .. tostring(false)) - getEtherNetIPConfig() + local dataToStore = FieldBus.StorageRequest.getData(storageHandle) + local storageResult = false + if storageOperation == "LOAD" then --FieldBus.StorageRequest.StorageOperation.Load + -- load from a file + local file = File.open(fieldbusStorageFile, 'rb') + if file then + local dataLoaded = File.read(file) + File.close(file) + storageResult = FieldBus.StorageRequest.setData(storageHandle, dataLoaded) + if storageResult == false then + _G.logger:severe(string.format("Setting data at storage request failed")) end else - _G.logger:info("Not able to LOAD data.") + _G.logger:severe(string.format("Failed to open file to load storage data from!")) + storageResult = false end - - --[[if setSuc then - FieldBus.StorageRequest.notifyResult(storageHandle, true) + elseif storageOperation == "SAVE" then --FieldBus.StorageRequest.StorageOperation.Save + -- store in a file + local file = File.open(fieldbusStorageFile, 'wb') + if file then + storageResult = File.write(file, dataToStore) + File.close(file) else - FieldBus.StorageRequest.notifyResult(storageHandle, false) - end]] - - elseif operation == 'SAVE' then - local data = FieldBus.StorageRequest.getData(storageHandle) - local dataFile = File.open(fieldbus_Model.parameters.etherNetIP.storageRequestDataPath, 'wb') - local suc = File.write(dataFile, data) - if suc then - FieldBus.StorageRequest.notifyResult(storageHandle, true) - else - FieldBus.StorageRequest.notifyResult(storageHandle, false) + _G.logger:severe(string.format("Failed to open file for saving of storage data!")) end - File.close(dataFile) - _G.logger:fine("Result to write SR = " .. tostring(suc)) - CSK_Fieldbus.pageCalled() end + FieldBus.StorageRequest.notifyResult(storageHandle, storageResult) + CSK_Fieldbus.pageCalled() end ----------------------- @@ -542,15 +567,14 @@ local function handleOnStatusChanged(status) getInfo() if fieldbus_Model.currentStatus == 'CLOSED' then + fieldbus_Model.opened = false deregisterFieldbusEvents() Script.releaseObject(fieldbus_Model.handle) fieldbus_Model.handle = nil collectgarbage() - end - - if status == 'OPENED' or status == 'ONLINE' then + elseif status == 'OPENED' or status == 'ONLINE' then fieldbus_Model.opened = true - elseif status == 'OFFLINE' or status == 'ERROR' or status == 'CLOSED' then + elseif status == 'OFFLINE' or status == 'ERROR' then fieldbus_Model.opened = false end Script.notifyEvent("Fieldbus_OnNewStatusFieldbusActive", fieldbus_Model.opened) @@ -564,8 +588,8 @@ local function create() if fieldbus_Model.handle then FieldBus.setMode(fieldbus_Model.handle, fieldbus_Model.parameters.transmissionMode) _G.logger:fine("Successfully created Fieldbus handle.") - getInfo() - getStatus() + --getInfo() + --getStatus() deregisterFieldbusEvents() FieldBus.register(fieldbus_Model.handle, 'OnStatusChanged', handleOnStatusChanged) From c19b4218ac4d3c96aabe8afa9b755c5a83b20ce2 Mon Sep 17 00:00:00 2001 From: alexandro-rezakhani <85354050+alexandro-rezakhani@users.noreply.github.com> Date: Wed, 26 Mar 2025 15:51:58 -0400 Subject: [PATCH 6/8] initial --- CHANGELOG.md | 5 +- CSK_Module_Fieldbus/project.mf.xml | 1126 ++-- .../Fieldbus/Fieldbus_Controller.lua | 31 +- .../Communication/Fieldbus/Fieldbus_Model.lua | 235 +- .../Fieldbus/helper/checkAPIs.lua | 2 - .../Communication/Fieldbus/helper/funcs.lua | 4 +- docu/CSK_Module_Fieldbus.html | 5526 ++++++++++++++++- 7 files changed, 6097 insertions(+), 832 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5535416..ade7e4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,5 @@ # Changelog All notable changes to this project will be documented in this file. -## Release 0.1.1 -- FieldBus.Config.EthernetIP setup - ## Release 0.1.0 -- Initial commit +- Initial commit \ No newline at end of file diff --git a/CSK_Module_Fieldbus/project.mf.xml b/CSK_Module_Fieldbus/project.mf.xml index d8fc150..21267f2 100644 --- a/CSK_Module_Fieldbus/project.mf.xml +++ b/CSK_Module_Fieldbus/project.mf.xml @@ -1,563 +1,563 @@ - - - - - This is an automatically generated CROWN (description not necessary). - - - released - Module to provide fieldbus (Profinet / EtherNet/IP) functionality. + -This module is helpful to forward data to/from other modules to communicate to a connected PLC. + -{empty} + -Typically the features of this module are used like this (check also main script of this module): + -{empty} + -**1) Selecte protocol** + -Select a fieldbus protocol to use via 'setProtocol' and trigger a device reboot to activate the protocol via 'submitProtocol'. + -After the reboot open the connection via 'openCommunication'. + -{empty} + -**2) ControlBits** + -To read the currently active ControlBits use 'refreshControlBits' and the events 'OnNewStatusControlBitsIn', 'OnNewStatusControlBitsInTable', 'OnNewStatusControlBitsOut', 'OnNewStatusControlBitsOut'. + -It is possible to set the ControlBitsIn by presetting them via 'setControlBitsIn'/'setSpecificControlBit' and to send them via 'writeControlBitsInViaUI'. + -To set a bitmask for the ControlBitsIn make use of 'setBitMask' or 'setSpecificBitMaskBit'. + -{empty} + -**3) Data to transmit** + -It is possible to define the data structure and source of the transmitted data. + -To do this preconfigure the data entry via 'setDataNameTransmit', 'setRegisteredEventTransmit', 'setConvertDataTransmit', 'setBigEndianTransmit', 'setDataTypeTransmit' and after that add this data via 'addDataToTransmitViaUI'. + -Based on the data received by the configured event (see 'setRegisteredEventTransmit') it will forward this data via fieldbus communication. + -{empty} + -**4) Data to receive** + -It is possible to define the data structure of the data to receive from the PLC. + -To do this preconfigure the data entry via 'setDataNameReceive', 'setConvertDataReceive', 'setBigEndianReceive', 'setDataTypeReceive' and after that add this data via 'addDataToReceiveViaUI'. + -The received data values will be provided via dynamically created events (see 'CSK_Fieldbus.OnNewData_DATANAME') and the full data via event 'CSK_Fieldbus.OnNewStatusReceivedData'. + - - Fieldbus protocol. - PROFINET - EtherNet_IP - EtherCAT - - - Mode for calling Fieldbus 'create' function. - EXPLICIT_OPEN - AUTOMATIC_OPEN - - - Fieldbus TransmissionMode - RAW - CONFIRMED_MESSAGING - - - Addressing mode for the IP address assignment. - DHCP - BOOTP - STATIC - - - Types of data to transmit - S_INT2 - S_BYTE - U_INT2 - U_BYTE - S_SHORT - U_SHORT - U_INT1 - U_INT8 - U_INT4 - S_INT1 - S_INT4 - U_LONG - S_INT8 - DOUBLE - FLOAT - S_LONG - CHAR - - - - Notify status if parameters should be loaded on app/device boot up. - - - - Notify status if features of CSK_PersistendData module are available. - - - - Event to call if module tried to load parameters and should be ready. - - - Notify name of persistent data parameter. - - - - Status of Operator userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Status of Maintenance userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Status of Service userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Status of Admin userlevel. Used internally in combination with the CSK_UserManagement module if available. - - - - Notify current selected fieldbus protocol. - - - - Notify if Fieldbus features should be used. - - - - Notify fieldbus create mode. - - - - Notify fieldbus transmission mode. - - - - Notify preset data to be transmitted. - - - - Notify preset ControlBitsIn to write. - - - - Notify bit mask to use for preset control bits to write. - - - - Notify latest ControlBitsOut received from the PLC. - - - - Notify status of the fieldbus communication. - - - - Notify if fieldbus communication is currently 'OPENED' or 'ONLINE'. - - - - Notify info of fieldbus communication. - - - - Notify current value of the control bits transmitted to the PLC. - - - - Notify addressing mode for EtherNet/IP IP assignment. - - - - Notify IP address of EtherNet/IP network. - - - - Notfify subnet mask of EtherNet/IP network. - - - - Notfify gateway of EtherNet/IP network. - - - - Notfify primary name server of EtherNet/IP network. - - - - Notfify secondary name server of EtherNet/IP network. - - - - Notfify domain name of EtherNet/IP network. - - - - Notfify MAC address of specified interface of EtherNet/IP network. - - - - Notify name of the device in the Profinet network. - - - - Notify IP address of ProfinetIO network. - - - - Notfify subnet mask of ProfinetIO network. - - - - Notfify gateway of ProfinetIO network. - - - - Notfify if the ProfinetIO network configuration tool set the IP address settings permanently. - - - - Notfify MAC address of specified interface of ProfinetIO network. - - - - Notify descriptor as used for the ProfinetIO DAP’s I&M3 data. - - - - Notify hardware revision as used for the DAP used in the I&M0 data. - - - - Notify installation date as used for the DAP’s I&M2 data. - - - - Notify software revision for the DAP (device access point) used in the I&M0 data. - - - - Notify function tag as used for the DAP’s I&M1 data. - - - - Notify location tag as used for the DAP’s I&M1 data. - - - - Notify currently active fieldbus protocol. - - - - Notify if explicit mode is selected. - - - - Notify name of event to receive data to transmit. - - - - Notify name of preconfigured transmit data. - - - - Notify preconfigured status if data needs to be converted to binary before transmission. - - - - Notify if big endian should be used to convert data to transmit (otherwise little endian will be used). - - - - Notify preconfigured data type of data to transmit. - - - - Notify list of data entires to use for data transmission. - - - - Notify temporarily set data to transmit on selected data position. - - - - Notify fieldbus relevant log message. - - - - Notify ControlBitsOut as boolean table. - - - - Notify control bits IN as boolean table. - - - - Notify bitmask of control bits IN as boolean table. - - - - Notfiy received data. - - - - Notify name of preconfigured data to receive. - - - - Notify list of data entires to use for data receiving. - - - - Notify preconfigured status if data needs to be converted to binary after receiving. - - - - Notify if big endian should be used to convert received data (otherwise little endian will be used). - - - - Notify preconfigured data type of data to receive. - - - - Dynamically created event to provide received data from PLC via event. + -NAME will be replaced by data identifier (e.g. 'CSK_Fieldbus.OnNewData_Data1'). - - - - Notify info text to restart device. - - - - Function to set the name of the parameters if saved/loaded via the CSK_PersistentData module. - - - - Send parameters to CSK_PersistentData module if possible to save them. - - - Load parameters for this module from the CSK_PersistentData module if possible and use them. - - - - Configure if this module should load its saved parameters at app/device boot up. - - - - Function to register "OnResume" of the module UI (only as helper function). - - - - Function to set fiedlbus protocol to use. - - - - Function to open fieldbus communication. - - - - Function to close fieldbus communication. - - - Function to refresh data of ControlBitsIn/Out - - - Function to preset data to transmit. - - - - Function to transmit preset data (see 'setDataToTransmit'). - - - Function to preset controlBitsIn to write/transmit to PLC. - - - - Function to preset bitmask to use for preset ControlBitsIn to write. - - - - Function to write preset ControlBitsIn to the PLC. - - - Function to set create mode of fieldbus communication. - - - - Function to set transmission mode. - - - - Function to set preset fieldbus protocol (see 'setProtocol') and restart device. - - - Function to get EtherNetIP configuration. - - - Function to setup preconfigured EtherNet/IP config. - - - Function to set addressing mode of EtherNetIP communication. - - - - Function to preset IP for EtherNet/IP communication. - - - - Function to preset subnet mask for EtherNet/IP communication. - - - - Function to preset gateway for EtherNet/IP communication. - - - - Function to preset primary name server for EtherNet/IP communication. - - - - Function to preset secondary name server for EtherNet/IP communication. - - - - Function to preset domain name for EtherNet/IP communication. - - - - Function to preset ProfinetIO device name. - - - - Function to preset IP for ProfinetIO communication. - - - - Function to preset subnet mask for ProfinetIO communication. - - - - Function to preset gateway for ProfinetIO communication. - - - - Function to get ProfinetIO configuration. - - - Function apply ProfinetIO configuration. - - - Function to store ProfinetIO configuration. - - - Function to set ProfinetIO DAP IM configuration. - - - Function to get ProfinetIO DAP IM data. - - - Function to store ProfinetIO DAP I&M data. - - - Function to set descriptor for the DAPs I&M3 data. - - - - Function to set the installation date for the DAPs I&M2 data. - - - - Function to set the function tag for the DAPs I&M1 data. - - - - Function to set location tag for the DAPs I&M1 data. - - - - Function to set event to receive data to transmit via fieldbus for new/selected data entry. - - - - Function to add preconfigured data to transmit. - - - Function to preconfigure name of data entry to transmit. - - - - Function to preconfigure if internally received data (via event) needs to be converted before transmission. - - - - Function to preconfigure if data to transmit uses big endianness. Will use little endian per default. - - - - Function to preconfigure type of data to convert data before transmission. - - - - Function to select transmit data entry in UI. - - - - Function to delete preselected data entry. - - - Function to move the position of the transmit data about one position higher. - - - Function to move the position of the selected transmit data about one position lower. - - - Function to set temporarily data of in UI selected data postion to transmit. - - - - Function to set preconfigured data to in UI selected data position (see 'setTempTransmitData'). + -After that it will transmit the full data to the fieldbus. - - - Function to set specific ControlBitIn (bit range from 0-15). - - - - Function to set specific bit of bitmask (bit range from 0-15). - - - - Function to preconfigure name of data entry to receive. - - - - Function to preconfigure if received data form PLC needs to be converted before transmission. - - - - Function to preconfigure if received data uses big endianness. Will use little endian per default. - - - - Function to preconfigure type of data to convert received data. - - - - Function to add preconfigured data to receive. - - - Function to delete preselected data entry. - - - Function to move the position of the selected data to receive about one position lower. - - - Function to move the position of the data to receive about one position higher. - - - Function to select data entry in UI. - - - - Function to reset all data to transmit. - - - - SICK AG - 1.0.1 - low - false - false - false - false - - - + + + + + This is an automatically generated CROWN (description not necessary). + + + released + Module to provide fieldbus (Profinet / EtherNet/IP) functionality. + +This module is helpful to forward data to/from other modules to communicate to a connected PLC. + +{empty} + +Typically the features of this module are used like this (check also main script of this module): + +{empty} + +**1) Selecte protocol** + +Select a fieldbus protocol to use via 'setProtocol' and trigger a device reboot to activate the protocol via 'submitProtocol'. + +After the reboot open the connection via 'openCommunication'. + +{empty} + +**2) ControlBits** + +To read the currently active ControlBits use 'refreshControlBits' and the events 'OnNewStatusControlBitsIn', 'OnNewStatusControlBitsInTable', 'OnNewStatusControlBitsOut', 'OnNewStatusControlBitsOut'. + +It is possible to set the ControlBitsIn by presetting them via 'setControlBitsIn'/'setSpecificControlBit' and to send them via 'writeControlBitsInViaUI'. + +To set a bitmask for the ControlBitsIn make use of 'setBitMask' or 'setSpecificBitMaskBit'. + +{empty} + +**3) Data to transmit** + +It is possible to define the data structure and source of the transmitted data. + +To do this preconfigure the data entry via 'setDataNameTransmit', 'setRegisteredEventTransmit', 'setConvertDataTransmit', 'setBigEndianTransmit', 'setDataTypeTransmit' and after that add this data via 'addDataToTransmitViaUI'. + +Based on the data received by the configured event (see 'setRegisteredEventTransmit') it will forward this data via fieldbus communication. + +{empty} + +**4) Data to receive** + +It is possible to define the data structure of the data to receive from the PLC. + +To do this preconfigure the data entry via 'setDataNameReceive', 'setConvertDataReceive', 'setBigEndianReceive', 'setDataTypeReceive' and after that add this data via 'addDataToReceiveViaUI'. + +The received data values will be provided via dynamically created events (see 'CSK_Fieldbus.OnNewData_DATANAME') and the full data via event 'CSK_Fieldbus.OnNewStatusReceivedData'. + + + Fieldbus protocol. + PROFINET + EtherNet_IP + EtherCAT + + + Mode for calling Fieldbus 'create' function. + EXPLICIT_OPEN + AUTOMATIC_OPEN + + + Fieldbus TransmissionMode + RAW + CONFIRMED_MESSAGING + + + Addressing mode for the IP address assignment. + DHCP + BOOTP + STATIC + + + Types of data to transmit + S_INT2 + S_BYTE + U_INT2 + U_BYTE + S_SHORT + U_SHORT + U_INT1 + U_INT8 + U_INT4 + S_INT1 + S_INT4 + U_LONG + S_INT8 + DOUBLE + FLOAT + S_LONG + CHAR + + + + Notify status if parameters should be loaded on app/device boot up. + + + + Notify status if features of CSK_PersistendData module are available. + + + + Event to call if module tried to load parameters and should be ready. + + + Notify name of persistent data parameter. + + + + Status of Operator userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Status of Maintenance userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Status of Service userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Status of Admin userlevel. Used internally in combination with the CSK_UserManagement module if available. + + + + Notify current selected fieldbus protocol. + + + + Notify if Fieldbus features should be used. + + + + Notify fieldbus create mode. + + + + Notify fieldbus transmission mode. + + + + Notify preset data to be transmitted. + + + + Notify preset ControlBitsIn to write. + + + + Notify bit mask to use for preset control bits to write. + + + + Notify latest ControlBitsOut received from the PLC. + + + + Notify status of the fieldbus communication. + + + + Notify if fieldbus communication is currently 'OPENED' or 'ONLINE'. + + + + Notify info of fieldbus communication. + + + + Notify current value of the control bits transmitted to the PLC. + + + + Notify addressing mode for EtherNet/IP IP assignment. + + + + Notify IP address of EtherNet/IP network. + + + + Notfify subnet mask of EtherNet/IP network. + + + + Notfify gateway of EtherNet/IP network. + + + + Notfify primary name server of EtherNet/IP network. + + + + Notfify secondary name server of EtherNet/IP network. + + + + Notfify domain name of EtherNet/IP network. + + + + Notfify MAC address of specified interface of EtherNet/IP network. + + + + Notify name of the device in the Profinet network. + + + + Notify IP address of ProfinetIO network. + + + + Notfify subnet mask of ProfinetIO network. + + + + Notfify gateway of ProfinetIO network. + + + + Notfify if the ProfinetIO network configuration tool set the IP address settings permanently. + + + + Notfify MAC address of specified interface of ProfinetIO network. + + + + Notify descriptor as used for the ProfinetIO DAP’s I&M3 data. + + + + Notify hardware revision as used for the DAP used in the I&M0 data. + + + + Notify installation date as used for the DAP’s I&M2 data. + + + + Notify software revision for the DAP (device access point) used in the I&M0 data. + + + + Notify function tag as used for the DAP’s I&M1 data. + + + + Notify location tag as used for the DAP’s I&M1 data. + + + + Notify currently active fieldbus protocol. + + + + Notify if explicit mode is selected. + + + + Notify name of event to receive data to transmit. + + + + Notify name of preconfigured transmit data. + + + + Notify preconfigured status if data needs to be converted to binary before transmission. + + + + Notify if big endian should be used to convert data to transmit (otherwise little endian will be used). + + + + Notify preconfigured data type of data to transmit. + + + + Notify list of data entires to use for data transmission. + + + + Notify temporarily set data to transmit on selected data position. + + + + Notify fieldbus relevant log message. + + + + Notify ControlBitsOut as boolean table. + + + + Notify control bits IN as boolean table. + + + + Notify bitmask of control bits IN as boolean table. + + + + Notfiy received data. + + + + Notify name of preconfigured data to receive. + + + + Notify list of data entires to use for data receiving. + + + + Notify preconfigured status if data needs to be converted to binary after receiving. + + + + Notify if big endian should be used to convert received data (otherwise little endian will be used). + + + + Notify preconfigured data type of data to receive. + + + + Dynamically created event to provide received data from PLC via event. + +NAME will be replaced by data identifier (e.g. 'CSK_Fieldbus.OnNewData_Data1'). + + + + Notify info text to restart device. + + + + Function to set the name of the parameters if saved/loaded via the CSK_PersistentData module. + + + + Send parameters to CSK_PersistentData module if possible to save them. + + + Load parameters for this module from the CSK_PersistentData module if possible and use them. + + + + Configure if this module should load its saved parameters at app/device boot up. + + + + Function to register "OnResume" of the module UI (only as helper function). + + + + Function to set fiedlbus protocol to use. + + + + Function to open fieldbus communication. + + + + Function to close fieldbus communication. + + + Function to refresh data of ControlBitsIn/Out + + + Function to preset data to transmit. + + + + Function to transmit preset data (see 'setDataToTransmit'). + + + Function to preset controlBitsIn to write/transmit to PLC. + + + + Function to preset bitmask to use for preset ControlBitsIn to write. + + + + Function to write preset ControlBitsIn to the PLC. + + + Function to set create mode of fieldbus communication. + + + + Function to set transmission mode. + + + + Function to set preset fieldbus protocol (see 'setProtocol') and restart device. + + + Function to get EtherNetIP configuration. + + + Function to setup preconfigured EtherNet/IP config. + + + Function to set addressing mode of EtherNetIP communication. + + + + Function to preset IP for EtherNet/IP communication. + + + + Function to preset subnet mask for EtherNet/IP communication. + + + + Function to preset gateway for EtherNet/IP communication. + + + + Function to preset primary name server for EtherNet/IP communication. + + + + Function to preset secondary name server for EtherNet/IP communication. + + + + Function to preset domain name for EtherNet/IP communication. + + + + Function to preset ProfinetIO device name. + + + + Function to preset IP for ProfinetIO communication. + + + + Function to preset subnet mask for ProfinetIO communication. + + + + Function to preset gateway for ProfinetIO communication. + + + + Function to get ProfinetIO configuration. + + + Function apply ProfinetIO configuration. + + + Function to store ProfinetIO configuration. + + + Function to set ProfinetIO DAP IM configuration. + + + Function to get ProfinetIO DAP IM data. + + + Function to store ProfinetIO DAP I&M data. + + + Function to set descriptor for the DAPs I&M3 data. + + + + Function to set the installation date for the DAPs I&M2 data. + + + + Function to set the function tag for the DAPs I&M1 data. + + + + Function to set location tag for the DAPs I&M1 data. + + + + Function to set event to receive data to transmit via fieldbus for new/selected data entry. + + + + Function to add preconfigured data to transmit. + + + Function to preconfigure name of data entry to transmit. + + + + Function to preconfigure if internally received data (via event) needs to be converted before transmission. + + + + Function to preconfigure if data to transmit uses big endianness. Will use little endian per default. + + + + Function to preconfigure type of data to convert data before transmission. + + + + Function to select transmit data entry in UI. + + + + Function to delete preselected data entry. + + + Function to move the position of the transmit data about one position higher. + + + Function to move the position of the selected transmit data about one position lower. + + + Function to set temporarily data of in UI selected data postion to transmit. + + + + Function to set preconfigured data to in UI selected data position (see 'setTempTransmitData'). + +After that it will transmit the full data to the fieldbus. + + + Function to set specific ControlBitIn (bit range from 0-15). + + + + Function to set specific bit of bitmask (bit range from 0-15). + + + + Function to preconfigure name of data entry to receive. + + + + Function to preconfigure if received data form PLC needs to be converted before transmission. + + + + Function to preconfigure if received data uses big endianness. Will use little endian per default. + + + + Function to preconfigure type of data to convert received data. + + + + Function to add preconfigured data to receive. + + + Function to delete preselected data entry. + + + Function to move the position of the selected data to receive about one position lower. + + + Function to move the position of the data to receive about one position higher. + + + Function to select data entry in UI. + + + + Function to reset all data to transmit. + + + + SICK AG + 1.0.0 + low + false + false + false + false + + + diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua index c44607c..637bbcc 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Controller.lua @@ -49,7 +49,6 @@ Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusInfo', 'Fieldbus_OnNewStatusF Script.serveEvent('CSK_Fieldbus.OnNewStatusCreateMode', 'Fieldbus_OnNewStatusCreateMode') Script.serveEvent('CSK_Fieldbus.OnNewStatusExplicitModeActive', 'Fieldbus_OnNewStatusExplicitModeActive') -Script.serveEvent('CSK_Fieldbus.OnNewStatusFieldbusMode', 'Fieldbus_OnNewStatusFieldbusMode') Script.serveEvent('CSK_Fieldbus.OnNewStatusTransmissionMode', 'Fieldbus_OnNewStatusTransmissionMode') Script.serveEvent('CSK_Fieldbus.OnNewStatusControlBitsIn', 'Fieldbus_OnNewStatusControlBitsIn') @@ -229,7 +228,6 @@ local function handleOnExpiredTmrFieldbus() Script.notifyEvent("Fieldbus_OnNewStatusCreateMode", fieldbus_Model.parameters.createMode) --checkExplicitMode() - Script.notifyEvent("Fieldbus_OnNewStatusTransmissionMode", fieldbus_Model.parameters.transmissionMode) if fieldbus_Model.fbMode == 'EtherNetIP' then @@ -240,9 +238,7 @@ local function handleOnExpiredTmrFieldbus() Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer", fieldbus_Model.parameters.etherNetIP.nameServer) Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer2", fieldbus_Model.parameters.etherNetIP.nameServer2) Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPDomainName", fieldbus_Model.parameters.etherNetIP.domainName) - if fieldbus_Model.parameters.etherNetIP.macAddress then - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPMACAddress", fieldbus_Model.parameters.etherNetIP.macAddress) - end + Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPMACAddress", fieldbus_Model.parameters.etherNetIP.macAddress) elseif fieldbus_Model.fbMode == 'ProfinetIO' then Script.notifyEvent("Fieldbus_OnNewStatusProfinetIODeviceName", fieldbus_Model.parameters.profinetIO.deviceName) @@ -344,8 +340,7 @@ local function openCommunication() else _G.logger:fine("Connection already active.") end - Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) - return success + return success end Script.serveFunction('CSK_Fieldbus.openCommunication', openCommunication) @@ -393,7 +388,7 @@ local function setSpecificControlBitIn(values) fieldbus_Model.boolControlBitsToWrite[pos+1] = value fieldbus_Model.controlBitsToWrite = fieldbus_Model.helperFuncs.toNumber(fieldbus_Model.boolControlBitsToWrite) Script.notifyEvent("Fieldbus_OnNewStatusControlBitsInToWrite", fieldbus_Model.controlBitsToWrite) - _G.logger:severe('fieldbus_Model.controlBitsToWrite') --Is this needed? + --print(fieldbus_Model.controlBitsToWrite) end end Script.serveFunction('CSK_Fieldbus.setSpecificControlBitIn', setSpecificControlBitIn) @@ -416,7 +411,7 @@ local function setSpecificBitMaskBit(values) fieldbus_Model.boolBitMask[pos+1] = value fieldbus_Model.bitMask = fieldbus_Model.helperFuncs.toNumber(fieldbus_Model.boolBitMask) Script.notifyEvent("Fieldbus_OnNewStatusBitMask", fieldbus_Model.bitMask) - _G.logger:severe('fieldbus_Model.bitMask') --Is this needed? + --print(fieldbus_Model.bitMask) end end Script.serveFunction('CSK_Fieldbus.setSpecificBitMaskBit', setSpecificBitMaskBit) @@ -429,57 +424,43 @@ Script.serveFunction('CSK_Fieldbus.writeControlBitsInViaUI', writeControlBitsInV -- EtherNet/IP relevant local function setAddressingMode(mode) _G.logger:fine(nameOfModule .. ": Preset Addressing mode to: " .. tostring(mode)) - local suc = FieldBus.Config.EtherNetIP.setAddressingMode(mode) - if suc then - fieldbus_Model.parameters.etherNetIP.addressingMode = FieldBus.Config.EtherNetIP.getAddressingMode() - if fieldbus_Model.parameters.etherNetIP.addressingMode == mode then - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPAddressingMode", fieldbus_Model.parameters.etherNetIP.addressingMode) - else - _G.logger:severe(nameOfModule .. ": Set Addressing mode error:" .. tostring(mode)) - end - end + fieldbus_Model.parameters.etherNetIP.addressingMode = mode end Script.serveFunction('CSK_Fieldbus.setAddressingMode', setAddressingMode) local function setEtherNetIPIP(ip) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP IP to: " .. tostring(ip)) fieldbus_Model.parameters.etherNetIP.ipAddress = ip - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPIPAddress", fieldbus_Model.parameters.etherNetIP.ipAddress) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPIP', setEtherNetIPIP) local function setEtherNetIPSubnetMask(netmask) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP subnet mask: " .. tostring(netmask)) fieldbus_Model.parameters.etherNetIP.netmask = netmask - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPSubnetMask", fieldbus_Model.parameters.etherNetIP.netmask) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPSubnetMask', setEtherNetIPSubnetMask) local function setEtherNetIPGateway(gateway) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP gateway: " .. tostring(gateway)) fieldbus_Model.parameters.etherNetIP.gateway = gateway - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPGateway", fieldbus_Model.parameters.etherNetIP.gateway) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPGateway', setEtherNetIPGateway) local function setEtherNetIPNameServer(nameServer) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP primary name server: " .. tostring(nameServer)) fieldbus_Model.parameters.etherNetIP.nameServer = nameServer - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer", fieldbus_Model.parameters.etherNetIP.nameServer) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPNameServer', setEtherNetIPNameServer) local function setEtherNetIPNameServer2(nameServer) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP secondary name server: " .. tostring(nameServer)) fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPNameServer2", fieldbus_Model.parameters.etherNetIP.nameServer2) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPNameServer2', setEtherNetIPNameServer2) local function setEtherNetIPDomainName(domainName) _G.logger:fine(nameOfModule .. ": Preset EtherNet/IP domain name: " .. tostring(domainName)) fieldbus_Model.parameters.etherNetIP.domainName = domainName - Script.notifyEvent("Fieldbus_OnNewStatusEtherNetIPDomainName", fieldbus_Model.parameters.etherNetIP.domainName) end Script.serveFunction('CSK_Fieldbus.setEtherNetIPDomainName', setEtherNetIPDomainName) @@ -490,7 +471,7 @@ end Script.serveFunction('CSK_Fieldbus.getEtherNetIPConfig', getEtherNetIPConfig) local function setEtherNetIPConfig() - _G.logger:fine(nameOfModule .. ": Activate preset EtherNet/IP configuration") + _G.logger:fine(nameOfModule .. ": Activate preset EtherNet/IP configuration.") fieldbus_Model.setEtherNetIPConfig() end Script.serveFunction('CSK_Fieldbus.setEtherNetIPConfig', setEtherNetIPConfig) diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua index 1158ec8..06d9906 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/Fieldbus_Model.lua @@ -110,22 +110,22 @@ fieldbus_Model.parameters.bigEndiansReceive = {} -- Little endian per default fieldbus_Model.parameters.etherNetIP = {} fieldbus_Model.parameters.etherNetIP.storageRequestDataPath = '/public/FieldBus/EtherNetIP/StorageData.dat' -- Path to store fieldbus storage data. fieldbus_Model.parameters.etherNetIP.addressingMode = 'STATIC' -- or 'DHCP' / 'BOOTP' -fieldbus_Model.parameters.etherNetIP.ipAddress = '192.168.0.1' -- IP address +fieldbus_Model.parameters.etherNetIP.ipAddress = '0.0.0.0' -- IP address fieldbus_Model.parameters.etherNetIP.netmask = '255.255.255.0' -- Subnet mask fieldbus_Model.parameters.etherNetIP.gateway = '0.0.0.0' -- Gateway address fieldbus_Model.parameters.etherNetIP.nameServer = '0.0.0.0' -- Primary name server fieldbus_Model.parameters.etherNetIP.nameServer2 = '0.0.0.0' -- Secondary name server -fieldbus_Model.parameters.etherNetIP.domainName = '0.0.0.0' -- Domain name -fieldbus_Model.parameters.etherNetIP.macAddress = '00:00:00:00:00:00' -- MAC address of fieldbus implementation. +fieldbus_Model.parameters.etherNetIP.domainName = '' -- Domain name +fieldbus_Model.parameters.etherNetIP.macAddress = '' -- MAC address of fieldbus implementation. fieldbus_Model.parameters.profinetIO = {} fieldbus_Model.parameters.profinetIO.storageRequestDataPath = '/public/FieldBus/ProfinetIO/StorageData.dat' -- Path to store fieldbus storage data. fieldbus_Model.parameters.profinetIO.deviceName = '' -- Device name fieldbus_Model.parameters.profinetIO.remanent = false -- Status if the network configuration tool sets the current name of the device permanently (true), that is, it will be reloaded after a restart of the device. -fieldbus_Model.parameters.profinetIO.ipAddress = '192.168.0.1' -- IP address +fieldbus_Model.parameters.profinetIO.ipAddress = '0.0.0.0' -- IP address fieldbus_Model.parameters.profinetIO.netmask = '255.255.255.0' -- Subnet mask fieldbus_Model.parameters.profinetIO.gateway = '0.0.0.0' -- Gateway address -fieldbus_Model.parameters.profinetIO.macAddress = '00:00:00:00:00:00' -- MAC address of fieldbus implementation. +fieldbus_Model.parameters.profinetIO.macAddress = '' -- MAC address of fieldbus implementation. fieldbus_Model.parameters.profinetIO.dapImDescriptor = 'Descriptor' -- The descriptor (a.k.a. 'comment') as used for the DAP’s (device access point) I&M3 data. fieldbus_Model.parameters.profinetIO.dapImHardwareRev = 0 -- Hardware revision as used for the DAP (device access point) used in the I&M0 data. @@ -166,82 +166,40 @@ createFolder('/public/FieldBus/ProfinetIO') -- EtherNet/IP relevant ----------------------- -local function getEtherNetIPConfig() - fieldbus_Model.parameters.etherNetIP.addressingMode = FieldBus.Config.EtherNetIP.getAddressingMode() - _G.logger:fine("Addressing Mode: " .. fieldbus_Model.parameters.etherNetIP.addressingMode) - local ipAddress, netmask, gateway, nameServer, nameServer2, domainName = FieldBus.Config.EtherNetIP.getInterfaceConfig() - if fieldbus_Model.parameters.etherNetIP.addressingMode == 'STATIC' and ipAddress ~= '0.0.0.0' and netmask ~= '0.0.0.0' then - _G.logger:fine("New EtherNet/IP interface config:") - fieldbus_Model.parameters.etherNetIP.ipAddress = ipAddress - _G.logger:fine("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) - fieldbus_Model.parameters.etherNetIP.netmask = netmask - _G.logger:fine("Gateway = " .. tostring(gateway)) - fieldbus_Model.parameters.etherNetIP.gateway = gateway - _G.logger:fine("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) - fieldbus_Model.parameters.etherNetIP.nameServer = nameServer - fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 - _G.logger:fine("DomainName = " .. tostring(domainName)) - fieldbus_Model.parameters.etherNetIP.domainName = domainName - local macAddress = FieldBus.Config.EtherNetIP.getMACAddress() - _G.logger:fine("MAC Address = " .. tostring(macAddress)) - fieldbus_Model.parameters.etherNetIP.macAddress = macAddress - elseif not fieldbus_Model.parameters.etherNetIP.addressingMode == 'STATIC' then - _G.logger:warning("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) - end - CSK_Fieldbus.pageCalled() -end -fieldbus_Model.getEtherNetIPConfig = getEtherNetIPConfig - -- Function to set EtherNet/IP config local function setEtherNetIPConfig() - if fieldbus_Model.parameters.etherNetIP.addressingMode == 'DHCP' or fieldbus_Model.parameters.etherNetIP.addressingMode == 'BOOTP' then --- local suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) --- if suc then --- _G.logger:fine(string.format("ENIP: Setting addressing mode to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.addressingMode)) --- end - elseif fieldbus_Model.parameters.etherNetIP.ipAddress ~= '0.0.0.0' and fieldbus_Model.parameters.etherNetIP.netmask ~= '0.0.0.0' then --- _G.logger:fine(string.format("ENIP: Setting addressing mode to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.addressingMode)) --- local suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) --- if suc then - local ipAddress = fieldbus_Model.parameters.etherNetIP.ipAddress - local netmask = fieldbus_Model.parameters.etherNetIP.netmask - local gateway = fieldbus_Model.parameters.etherNetIP.gateway - local nameServer = fieldbus_Model.parameters.etherNetIP.nameServer - local nameServer2 = fieldbus_Model.parameters.etherNetIP.nameServer2 - local domainName = fieldbus_Model.parameters.etherNetIP.domainName - local suc = FieldBus.Config.EtherNetIP.setInterfaceConfig(ipAddress, netmask, gateway, nameServer, nameServer2, domainName) - if suc then - _G.logger:fine(string.format("ENIP: Setting IP Address to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.ipAddress)) --- _G.logger:finer(string.format("ENIP: Setting NetMask to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.netmask)) --- _G.logger:finer(string.format("ENIP: Setting Gateway IP Address to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.gateway)) --- _G.logger:finer(string.format("ENIP: Setting Name Server 1 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer)) --- _G.logger:finer(string.format("ENIP: Setting Name Server 2 to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.nameServer2)) --- _G.logger:finer(string.format("ENIP: Setting Domain Name Server to '%s' succeeded", fieldbus_Model.parameters.etherNetIP.domainName)) - else - _G.logger:severe(string.format("ENIP: Setting IP Address to '%s' failed", fieldbus_Model.parameters.etherNetIP.ipAddress)) --- _G.logger:severe(string.format("ENIP: Setting NetMask to '%s' failed", fieldbus_Model.parameters.etherNetIP.netmask)) --- _G.logger:severe(string.format("ENIP: Setting Gateway IP Address to '%s' failed", fieldbus_Model.parameters.etherNetIP.gateway)) --- _G.logger:severe(string.format("ENIP: Setting Name Server 1 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer)) --- _G.logger:severe(string.format("ENIP: Setting Name Server 2 to '%s' failed", fieldbus_Model.parameters.etherNetIP.nameServer2)) --- _G.logger:severe(string.format("ENIP: Setting Domain Name Server to '%s' failed", fieldbus_Model.parameters.etherNetIP.domainName)) - end + --TODO Check following content... + --print("Set mode = " .. fieldbus_Model.parameters.etherNetIP.addressingMode) + local suc = false + + suc = FieldBus.Config.EtherNetIP.setAddressingMode(fieldbus_Model.parameters.etherNetIP.addressingMode) + --print("Suc = " .. tostring(suc)) + + if fieldbus_Model.parameters.etherNetIP.addressingMode == 'STATIC' then + --print(fieldbus_Model.parameters.etherNetIP.ipAddress) + --print(fieldbus_Model.parameters.etherNetIP.netmask) + suc = FieldBus.Config.EtherNetIP.setInterfaceConfig(fieldbus_Model.parameters.etherNetIP.ipAddress, fieldbus_Model.parameters.etherNetIP.netmask)--, fieldbus_Model.parameters.etherNetIP.gateway, fieldbus_Model.parameters.etherNetIP.nameServer, fieldbus_Model.parameters.etherNetIP.nameServer2, fieldbus_Model.parameters.etherNetIP.domainName) + --print("Setting of static IP setup = " .. tostring(suc)) + end + + --[[if suc then + if fieldbus_Model.parameters.etherNetIP.addressingMode == 'STATIC' then + suc = FieldBus.Config.EtherNetIP.setInterfaceConfig(fieldbus_Model.parameters.etherNetIP.ipAddress, fieldbus_Model.parameters.etherNetIP.netmask, fieldbus_Model.parameters.etherNetIP.gateway, fieldbus_Model.parameters.etherNetIP.nameServer, fieldbus_Model.parameters.etherNetIP.nameServer2, fieldbus_Model.parameters.etherNetIP.domainName) + print("Setting of static IP setup = " .. tostring(suc)) end --- end + ]] + --end CSK_Fieldbus.pageCalled() - Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) end fieldbus_Model.setEtherNetIPConfig = setEtherNetIPConfig - -- Function to react on received EtherNet/IP addressing mode ---@param addressingMode FieldBus.Config.EtherNetIP.AddressingMode Addressing mode for the ip parameters. local function handleOnAddressingModeChanged(addressingMode) - _G.logger:finer("New EtherNet/IP Adressing Mode = " .. tostring(addressingMode)) - if fieldbus_Model.parameters.etherNetIP.addressingMode == addressingMode then - _G.logger:severe('error: how can this happen?') - else - fieldbus_Model.parameters.etherNetIP.addressingMode = addressingMode - end + _G.logger:fine("New EtherNet/IP AdressingMode = " .. tostring(addressingMode)) + fieldbus_Model.parameters.etherNetIP.addressingMode = addressingMode + + --setEtherNetIPConfig() --TODO chech logic end -- Function to react on received EtherNet/IP interface config. @@ -252,69 +210,92 @@ end ---@param nameServer2? string Secondary name server. ---@param domainName? string Default domain name. local function handleOnEthernetIPInterfaceConfigChanged(ipAddress, netmask, gateway, nameServer, nameServer2, domainName) - if ipAddress ~= '0.0.0.0' and netmask ~= '0.0.0.0' then - _G.logger:fine("New EtherNet/IP interface config:") - _G.logger:finer("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) - fieldbus_Model.parameters.etherNetIP.ipAddress = ipAddress - fieldbus_Model.parameters.etherNetIP.netmask = netmask - _G.logger:finer("Gateway = " .. tostring(gateway)) - fieldbus_Model.parameters.etherNetIP.gateway = gateway - if nameServer and nameServer2 then - _G.logger:finer("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) - fieldbus_Model.parameters.etherNetIP.nameServer = nameServer - fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 - else - if nameServer then - _G.logger:finer("Nameserver 1 = " .. tostring(nameServer)) - fieldbus_Model.parameters.etherNetIP.nameServer = nameServer - end - if nameServer2 then - _G.logger:finer("Nameserver 2 = " .. tostring(nameServer2)) - fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 - end - end - if domainName then - _G.logger:finer("DomainName = " .. tostring(domainName)) - fieldbus_Model.parameters.etherNetIP.domainName = domainName - end - else - _G.logger:warning("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + _G.logger:fine("New EtherNet/IP interface config:") + _G.logger:fine("IP Address / NetMask = " .. tostring(ipAddress) .. ' / ' .. tostring(netmask)) + _G.logger:fine("Gateway = " .. tostring(gateway)) + _G.logger:fine("Nameserver 1 / 2 = " .. tostring(nameServer) .. ' / ' .. tostring(nameServer2)) + _G.logger:fine("DomainName = " .. tostring(domainName)) + + --TODO check logic + --[[ + fieldbus_Model.parameters.etherNetIP.addressingMode + fieldbus_Model.parameters.etherNetIP.ipAddress + fieldbus_Model.parameters.etherNetIP.netmask + fieldbus_Model.parameters.etherNetIP.gateway + fieldbus_Model.parameters.etherNetIP.nameServer + fieldbus_Model.parameters.etherNetIP.nameServer2 + fieldbus_Model.parameters.etherNetIP.domainName + setEtherNetIPConfig() + ]] + +end + +local function getEtherNetIPConfig() + local addressingMode = FieldBus.Config.EtherNetIP.getAddressingMode() + local ipAddress, netmask, gateway, nameServer, nameServer2, domainName = FieldBus.Config.EtherNetIP.getInterfaceConfig() + local macAddress = FieldBus.Config.EtherNetIP.getMACAddress() + + fieldbus_Model.parameters.etherNetIP.addressingMode = addressingMode + fieldbus_Model.parameters.etherNetIP.ipAddress = ipAddress + fieldbus_Model.parameters.etherNetIP.netmask = netmask + fieldbus_Model.parameters.etherNetIP.gateway = gateway + fieldbus_Model.parameters.etherNetIP.nameServer = nameServer + fieldbus_Model.parameters.etherNetIP.nameServer2 = nameServer2 + fieldbus_Model.parameters.etherNetIP.domainName = domainName + if macAddress then + fieldbus_Model.parameters.etherNetIP.macAddress = macAddress end + + CSK_Fieldbus.pageCalled() + +-- _G.logger:fine("AddressingMode = " .. tostring(etherNetIPAddressingMode)) +-- _G.logger:fine("InterfaceConfig = " .. tostring(etherNetIPInterfaceConfig)) +-- _G.logger:fine("MAC Address = " .. tostring(etherNetIPMACAddress)) + end +fieldbus_Model.getEtherNetIPConfig = getEtherNetIPConfig -- Function to react on FieldbusStoreRequest ---@param storageHandle FieldBus.StorageRequest Object containing the data to be saved or loaded local function handleOnEtherNetIPFieldbusStorageRequest(storageHandle) local operation = FieldBus.StorageRequest.getOperation(storageHandle) _G.logger:fine('StorageRequest operation = ' .. tostring(operation)) - local dataToStore = FieldBus.StorageRequest.getData(storageHandle) - local storageResult = false - if storageOperation == "LOAD" then --FieldBus.StorageRequest.StorageOperation.Load - -- load from a file - local file = File.open(fieldbusStorageFile, 'rb') - if file then - local dataLoaded = File.read(file) - File.close(file) - storageResult = FieldBus.StorageRequest.setData(storageHandle, dataLoaded) - if storageResult == false then - _G.logger:severe(string.format("Setting data at storage request failed")) - end + if operation == 'LOAD' then + + -- Check if file exists + local dataFile = File.open(fieldbus_Model.parameters.etherNetIP.storageRequestDataPath, 'rb') + local setSuc = false + + if dataFile then + local data = File.read(dataFile) + File.close(dataFile) + setSuc = FieldBus.StorageRequest.setData(storageHandle, data) + _G.logger:fine("Setting data = " .. tostring(setSuc)) + getEtherNetIPConfig() else - _G.logger:severe(string.format("Failed to open file to load storage data from!")) - storageResult = false + _G.logger:info("Not able to LOAD data.") end - elseif storageOperation == "SAVE" then --FieldBus.StorageRequest.StorageOperation.Save - -- store in a file - local file = File.open(fieldbusStorageFile, 'wb') - if file then - storageResult = File.write(file, dataToStore) - File.close(file) + + if setSuc then + FieldBus.StorageRequest.notifyResult(storageHandle, true) else - _G.logger:severe(string.format("Failed to open file for saving of storage data!")) + FieldBus.StorageRequest.notifyResult(storageHandle, false) + end + + elseif operation == 'SAVE' then + local data = FieldBus.StorageRequest.getData(storageHandle) + local dataFile = File.open(fieldbus_Model.parameters.etherNetIP.storageRequestDataPath, 'wb') + local suc = File.write(dataFile, data) + File.close(dataFile) + _G.logger:fine("Result to write SR = " .. tostring(suc)) + + if suc then + FieldBus.StorageRequest.notifyResult(storageHandle, true) + else + FieldBus.StorageRequest.notifyResult(storageHandle, false) end + CSK_Fieldbus.pageCalled() end - FieldBus.StorageRequest.notifyResult(storageHandle, storageResult) - CSK_Fieldbus.pageCalled() end ----------------------- @@ -567,14 +548,15 @@ local function handleOnStatusChanged(status) getInfo() if fieldbus_Model.currentStatus == 'CLOSED' then - fieldbus_Model.opened = false deregisterFieldbusEvents() Script.releaseObject(fieldbus_Model.handle) fieldbus_Model.handle = nil collectgarbage() - elseif status == 'OPENED' or status == 'ONLINE' then + end + + if status == 'OPENED' or status == 'ONLINE' then fieldbus_Model.opened = true - elseif status == 'OFFLINE' or status == 'ERROR' then + elseif status == 'OFFLINE' or status == 'ERROR' or status == 'CLOSED' then fieldbus_Model.opened = false end Script.notifyEvent("Fieldbus_OnNewStatusFieldbusActive", fieldbus_Model.opened) @@ -588,8 +570,8 @@ local function create() if fieldbus_Model.handle then FieldBus.setMode(fieldbus_Model.handle, fieldbus_Model.parameters.transmissionMode) _G.logger:fine("Successfully created Fieldbus handle.") - --getInfo() - --getStatus() + getInfo() + getStatus() deregisterFieldbusEvents() FieldBus.register(fieldbus_Model.handle, 'OnStatusChanged', handleOnStatusChanged) @@ -611,7 +593,6 @@ local function create() end else _G.logger:fine("Handle already exists.") - Script.notifyEvent("Fieldbus_OnNewStatusFieldbusInfo", fieldbus_Model.helperFuncs.jsonLine2Table(fieldbus_Model.info)) end end end diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua index a835693..36ea4f4 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/checkAPIs.lua @@ -25,8 +25,6 @@ local function loadAPIs() CSK_PersistentData = require 'API.CSK_PersistentData' elseif appList[i] == 'CSK_Module_UserManagement' then CSK_UserManagement = require 'API.CSK_UserManagement' - elseif appList[i] == 'CSK_Module_FlowConfig' then - CSK_FlowConfig = require 'API.CSK_FlowConfig' end end end diff --git a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua index 07b32f3..7c6ed55 100644 --- a/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua +++ b/CSK_Module_Fieldbus/scripts/Communication/Fieldbus/helper/funcs.lua @@ -145,7 +145,7 @@ funcs.createStringListBySimpleTable = createStringListBySimpleTable --- Function to convert value out of binary string ---@param value binary Binary string ---@param format string Format the value is packed ----@param bigEndian ?bool Status if big endian is used. Otherwise little endian is active +---@param bigEndian bool Status if big endian is used. Otherwise little endian is active ---@return auto result Converted value local function convertFromBinary(value, format, bigEndian) local result @@ -199,7 +199,7 @@ funcs.convertFromBinary = convertFromBinary --- Function to convert value to binary string ---@param value auto Value to convert ---@param format string Format the value is packed ----@param bigEndian? bool Status if big endian is used. Otherwise little endian is active +---@param bigEndian bool Status if big endian is used. Otherwise little endian is active ---@return binary result Converted value local function convertToBinary(value, format, bigEndian) local result diff --git a/docu/CSK_Module_Fieldbus.html b/docu/CSK_Module_Fieldbus.html index 3cd178a..bf61348 100644 --- a/docu/CSK_Module_Fieldbus.html +++ b/docu/CSK_Module_Fieldbus.html @@ -6,7 +6,7 @@ -Documentation - CSK_Module_Fieldbus 0.1.0 +Documentation - CSK_Module_Fieldbus 1.0.0