diff --git a/CHANGELOG.md b/CHANGELOG.md index 9da41ee..26edea3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Changelog All notable changes to this project will be documented in this file. +## Release 6.1.0 + +### New features +- Function to set image pool size +- Check if persistent data to load provides all relevant parameters. Otherwise add default values. +- React on "OnStopFlowConfigProviders" event of FlowConfig module to stop cameras if in "Continuous Mode" + +### Improvements +- Prevent to change camera type via UI if camera is already connected + ## Release 6.0.0 ### New features diff --git a/CSK_Module_MultiRemoteCamera/pages/pages/CSK_Module_MultiRemoteCamera/CSK_Module_MultiRemoteCamera.html b/CSK_Module_MultiRemoteCamera/pages/pages/CSK_Module_MultiRemoteCamera/CSK_Module_MultiRemoteCamera.html index 8c0c904..97bc245 100644 --- a/CSK_Module_MultiRemoteCamera/pages/pages/CSK_Module_MultiRemoteCamera/CSK_Module_MultiRemoteCamera.html +++ b/CSK_Module_MultiRemoteCamera/pages/pages/CSK_Module_MultiRemoteCamera/CSK_Module_MultiRemoteCamera.html @@ -508,6 +508,11 @@ path="param/args/status" auto-commit> + + @@ -560,6 +565,11 @@ protocol="crownMSGPACK" crown-path="camModel"> + + @@ -630,6 +640,45 @@ update-on-resume> + + + + + + + + + + + + + + + + Notify if module can be used on device. + + Notfiy image pool size to use for camera. + + Function to register "OnResume" of the module UI (only as helper function). @@ -594,6 +598,14 @@ According to the selected model it will use some predefined GigE Vision paramete Function to reset main configuration of module. + + Function to limit the number of images which can be acquired and used at the same time + + + + Function to stop FlowConfig relevant providers. + + @@ -628,7 +640,7 @@ According to the selected model it will use some predefined GigE Vision paramete SICK AG - 6.0.0 + 6.1.0 low false false diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_FlowConfig.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_FlowConfig.lua index ffda0cd..95cb779 100644 --- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_FlowConfig.lua +++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_FlowConfig.lua @@ -21,6 +21,19 @@ local function handleOnClearOldFlow() end Script.register('CSK_FlowConfig.OnClearOldFlow', handleOnClearOldFlow) +--- Function to react if FlowConfig was updated +local function handleOnStopProvider() + if _G.availableAPIs.default and _G.availableAPIs.imageProvider then + for i = 1, #multiRemoteCamera_Instances do + if multiRemoteCamera_Instances[i].parameters.flowConfigPriority then + CSK_MultiRemoteCamera.stopFlowConfigRelevantProvider(i) + break + end + end + end +end +Script.register('CSK_FlowConfig.OnStopFlowConfigProviders', handleOnStopProvider) + --- Function to get access to the multiRemoteCamera_Instances ---@param handle handle Handle of multiRemoteCamera_Instances object local function setMultiRemoteCamera_Instances_Handle(handle) diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_OnNewImage.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_OnNewImage.lua index daca709..87ee8be 100644 --- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_OnNewImage.lua +++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_OnNewImage.lua @@ -8,6 +8,24 @@ local nameOfModule = 'CSK_MultiRemoteCamera' -- Required to keep track of already allocated resource local instanceTable = {} +--- Timer to start camera via FlowConfig if in CONTINUOUS (FIXED_FREQUENCY) mode +local tmrStartCamera = Timer.create() +tmrStartCamera:setExpirationTime(5000) +tmrStartCamera:setPeriodic(false) + +--- Function to start camera via FlowConig +local function handleOnExpired() + local amount = CSK_MultiRemoteCamera.getInstancesAmount() + for i=1, amount do + CSK_MultiRemoteCamera.setSelectedInstance(i) + local mode = CSK_MultiRemoteCamera.getAcquisitionMode() + if mode == 'FIXED_FREQUENCY' then + CSK_MultiRemoteCamera.startCamera() + end + end +end +Timer.register(tmrStartCamera, 'OnExpired', handleOnExpired) + local function register(handle, _ , callback) Container.remove(handle, "CB_Function") @@ -35,6 +53,8 @@ local function register(handle, _ , callback) end Script.register('CSK_FlowConfig.OnNewFlowConfig', localCallback) + tmrStartCamera:start() + return true end Script.serveFunction(BLOCK_NAMESPACE ..".register", register) diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua index ec00f9c..68acace 100644 --- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua +++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua @@ -93,6 +93,7 @@ Script.serveEvent("CSK_MultiRemoteCamera.OnNewStatusSaveAllImagesActive", "Multi Script.serveEvent("CSK_MultiRemoteCamera.OnNewStatusTempImageActive", "MultiRemoteCamera_OnNewStatusTempImageActive") Script.serveEvent("CSK_MultiRemoteCamera.OnNewCameraOverviewTable", "MultiRemoteCamera_OnNewCameraOverviewTable") Script.serveEvent("CSK_MultiRemoteCamera.OnNewProcessingMode", "MultiRemoteCamera_OnNewProcessingMode") +Script.serveEvent('CSK_MultiRemoteCamera.OnNewImagePoolSize', 'MultiRemoteCamera_OnNewImagePoolSize') Script.serveEvent("CSK_MultiRemoteCamera.OnNewSwitchMode", "MultiRemoteCamera_OnNewSwitchMode") Script.serveEvent("CSK_MultiRemoteCamera.OnNewMonitoring", "MultiRemoteCamera_OnNewMonitoring") Script.serveEvent("CSK_MultiRemoteCamera.OnNewMonitoringState", "MultiRemoteCamera_OnNewMonitoringState") --for UI @@ -304,6 +305,7 @@ local function handleOnExpiredTmrCamera() Script.notifyEvent('MultiRemoteCamera_OnNewGigEVisionConfigTableContent', multiRemoteCamera_Instances[selectedInstance].gigEVisionConfigUITable) end end + Script.notifyEvent('MultiRemoteCamera_OnNewImagePoolSize', multiRemoteCamera_Instances[selectedInstance].parameters.imagePoolSize) Script.notifyEvent('MultiRemoteCamera_OnNewMonitoring', multiRemoteCamera_Instances[selectedInstance].parameters.monitorCamera) Script.notifyEvent('MultiRemoteCamera_OnNewSwitchMode', multiRemoteCamera_Instances[selectedInstance].parameters.switchMode) @@ -522,6 +524,12 @@ local function getGigEVision() end Script.serveFunction("CSK_MultiRemoteCamera.getGigEVision", getGigEVision) +local function setImagePoolSize(size) + _G.logger:fine(nameOfModule .. ": Set image pool size = " .. tostring(size)) + multiRemoteCamera_Instances[selectedInstance].parameters.imagePoolSize = size +end +Script.serveFunction('CSK_MultiRemoteCamera.setImagePoolSize', setImagePoolSize) + local function setSwitchMode (status) for i = 1, #multiRemoteCamera_Instances do multiRemoteCamera_Instances[i].parameters.switchMode = status @@ -957,6 +965,14 @@ local function getStatusModuleActive() end Script.serveFunction('CSK_MultiRemoteCamera.getStatusModuleActive', getStatusModuleActive) +local function stopFlowConfigRelevantProvider(instance) + if multiRemoteCamera_Instances[instance].parameters.acquisitionMode == 'FIXED_FREQUENCY' then + setSelectedInstance(instance) + stopCamera() + end +end +Script.serveFunction('CSK_MultiRemoteCamera.stopFlowConfigRelevantProvider', stopFlowConfigRelevantProvider) + local function clearFlowConfigRelevantConfiguration() -- Nothing to do so far end @@ -1007,6 +1023,9 @@ local function loadParameters() if data then _G.logger:info(nameOfModule .. ": Loaded parameters from CSK_PersistentData module.") multiRemoteCamera_Instances[selectedInstance].parameters = helperFuncs.convertContainer2Table(data) + + multiRemoteCamera_Instances[selectedInstance].parameters = helperFuncs.checkParameters(multiRemoteCamera_Instances[selectedInstance].parameters, helperFuncs.defaultParameters) + multiRemoteCamera_Instances[selectedInstance]:setNewConfig() updateImageProcessingParameter() pageCalled() diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua index 0933f8b..d7d3efb 100644 --- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua +++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua @@ -87,45 +87,12 @@ function multiRemoteCamera.create(cameraNo) self.triggerFunction = nil -- Internally used function to SW trigger the camera self.parameters = {} - self.parameters.flowConfigPriority = CSK_FlowConfig ~= nil or false -- Status if FlowConfig should have priority for FlowConfig relevant configurations + self.parameters = require('Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters') -- Load default parameters + + -- Instance specific parameters self.parameters.cameraNo = cameraNo -- Instance no of this camera self.parameters.camSum = cameraNo -- Amount of all cameras - self.parameters.switchMode = false -- Is camera connected via switch to SIM? - -- gigEvision or false -- GigE Vision camera? - if _G.availableAPIs.GigEVision == true then - self.parameters.gigEvision = true - else - self.parameters.gigEvision = false - end self.parameters.cameraIP = '192.168.1.10' .. tostring(cameraNo-1) -- IP of camera - self.parameters.shutterTime = 20000 -- Shutter time to use - self.parameters.gain = 1.0 -- Gain - self.parameters.framerate = 1 -- Frame rate in "FIXED_FREQUENCY" mode - self.parameters.acquisitionMode = 'SOFTWARE_TRIGGER' -- 'FIXED_FREQUENCY' / 'SOFTWARE_TRIGGER' / 'HARDWARE_TRIGGER' - self.parameters.swTriggerEvent = '' -- Opt. event to trigger camera in SW mode - self.parameters.hardwareTriggerDelay = 0 -- Opt. delay for HW trigger - self.parameters.triggerDelayBlockName = nil -- Name of specific delay bock within cFlow - self.parameters.colorMode = 'MONO8' --'COLOR8' / 'MONO8' / 'RAW8' - self.parameters.xStartFOV = 0 -- Field of view xStart - self.parameters.xEndFOV = 100 -- Field of view xEnd - self.parameters.yStartFOV = 0 -- Field of view yStart - self.parameters.yEndFOV = 100 -- Field of view yEnd - self.parameters.processingFile = 'CSK_MultiRemoteCamera_ImageProcessing' -- Script to use for processing in thread - self.parameters.monitorCamera = false -- Opt. monitor camera status in "CameraOverview" UI - self.parameters.customGigEVisionConfig = {} -- Custom GigEVision setting, content are 3 tables ".parameter", ".type", ".value" - self.parameters.cameraModel = "PicoMidiCam2" -- 'a2A1920-51gcBAS', 'CustomConfig' - - -- Image processing parameters - self.parameters.processingMode = "BOTH" -- 'SCRIPT', 'APP', 'BOTH' --> see "setProcessingMode" - self.parameters.maxImageQueueSize = 5 -- max. size of image queue - self.parameters.savingImagePath = '/public/' -- path of images to save (SD or public) - self.parameters.imageFilePrefix = 'Image_' -- prefix for images to be saved - self.parameters.saveAllImages = false -- Save all incoming images - self.parameters.tempSaveImage = false -- Save latest image to opt. save it later - self.parameters.resizeFactor = 1.0 -- factor to resize the incoming image, 0.1 - 1.0 - self.parameters.imageSaveFormat = 'bmp' -- bmp / jpg / png - self.parameters.imageSaveJpgFormatCompression = 90 - self.parameters.imageSavePngFormatCompression = 6 Script.serveEvent("CSK_MultiRemoteCamera.OnRegisterCamera" .. tostring(cameraNo), "MultiRemoteCamera_OnRegisterCamera" .. tostring(cameraNo), 'handle:1:Image.Provider.RemoteCamera') Script.serveEvent("CSK_MultiRemoteCamera.OnDeregisterCamera" .. tostring(cameraNo), "MultiRemoteCamera_OnDeregisterCamera" .. tostring(cameraNo), 'handle:1:Image.Provider.RemoteCamera') @@ -201,6 +168,7 @@ end function multiRemoteCamera:connectCamera() self.CameraProvider = Image.Provider.RemoteCamera.create() + Image.Provider.RemoteCamera.setImagePoolSize(self.CameraProvider, self.parameters.imagePoolSize) if self.parameters.gigEvision then self.CameraProvider:setType('GIGE_VISIONCAM') @@ -265,7 +233,9 @@ end --- Function to stop the camera function multiRemoteCamera:stopCamera() - self.CameraProvider:stop() + if self.CameraProvider then + self.CameraProvider:stop() + end end --- Function to set new camera config @@ -280,7 +250,7 @@ function multiRemoteCamera:setNewConfig() _G.logger:fine(nameOfModule .. ": GigEVision Config") _G.logger:fine(nameOfModule .. ": Camera-Model: " .. self.parameters.cameraModel) _G.logger:fine(nameOfModule .. ": Mode = " .. self.parameters.acquisitionMode) - + if self.parameters.cameraModel ~= "CustomConfig" then self.customCameraActive = false _G.logger:fine(nameOfModule .. ": Camera-Model: " .. self.parameters.cameraModel) diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters.lua new file mode 100644 index 0000000..ea4c837 --- /dev/null +++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters.lua @@ -0,0 +1,51 @@ +---@diagnostic disable: redundant-parameter, undefined-global + +--*************************************************************** +-- Inside of this script, you will find the relevant parameters +-- for this module and its default values +--*************************************************************** + +local multiRemoteCameraParameters = {} +multiRemoteCameraParameters.cameraNo = 1 -- Instance no of this camera (must be set individually) +multiRemoteCameraParameters.camSum = 1 -- Amount of all cameras (must be set individually) +multiRemoteCameraParameters.cameraIP = '192.168.1.100' -- IP of camera (must be set individually) + +if _G.availableAPIs.GigEVision == true then + multiRemoteCameraParameters.gigEvision = true -- Use GigE Vision camera +else + multiRemoteCameraParameters.gigEvision = false -- Use GigE Vision camera +end + +multiRemoteCameraParameters.flowConfigPriority = CSK_FlowConfig ~= nil or false -- Status if FlowConfig should have priority for FlowConfig relevant configurations +multiRemoteCameraParameters.switchMode = false -- Is camera connected via switch to SIM? +multiRemoteCameraParameters.shutterTime = 20000 -- Shutter time to use +multiRemoteCameraParameters.gain = 1.0 -- Gain +multiRemoteCameraParameters.framerate = 1 -- Frame rate in "FIXED_FREQUENCY" mode +multiRemoteCameraParameters.acquisitionMode = 'SOFTWARE_TRIGGER' -- 'FIXED_FREQUENCY' / 'SOFTWARE_TRIGGER' / 'HARDWARE_TRIGGER' +multiRemoteCameraParameters.swTriggerEvent = '' -- Opt. event to trigger camera in SW mode +multiRemoteCameraParameters.hardwareTriggerDelay = 0 -- Opt. delay for HW trigger +multiRemoteCameraParameters.triggerDelayBlockName = nil -- Name of specific delay bock within cFlow +multiRemoteCameraParameters.colorMode = 'MONO8' --'COLOR8' / 'MONO8' / 'RAW8' +multiRemoteCameraParameters.xStartFOV = 0 -- Field of view xStart +multiRemoteCameraParameters.xEndFOV = 100 -- Field of view xEnd +multiRemoteCameraParameters.yStartFOV = 0 -- Field of view yStart +multiRemoteCameraParameters.yEndFOV = 100 -- Field of view yEnd +multiRemoteCameraParameters.imagePoolSize = 10 -- Image pool size +multiRemoteCameraParameters.processingFile = 'CSK_MultiRemoteCamera_ImageProcessing' -- Script to use for processing in thread +multiRemoteCameraParameters.monitorCamera = false -- Opt. monitor camera status in "CameraOverview" UI +multiRemoteCameraParameters.customGigEVisionConfig = {} -- Custom GigEVision setting, content are 3 tables ".parameter", ".type", ".value" +multiRemoteCameraParameters.cameraModel = "PicoMidiCam2" -- 'a2A1920-51gcBAS', 'CustomConfig' + +-- Image processing parameters +multiRemoteCameraParameters.processingMode = "BOTH" -- 'SCRIPT', 'APP', 'BOTH' --> see "setProcessingMode" +multiRemoteCameraParameters.maxImageQueueSize = 5 -- max. size of image queue +multiRemoteCameraParameters.savingImagePath = '/public/' -- path of images to save (SD or public) +multiRemoteCameraParameters.imageFilePrefix = 'Image_' -- prefix for images to be saved +multiRemoteCameraParameters.saveAllImages = false -- Save all incoming images +multiRemoteCameraParameters.tempSaveImage = false -- Save latest image to opt. save it later +multiRemoteCameraParameters.resizeFactor = 1.0 -- factor to resize the incoming image, 0.1 - 1.0 +multiRemoteCameraParameters.imageSaveFormat = 'bmp' -- bmp / jpg / png +multiRemoteCameraParameters.imageSaveJpgFormatCompression = 90 +multiRemoteCameraParameters.imageSavePngFormatCompression = 6 + +return multiRemoteCameraParameters \ No newline at end of file diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/funcs.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/funcs.lua index bf104e9..8d70a35 100644 --- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/funcs.lua +++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/funcs.lua @@ -7,9 +7,13 @@ --**********************Start Global Scope ********************************* --************************************************************************** +local nameOfModule = 'CSK_MultiRemoteCamera' + local funcs = {} -- Providing standard JSON functions funcs.json = require('Sensors/MultiRemoteCamera/helper/Json') +-- Default parameters for instances of module +funcs.defaultParameters = require('Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters') --************************************************************************** --********************** End Global Scope ********************************** @@ -133,6 +137,30 @@ local function convertContainer2Table(cont) end funcs.convertContainer2Table = convertContainer2Table +--- Function to compare table content. Optionally will fill missing values within content table with values of defaultTable +---@param content auto Data to check +---@param defaultTable auto Reference data +---@return auto[] content Update of data +local function checkParameters(content, defaultTable) + for key, value in pairs(defaultTable) do + if type(value) == 'table' then + if content[key] == nil then + _G.logger:info(nameOfModule .. ": Created missing parameters table '" .. tostring(key) .. "'") + content[key] = {} + end + content[key] = checkParameters(content[key], defaultTable[key]) + elseif content[key] == nil then + _G.logger:info(nameOfModule .. ": Missing parameter '" .. tostring(key) .. "'. Adding default value '" .. tostring(defaultTable[key]) .. "'") + content[key] = defaultTable[key] + if key == 'cameraNo' then + _G.logger:warning(nameOfModule .. ": '" .. tostring(key) .. "' is a major parameter! Default value might not work and needs to be edited!") + end + end + end + return content +end +funcs.checkParameters = checkParameters + return funcs --************************************************************************** diff --git a/README.md b/README.md index 3abf378..10537e2 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Tested on |Device|Firmware|Module version| |--|--|--| +|SIM2x00|V1.8.0|V6.1.0| +|SIM1012|V2.4.2|V6.1.0| |SIM1012|V2.4.2|V6.0.0| |SIM1012|V2.2.0| -Documentation - CSK_Module_MultiRemoteCamera 6.0.0 +Documentation - CSK_Module_MultiRemoteCamera 6.1.0