diff --git a/CHANGELOG.md b/CHANGELOG.md
index b1322c1..fbce9aa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,18 @@
# Changelog
All notable changes to this project will be documented in this file.
+## Release 6.3.0
+
+### New features
+- Set delay to wait before trying to download latest image from SEC camera (see setSEC100SnapshotDelay)
+- Set status if images of SEC camera should be processed internally. Deactivate to save processing time (see setSEC100InternalImageProcessing)
+- Provide image binary string via event (see OnNewRawImageCameraNUM)
+
+### Improvements
+- Better handling of SEC images (CSK_Module_MultiHTTPClient version 2.3.0 needed)
+- Provide SEC features on devices without image processing
+- Improved connection check to SEC camera
+
## Release 6.2.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 98e4f8c..8de7349 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
@@ -291,10 +291,10 @@
-
-
+
+
@@ -1558,6 +1558,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CSK_Module_MultiRemoteCamera/project.mf.xml b/CSK_Module_MultiRemoteCamera/project.mf.xml
index 11dc766..ec824e3 100644
--- a/CSK_Module_MultiRemoteCamera/project.mf.xml
+++ b/CSK_Module_MultiRemoteCamera/project.mf.xml
@@ -52,6 +52,11 @@ There is also the possibility to edit GigE Vision camera parameters (check also
jpgpng
+
+ Mode of image.
+ IMAGE
+ BINARY
+ Notify gain of currently selected camera instance.
@@ -371,6 +376,23 @@ INFO: Other modules can check via "Script.isServedAsEvent" if event of sepecific
Notfiy interface of HTTP client to use for SEC connection.
+
+ released
+ Example of dynamically created event to transfer incoming raw images of SEC cameras. +
+This event is only used if the internal image processing for these raw images is inactive (see 'setSEC100InternalImageProcessing'). +
+NUM will be replaced by the number of instance (e.g. "OnNewRawImageCamera1"). +
+INFO: Other modules can check via "Script.isServedAsEvent" if event of sepecific instance exists.
+
+
+
+
+ Notify time to wait after SEC snapshot to download the image.
+
+
+
+ Notify status if SEC raw images should be converted for internal image processing (TRUE) or if only raw images will be forwarrded without conversion to reduce processing time (FALSE).
+
+ Function to register "OnResume" of the module UI (only as helper function).
@@ -680,6 +702,14 @@ According to the selected model it will use some predefined GigE Vision paramete
Function to set interface of HTTP client to use for SEC100 connection.
+
+ Function to set delay to wait after SEC trigger to download the latest snapshot from the SEC.
+
+
+
+ Function to set status if received raw images of SEC camera should be converted for internal image processing. Set to FALSE to reduce processing time if raw images should only be forwarded.
+
+
@@ -694,12 +724,13 @@ According to the selected model it will use some predefined GigE Vision paramete
data-flowProvide image acquired by camera.
-
+
releasedInternally used CSK_FlowConfig create function.
+
@@ -714,7 +745,7 @@ According to the selected model it will use some predefined GigE Vision paramete
SICK AG
- 6.2.0
+ 6.3.0
low
false
false
diff --git a/CSK_Module_MultiRemoteCamera/scripts/CSK_Module_MultiRemoteCamera.lua b/CSK_Module_MultiRemoteCamera/scripts/CSK_Module_MultiRemoteCamera.lua
index 6e811da..96c93da 100644
--- a/CSK_Module_MultiRemoteCamera/scripts/CSK_Module_MultiRemoteCamera.lua
+++ b/CSK_Module_MultiRemoteCamera/scripts/CSK_Module_MultiRemoteCamera.lua
@@ -66,9 +66,11 @@ local multiRemoteCameras_Instances = {} -- Handle all instances
local multiRemoteCameraController = require('Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller')
-- Check if specific APIs are available on device
-if _G.availableAPIs.default and _G.availableAPIs.imageProvider then
- _G.logger:info("I2D Support = " .. tostring(_G.availableAPIs.I2D) .. ", GigEVision support = " .. tostring(_G.availableAPIs.GigEVision))
- require('Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_FlowConfig')
+if _G.availableAPIs.default then
+ _G.logger:info("I2D Support = " .. tostring(_G.availableAPIs.I2D) .. ", GigEVision support = " .. tostring(_G.availableAPIs.GigEVision) .. ", SEC support = " .. tostring(_G.availableAPIs.SEC100))
+ if _G.availableAPIs.flow then
+ require('Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_FlowConfig')
+ end
table.insert(multiRemoteCameras_Instances, multiRemoteCamera_Model.create(1)) -- create(cameraNo:int)
multiRemoteCameraController.setMultiRemoteCamera_Instances_Handle(multiRemoteCameras_Instances) -- share handle of instances
else
diff --git a/CSK_Module_MultiRemoteCamera/scripts/CSK_MultiRemoteCamera_ImageProcessing.lua b/CSK_Module_MultiRemoteCamera/scripts/CSK_MultiRemoteCamera_ImageProcessing.lua
index 940b1a7..0166706 100644
--- a/CSK_Module_MultiRemoteCamera/scripts/CSK_MultiRemoteCamera_ImageProcessing.lua
+++ b/CSK_Module_MultiRemoteCamera/scripts/CSK_MultiRemoteCamera_ImageProcessing.lua
@@ -42,17 +42,35 @@ imageProcessingParams.secUser = scriptParams:get('secUser')
imageProcessingParams.secUserPassword = scriptParams:get('secUserPassword')
imageProcessingParams.secMode = scriptParams:get('secMode')
imageProcessingParams.secWebSocketClientInstance = scriptParams:get('secWebSocketClientInstance')
+imageProcessingParams.secSnapshotDelay = scriptParams:get('secSnapshotDelay')
+imageProcessingParams.secInternalImageProcessing = scriptParams:get('secInternalImageProcessing')
imageProcessingParams.activeInUI = false -- Is this instance currently selected in UI
imageProcessingParams.viewerActive = false -- Should the image be shown in viewer
-local viewer = View.create(viewerId) -- Viewer to show image
+local viewer
+if availableAPIs.imageProvider then
+ viewer = View.create(viewerId) -- Viewer to show image
+end
local imageQueue = Script.Queue.create() -- Queue to stop processing if increasing too much
-local jpeg = Image.Format.JPEG.create() -- Image decoder for SEC100 images
+local jpeg
+
+if availableAPIs.imageProcessing then
+ jpeg = Image.Format.JPEG.create() -- Image decoder for SEC100 images
+end
+
+local latestChallengeResponse = nil -- Latest challenge response of SEC camera
+
+local tmrLatestSnapshot = Timer.create()
+tmrLatestSnapshot:setExpirationTime(imageProcessingParams.secSnapshotDelay)
+tmrLatestSnapshot:setPeriodic(false)
-- Event to forward image to other modules
Script.serveEvent("CSK_MultiRemoteCamera.OnNewImageCamera" .. cameraNumberString, "MultiRemoteCamera_OnNewImageCamera" .. cameraNumberString, 'object:1:Image, int:?')
+-- Event to forward RAW image (binary string) to other modules
+Script.serveEvent("CSK_MultiRemoteCamera.OnNewRawImageCamera" .. cameraNumberString, "MultiRemoteCamera_OnNewRawImageCamera" .. cameraNumberString, 'string:1, int:?')
+
-- Event to forward updated values e.g. through Controller to UI
Script.serveEvent("CSK_MultiRemoteCamera.OnNewValueToForward" .. cameraNumberString, "MultiRemoteCamera_OnNewValueToForward" .. cameraNumberString, 'string:1, auto:1')
@@ -153,8 +171,10 @@ local function handleOnNewImageProcessing(image, sensorData)
if imageProcessingParams.mode == 'SCRIPT' or imageProcessingParams.mode == 'BOTH' then
-- OPTION A --> Using image locally in this script
if imageProcessingParams.activeInUI == true and imageProcessingParams.viewerActive == true then
- viewer:addImage(resImage)
- viewer:present()
+ if availableAPIs.imageProvider then
+ viewer:addImage(resImage)
+ viewer:present()
+ end
end
end
@@ -228,56 +248,92 @@ local function computeResponseHash(challenge, action, user, password)
return buildDigest({ha1, nonce, ha2})
end
+
+-- Function to get new SEC challenge
+local function getSECChallenge()
+ local _, _, challengeResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/api/getChallenge', 80, nil, '{"data":{"user": "' .. imageProcessingParams.secUser .. '"}}', 'application/json', false)
+ latestChallengeResponse = json.decode(challengeResponse:getContent())
+end
+
+-- Function to create request body for SEC
+local function getRequestBody(command, data)
+ local responseHash = computeResponseHash(latestChallengeResponse.challenge, command, imageProcessingParams.secUser, imageProcessingParams.secUserPassword)
+ local requestBody
+
+ if data then
+ requestBody = '{"header":{"user":"' .. imageProcessingParams.secUser .. '","response":"' .. responseHash .. '","realm":"SICK Sensor","opaque":"' .. latestChallengeResponse.challenge.opaque .. '","nonce":"' .. latestChallengeResponse.challenge.nonce .. '"},' .. data .. '}'
+ else
+ requestBody = '{"header":{"user":"' .. imageProcessingParams.secUser .. '","response":"' .. responseHash .. '","realm":"SICK Sensor","opaque":"' .. latestChallengeResponse.challenge.opaque .. '","nonce":"' .. latestChallengeResponse.challenge.nonce .. '"}}'
+ end
+ return requestBody
+end
+
--- Function to trigger SEC camera
---@param command string Command to send to SEC camera
---@param data string Data for command
---@return bool suc Success of trigger
local function triggerSEC(command, data)
- local _, challengeResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/api/getChallenge', 80, nil, '{"data":{"user": "' .. imageProcessingParams.secUser .. '"}}', 'application/json')
- local challengeResponseContent = json.decode(challengeResponse)
- if challengeResponseContent.Response then
+ if latestChallengeResponse == nil then
+ getSECChallenge()
+ end
- local response = json.decode(challengeResponseContent.Response)
+ if latestChallengeResponse.challenge then
+ local requestBody = getRequestBody(command, data)
+ local requestResponse
- if response.challenge then
- local responseHash = computeResponseHash(response.challenge, command, imageProcessingParams.secUser, imageProcessingParams.secUserPassword)
- local requestBody
+ if command == 'latestSnapshot' then
+ _, _, requestResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/file/download/' .. command, 80, nil, requestBody, 'image/jpeg', false)
- if data then
- requestBody = '{"header":{"user":"' .. imageProcessingParams.secUser .. '","response":"' .. responseHash .. '","realm":"SICK Sensor","opaque":"' .. response.challenge.opaque .. '","nonce":"' .. response.challenge.nonce .. '"},' .. data .. '}'
- else
- requestBody = '{"header":{"user":"' .. imageProcessingParams.secUser .. '","response":"' .. responseHash .. '","realm":"SICK Sensor","opaque":"' .. response.challenge.opaque .. '","nonce":"' .. response.challenge.nonce .. '"}}'
+ if requestResponse:getStatusCode() ~= 200 then
+ _G.logger:info(nameOfModule .. ": Did not work. Try again with new challenge.")
+ getSECChallenge()
+ requestBody = getRequestBody(command, data)
+ _, _, requestResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/file/download/' .. command, 80, nil, requestBody, 'image/jpeg', false)
end
- local requestResponse
- local responseData
- if command == 'latestSnapshot' then
- _, requestResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/file/download/' .. command, 80, nil, requestBody, 'image/jpeg')
- responseData = json.decode(requestResponse)
- if responseData.StatusCode == 200 then
- local img = jpeg:decode(responseData.Response)
+ if requestResponse:getStatusCode() == 200 then
+ local imageContent = requestResponse:getContent()
+ if availableAPIs.imageProcessing and imageProcessingParams.secInternalImageProcessing then
+ local img = jpeg:decode(imageContent)
handleOnNewImageProcessing(img)
- return true
else
- _G.logger:warning(nameOfModule .. ": Request did not work.")
- return false
+ Script.notifyEvent('MultiRemoteCamera_OnNewRawImageCamera' .. cameraNumberString, imageContent, DateTime.getTimestamp())
end
+ return true
else
- _, requestResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/api/' .. command, 80, nil, requestBody, 'application/json')
- responseData = json.decode(requestResponse)
- if responseData.StatusCode ~= 200 then
+ _G.logger:warning(nameOfModule .. ": Request did not work.")
+ return false
+ end
+ else
+ _, _, requestResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/api/' .. command, 80, nil, requestBody, 'application/json', false)
+
+ local wrongPasword = nil
+ if command == 'SnapshotMode' then
+ wrongPasword = string.find(requestResponse:getContent(), 'Access Denied')
+ end
+
+ if wrongPasword ~= nil then
+ _G.logger:warning(nameOfModule .. ": No connection to SEC (due to wrong password?).")
+ latestChallengeResponse = nil
+ return false
+ else
+ if requestResponse:getStatusCode() ~= 200 then
+ _G.logger:info(nameOfModule .. ": Did not work. Try again with new challenge.")
+ getSECChallenge()
+ _, _, requestResponse = Script.callFunction('CSK_MultiHTTPClient.sendRequest' .. tostring(imageProcessingParams.httpClientInstance), 'POST', 'http://' .. secIP .. '/api/' .. command, 80, nil, requestBody, 'application/json', false)
+ end
+
+ if requestResponse:getStatusCode() ~= 200 then
_G.logger:warning(nameOfModule .. ": Request did not work.")
return false
else
return true
end
end
- else
- _G.logger:warning(nameOfModule .. ": Request challenge did not work.")
- return false
end
else
+ _G.logger:warning(nameOfModule .. ": Request challenge did not work.")
return false
end
end
@@ -287,8 +343,12 @@ end
---@param format enum Message format.
local function unpackBinaryImage(data, format)
if format == 'BINARY' then
- local img = jpeg:decode(data)
- handleOnNewImageProcessing(img)
+ if availableAPIs.imageProcessing and imageProcessingParams.secInternalImageProcessing then
+ local img = jpeg:decode(data)
+ handleOnNewImageProcessing(img)
+ elseif not imageProcessingParams.secInternalImageProcessing then
+ Script.notifyEvent('MultiRemoteCamera_OnNewRawImageCamera' .. cameraNumberString, data, DateTime.getTimestamp())
+ end
end
end
queue:setFunction(unpackBinaryImage)
@@ -297,6 +357,12 @@ queue:setFunction(unpackBinaryImage)
--################ SEC100 END #################
--#############################################
+-- Function to get latest snapshot after timer expired
+local function getLatestSnapshot()
+ triggerSEC('latestSnapshot')
+end
+Timer.register(tmrLatestSnapshot, 'OnExpired', getLatestSnapshot)
+
--- Function to handle updates of processing parameters from Controller
---@param cameraNo int Number of camera instance to update
---@param parameter string Parameter to update
@@ -305,8 +371,10 @@ local function handleOnNewImageProcessingParameter(cameraNo, parameter, value)
if parameter == 'viewerActive' then
imageProcessingParams[parameter] = value
if value == false then
- viewer:clear()
- viewer:present()
+ if availableAPIs.imageProvider then
+ viewer:clear()
+ viewer:present()
+ end
end
elseif cameraNo == cameraNumber then
if parameter == 'saveLastImage' then
@@ -340,18 +408,22 @@ local function handleOnNewImageProcessingParameter(cameraNo, parameter, value)
end
elseif parameter == 'SEC100_Trigger' then
triggerSEC('SnapshotTriggerSnapshot')
- Script.sleep(200)
- triggerSEC('latestSnapshot')
+ tmrLatestSnapshot:start()
else
if not parameter == 'activeInUI' then
_G.logger:fine(nameOfModule .. ": Update parameter '" .. parameter .. "' of cameraNo." .. tostring(cameraNo) .. " to value = " .. tostring(value))
end
imageProcessingParams[parameter] = value
+ if parameter == 'secSnapshotDelay' then
+ tmrLatestSnapshot:setExpirationTime(value)
+ end
end
elseif parameter == 'activeInUI' then
imageProcessingParams[parameter] = false
- viewer:clear()
- viewer:present()
+ if availableAPIs.imageProvider then
+ viewer:clear()
+ viewer:present()
+ end
end
end
Script.register("CSK_MultiRemoteCamera.OnNewImageProcessingParameter", handleOnNewImageProcessingParameter)
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 87ee8be..f3b2447 100644
--- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_OnNewImage.lua
+++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/FlowConfig/MultiRemoteCamera_OnNewImage.lua
@@ -32,6 +32,7 @@ local function register(handle, _ , callback)
Container.add(handle, "CB_Function", callback)
local instance = Container.get(handle, 'Instance')
+ local imageMode = Container.get(handle, 'ImageMode')
-- Check if amount of instances is valid
-- if not: add multiple additional instances
@@ -46,7 +47,11 @@ local function register(handle, _ , callback)
local function localCallback()
if callback ~= nil then
- Script.callFunction(callback, 'CSK_MultiRemoteCamera.OnNewImageCamera' .. tostring(instance))
+ if imageMode == 'BINARY' then
+ Script.callFunction(callback, 'CSK_MultiRemoteCamera.OnNewRawImageCamera' .. tostring(instance))
+ else
+ Script.callFunction(callback, 'CSK_MultiRemoteCamera.OnNewImageCamera' .. tostring(instance))
+ end
else
_G.logger:warning(nameOfModule .. ": " .. BLOCK_NAMESPACE .. ".CB_Function missing!")
end
@@ -62,7 +67,7 @@ Script.serveFunction(BLOCK_NAMESPACE ..".register", register)
--*************************************************************
--*************************************************************
-local function create(instance)
+local function create(instance, imageMode)
-- Check if same instance is already configured
if instance < 1 or nil ~= instanceTable[instance] then
@@ -73,6 +78,7 @@ local function create(instance)
local handle = Container.create()
instanceTable[instance] = instance
Container.add(handle, 'Instance', instance)
+ Container.add(handle, 'ImageMode', imageMode or 'Image')
Container.add(handle, "CB_Function", "")
return handle
end
diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua
index d5b7c10..3322559 100644
--- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua
+++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Controller.lua
@@ -109,6 +109,8 @@ Script.serveEvent('CSK_MultiRemoteCamera.OnNewPasswordSEC', 'MultiRemoteCamera_O
Script.serveEvent('CSK_MultiRemoteCamera.OnNewStatusSECMode', 'MultiRemoteCamera_OnNewStatusSECMode')
Script.serveEvent('CSK_MultiRemoteCamera.OnNewWebSocketClientInstance', 'MultiRemoteCamera_OnNewWebSocketClientInstance')
Script.serveEvent('CSK_MultiRemoteCamera.OnNewStatusSECStreamIsActive', 'MultiRemoteCamera_OnNewStatusSECStreamIsActive')
+Script.serveEvent('CSK_MultiRemoteCamera.OnNewStatusSECSnapshotDelay', 'MultiRemoteCamera_OnNewStatusSECSnapshotDelay')
+Script.serveEvent('CSK_MultiRemoteCamera.OnNewStatusSECInternalImageProcessing', 'MultiRemoteCamera_OnNewStatusSECInternalImageProcessing')
Script.serveEvent('CSK_MultiRemoteCamera.OnNewStatusFlowConfigPriority', 'MultiRemoteCamera_OnNewStatusFlowConfigPriority')
Script.serveEvent("CSK_MultiRemoteCamera.OnNewStatusLoadParameterOnReboot", "MultiRemoteCamera_OnNewStatusLoadParameterOnReboot")
@@ -299,9 +301,9 @@ local function handleOnExpiredTmrCamera()
Script.notifyEvent("MultiRemoteCamera_OnNewStatusModuleVersion", 'v' .. multiRemoteCamera_Model.version)
Script.notifyEvent("MultiRemoteCamera_OnNewStatusCSKStyle", multiRemoteCamera_Model.styleForUI)
- Script.notifyEvent("MultiRemoteCamera_OnNewStatusModuleIsActive", _G.availableAPIs.default and _G.availableAPIs.imageProvider)
+ Script.notifyEvent("MultiRemoteCamera_OnNewStatusModuleIsActive", _G.availableAPIs.default and (_G.availableAPIs.imageProvider or _G.availableAPIs.SEC100))
- if _G.availableAPIs.default and _G.availableAPIs.imageProvider then
+ if _G.availableAPIs.default and (_G.availableAPIs.imageProvider or _G.availableAPIs.SEC100) then
updateUserLevel()
@@ -343,6 +345,8 @@ local function handleOnExpiredTmrCamera()
Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECMode', multiRemoteCamera_Instances[selectedInstance].parameters.secMode)
Script.notifyEvent('MultiRemoteCamera_OnNewWebSocketClientInstance', multiRemoteCamera_Instances[selectedInstance].parameters.secWebSocketClientInstance)
Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECStreamIsActive', multiRemoteCamera_Instances[selectedInstance].secWebSocketStreamIsActive)
+ Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECSnapshotDelay', multiRemoteCamera_Instances[selectedInstance].parameters.secSnapshotDelay)
+ Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECInternalImageProcessing', multiRemoteCamera_Instances[selectedInstance].parameters.secInternalImageProcessing)
Script.notifyEvent('MultiRemoteCamera_OnNewShutterTime', multiRemoteCamera_Instances[selectedInstance].parameters.shutterTime)
Script.notifyEvent('MultiRemoteCamera_OnNewGain', multiRemoteCamera_Instances[selectedInstance].parameters.gain)
@@ -402,7 +406,7 @@ end
Timer.register(tmrMonitorCameras, "OnExpired", handleOnExpiredTmrMonitorCameras)
local function pageCalled()
- if _G.availableAPIs.default and _G.availableAPIs.imageProvider then
+ if _G.availableAPIs.default and (_G.availableAPIs.imageProvider or _G.availableAPIs.SEC100) then
updateUserLevel() -- try to hide user specific content asap
end
tmrCamera:start()
@@ -520,15 +524,20 @@ local function setCameraModel (camModel)
end
else
if camModel == 'PicoMidiCam' then
- setGigEVision(false)
- if multiRemoteCamera_Instances[selectedInstance].parameters.gigEvision == false then
- multiRemoteCamera_Instances[selectedInstance].parameters.cameraModel = camModel
+ if _G.availableAPIs.I2D then
+ setGigEVision(false)
+ if multiRemoteCamera_Instances[selectedInstance].parameters.gigEvision == false then
+ multiRemoteCamera_Instances[selectedInstance].parameters.cameraModel = camModel
+ else
+ _G.logger:warning(nameOfModule .. ": Features of camera model '" .. camModel .. "'' not available.")
+ end
+ Script.notifyEvent('MultiRemoteCamera_OnNewCameraModel', multiRemoteCamera_Instances[selectedInstance].parameters.cameraModel)
+ multiRemoteCamera_Instances[selectedInstance].customCameraActive = false
+ multiRemoteCamera_Instances[selectedInstance].cameraParameters = 'Others'
else
- _G.logger:warning(nameOfModule .. ": Features of camera model '" .. camModel .. "'' not available.")
+ _G.logger:warning(nameOfModule .. ": Pico/MidiCam features not available.")
+ Script.notifyEvent('MultiRemoteCamera_OnNewCameraModel', multiRemoteCamera_Instances[selectedInstance].parameters.cameraModel)
end
- Script.notifyEvent('MultiRemoteCamera_OnNewCameraModel', multiRemoteCamera_Instances[selectedInstance].parameters.cameraModel)
- multiRemoteCamera_Instances[selectedInstance].customCameraActive = false
- multiRemoteCamera_Instances[selectedInstance].cameraParameters = 'Others'
else
setGigEVision(true)
if multiRemoteCamera_Instances[selectedInstance].parameters.gigEvision == true then
@@ -592,6 +601,20 @@ local function setSEC100UserPassword(password)
end
Script.serveFunction('CSK_MultiRemoteCamera.setSEC100UserPassword', setSEC100UserPassword)
+local function setSEC100SnapshotDelay(delay)
+ _G.logger:fine(nameOfModule .. ": Set delay to download latest snapshot to " .. tostring(delay))
+ multiRemoteCamera_Instances[selectedInstance].parameters.secSnapshotDelay = delay
+ Script.notifyEvent('MultiRemoteCamera_OnNewImageProcessingParameter', selectedInstance, 'secSnapshotDelay', delay)
+end
+Script.serveFunction('CSK_MultiRemoteCamera.setSEC100SnapshotDelay', setSEC100SnapshotDelay)
+
+local function setSEC100InternalImageProcessing(status)
+ _G.logger:fine(nameOfModule .. ": Set status to only forward SEC raw images to " .. tostring(status))
+ multiRemoteCamera_Instances[selectedInstance].parameters.secInternalImageProcessing = status
+ Script.notifyEvent('MultiRemoteCamera_OnNewImageProcessingParameter', selectedInstance, 'secInternalImageProcessing', status)
+end
+Script.serveFunction('CSK_MultiRemoteCamera.setSEC100InternalImageProcessing', setSEC100InternalImageProcessing)
+
local function connectCamera()
-- Try to connect the camera
_G.logger:info(nameOfModule .. ": Try to connect to camera no. " .. tostring(selectedInstance))
@@ -749,8 +772,10 @@ local function setSECMode(mode)
Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECMode', multiRemoteCamera_Instances[selectedInstance].parameters.secMode)
Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECStreamIsActive', multiRemoteCamera_Instances[selectedInstance].secWebSocketStreamIsActive)
elseif mode == 'Snapshot' then
+ setSECStreamStatus(false)
multiRemoteCamera_Instances[selectedInstance].parameters.secMode = mode
Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECMode', multiRemoteCamera_Instances[selectedInstance].parameters.secMode)
+ Script.notifyEvent('MultiRemoteCamera_OnNewStatusSECSnapshotDelay', multiRemoteCamera_Instances[selectedInstance].parameters.secSnapshotDelay)
CSK_MultiWebSocketClient.setConnectionStatus(false)
end
Script.notifyEvent('MultiRemoteCamera_OnNewImageProcessingParameter', selectedInstance, 'secMode', multiRemoteCamera_Instances[selectedInstance].parameters.secMode)
@@ -980,9 +1005,14 @@ end
Script.serveFunction("CSK_MultiRemoteCamera.setTempImageActive", setTempImageActive)
local function setViewerActive(status)
- _G.logger:fine(nameOfModule .. ": Viewer active: " .. tostring(status))
- viewerActive = status
- Script.notifyEvent('MultiRemoteCamera_OnNewImageProcessingParameter', selectedInstance, 'viewerActive', viewerActive)
+ if _G.availableAPIs.imageProvider then
+ _G.logger:fine(nameOfModule .. ": Viewer active: " .. tostring(status))
+ viewerActive = status
+ Script.notifyEvent('MultiRemoteCamera_OnNewImageProcessingParameter', selectedInstance, 'viewerActive', viewerActive)
+ else
+ _G.logger:info(nameOfModule .. ": Viewer not supported.")
+ Script.notifyEvent('MultiRemoteCamera_OnNewStatusViewerActive', false)
+ end
end
Script.serveFunction("CSK_MultiRemoteCamera.setViewerActive", setViewerActive)
@@ -1126,7 +1156,7 @@ end
Script.serveFunction('CSK_MultiRemoteCamera.restartAllCameras', restartAllCameras)
local function getStatusModuleActive()
- return _G.availableAPIs.default and _G.availableAPIs.imageProvider
+ return _G.availableAPIs.default and (_G.availableAPIs.imageProvider or _G.availableAPIs.SEC100)
end
Script.serveFunction('CSK_MultiRemoteCamera.getStatusModuleActive', getStatusModuleActive)
@@ -1262,7 +1292,7 @@ Timer.register(tmrCameraBootUp, 'OnExpired', setupCamerasAfterBootUp)
--- Function to react on initial load of persistent parameters
local function handleOnInitialDataLoaded()
- if _G.availableAPIs.default and _G.availableAPIs.imageProvider then
+ if _G.availableAPIs.default and (_G.availableAPIs.imageProvider or _G.availableAPIs.SEC100) then
_G.logger:fine(nameOfModule .. ': Try to initially load parameter from CSK_PersistentData module.')
-- Check if CSK_PersistentData version is > 1.x.x
@@ -1320,12 +1350,12 @@ local function handleOnInitialDataLoaded()
end
end
end
-if _G.availableAPIs.default and _G.availableAPIs.imageProvider then
+if _G.availableAPIs.default and (_G.availableAPIs.imageProvider or _G.availableAPIs.SEC100) then
Script.register("CSK_PersistentData.OnInitialDataLoaded", handleOnInitialDataLoaded)
end
local function resetModule()
- if _G.availableAPIs.default and _G.availableAPIs.specific then
+ if _G.availableAPIs.default and (_G.availableAPIs.imageProvider or _G.availableAPIs.SEC100) then
for i = 1, #multiRemoteCamera_Instances do
setSelectedInstance(i)
stopCamera()
diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua
index 2e0ae90..cd084e2 100644
--- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua
+++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Model.lua
@@ -36,7 +36,7 @@ for i = 1, 10 do
table.insert(multiRemoteCamera.swTriggerFunctions, triggerCamera)
end
-if _G.availableAPIs.imageProvider then
+if _G.availableAPIs.ethernet then
multiRemoteCamera.interfaces = Ethernet.Interface.getInterfaces()
table.insert(multiRemoteCamera.interfaces, 'Localhost')
end
@@ -96,7 +96,11 @@ function multiRemoteCamera.create(cameraNo)
self.gigEVisionConfigUITable = nil -- Content of custom GigEVision setting for UI table
self.customCameraActive = false -- TRUE if camera model == 'CUSTOM'
- self.cameraParameters = 'Others' -- Type of camera parameters to show in UI
+ if _G.availableAPIs.imageProvider and (_G.availableAPIs.I2D or _G.availableAPIs.GigEVision) then
+ self.cameraParameters = 'Others' -- Type of camera parameters to show in styleForUI
+ elseif _G.availableAPIs.SEC100 then
+ self.cameraParameters = 'SEC100'
+ end
self.triggerFunction = nil -- Internally used function to SW trigger the camera
@@ -132,6 +136,8 @@ function multiRemoteCamera.create(cameraNo)
self.imageProcessingParams:add('secUserPassword', self.parameters.secUserPassword, "STRING")
self.imageProcessingParams:add('secMode', self.parameters.secMode, "STRING")
self.imageProcessingParams:add('secWebSocketClientInstance', self.parameters.secWebSocketClientInstance, "INT")
+ self.imageProcessingParams:add('secSnapshotDelay', self.parameters.secSnapshotDelay, "INT")
+ self.imageProcessingParams:add('secInternalImageProcessing', self.parameters.secInternalImageProcessing, "BOOL")
return self
end
@@ -233,6 +239,8 @@ function multiRemoteCamera:connectCamera()
else
_G.logger:warning(nameOfModule .. ": Not possible to connect to Camera No. ".. tostring(self.parameters.cameraNo))
end
+ Script.notifyEvent('MultiRemoteCamera_OnCameraConnected', self.isConnected)
+ _G.logger:info(nameOfModule .. ': Connection to camera = ' .. tostring(self.isConnected))
else
local instanceAmount = CSK_MultiHTTPClient.getInstancesAmount()
if instanceAmount >= self.parameters.httpClientInstance then
@@ -250,10 +258,7 @@ function multiRemoteCamera:connectCamera()
end
end
- Script.notifyEvent('MultiRemoteCamera_OnCameraConnected', self.isConnected)
- _G.logger:info(nameOfModule .. ': Connection to camera = ' .. tostring(self.isConnected))
Script.notifyEvent("MultiRemoteCamera_OnScanCamera", false)
-
CSK_MultiRemoteCamera.pageCalled()
end
diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters.lua
index 3a6c608..982911f 100644
--- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters.lua
+++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/MultiRemoteCamera_Parameters.lua
@@ -38,10 +38,18 @@ local function getParameters()
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', 'SEC100'
+ if _G.availableAPIs.GigEVision then
+ multiRemoteCameraParameters.cameraModel = "PicoMidiCam2" -- 'a2A1920-51gcBAS', 'CustomConfig', 'SEC100'
+ elseif _G.availableAPIs.I2D then
+ multiRemoteCameraParameters.cameraModel = "PicoMidiCam" -- Version 1
+ elseif _G.availableAPIs.SEC100 then
+ multiRemoteCameraParameters.cameraModel = "SEC100" -- 'a2A1920-51gcBAS', 'CustomConfig', 'SEC100'
+ end
multiRemoteCameraParameters.secUser = 'Service' -- User to login to SEC camera
multiRemoteCameraParameters.secUserPassword = '' -- User password to login to SEC camera
multiRemoteCameraParameters.secMode = 'Snapshot' -- Mode to run SEC camera
+ multiRemoteCameraParameters.secInternalImageProcessing = true -- Convert raw images for internal image processing (TRUE) or only forward raw images (FALSE)
+ multiRemoteCameraParameters.secSnapshotDelay = 400 -- Time to wait before downloading latest snapshot
-- Image processing parameters
multiRemoteCameraParameters.processingMode = "BOTH" -- 'SCRIPT', 'APP', 'BOTH' --> see "setProcessingMode"
diff --git a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/checkAPIs.lua b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/checkAPIs.lua
index bb8148c..04ca94e 100644
--- a/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/checkAPIs.lua
+++ b/CSK_Module_MultiRemoteCamera/scripts/Sensors/MultiRemoteCamera/helper/checkAPIs.lua
@@ -40,11 +40,17 @@ local function loadSpecificAPIs()
Image = require 'API.Image'
Image.Provider = {}
Image.Provider.RemoteCamera = require 'API.Image.Provider.RemoteCamera'
+ View = require 'API.View'
+end
+
+local function loadEthernetSpecificAPIs()
Ethernet = require 'API.Ethernet'
Ethernet.Interface = require 'API.Ethernet.Interface'
+end
+
+-- Function to load flow specific API
+local function loadFlowSpecific()
Flow = require 'API.Flow'
- Image = require 'API.Image'
- View = require 'API.View'
end
-- Function to load specific I2D APIs
@@ -66,9 +72,6 @@ local function loadSEC100SpecificAPIs()
Hash = {}
Hash.SHA256 = require 'API.Hash.SHA256'
- Image.Format = {}
- Image.Format.JPEG = require 'API.Image.Format.JPEG'
-
-- Check if related CSK modules are available to be used
local appList = Engine.listApps()
for i = 1, #appList do
@@ -91,10 +94,20 @@ local function loadSEC100StreamSpecificAPIs()
end
end
+local function loadImageProcessingSpecificAPIs()
+ Image.Format = {}
+ Image.Format.JPEG = require 'API.Image.Format.JPEG'
+end
+
availableAPIs.default = xpcall(loadAPIs, debug.traceback) -- TRUE if all default APIs were loaded correctly
availableAPIs.imageProvider = xpcall(loadSpecificAPIs, debug.traceback) -- TRUE if all specific APIs were loaded correctly
availableAPIs.I2D = xpcall(loadI2DSpecificAPIs, debug.traceback) -- TRUE if all I2D specific APIs were loaded correctly
availableAPIs.GigEVision = xpcall(loadGigEVisionSpecificAPIs, debug.traceback) -- TRUE if all GigE Vision specific APIs were loaded correctly
+availableAPIs.imageProcessing = xpcall(loadImageProcessingSpecificAPIs, debug.traceback) -- TRUE if all SEC100 specific APIs were loaded correctly
+
+availableAPIs.ethernet = xpcall(loadEthernetSpecificAPIs, debug.traceback) -- TRUE if all default APIs were loaded correctly
+availableAPIs.flow = xpcall(loadFlowSpecific, debug.traceback) -- TRUE if all default APIs were loaded correctly
+
availableAPIs.SEC100 = xpcall(loadSEC100SpecificAPIs, debug.traceback) -- TRUE if all SEC100 specific APIs were loaded correctly
availableAPIs.SEC100Stream = xpcall(loadSEC100StreamSpecificAPIs, debug.traceback) -- TRUE if all SEC100 specific APIs were loaded correctly
diff --git a/README.md b/README.md
index 9a7c139..665f2ee 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ Following CSK modules are necessary if you want to run it with SEC cameras:
|Module|Version|Remark
|--|--|--|
-|CSK_Module_MultiHTTPClient|[V2.2.0](https://github.com/SICKAppSpaceCodingStarterKit/CSK_Module_MultiHTTPClient/releases/tag/v2.2.0)|
+|CSK_Module_MultiHTTPClient|[V2.3.0](https://github.com/SICKAppSpaceCodingStarterKit/CSK_Module_MultiHTTPClient/releases/tag/v2.3.0)|
|CSK_Module_MultiWebSocketClient|[V1.0.0](https://github.com/SICKAppSpaceCodingStarterKit/CSK_Module_MultiWebSocketClient/releases/tag/v1.0.0)|
## Information
@@ -26,6 +26,7 @@ Tested on
|Device|Firmware|Module version|
|--|--|--|
+|SIM800|V1.2.0|V6.3.0|
|SIM2x00|V1.8.0|V6.1.1|
|SIM2x00|V1.8.0|V6.1.0|
|SIM1012|V2.4.2|V6.1.0|
diff --git a/docu/CSK_Module_MultiRemoteCamera.html b/docu/CSK_Module_MultiRemoteCamera.html
index 011b9e9..736ee76 100644
--- a/docu/CSK_Module_MultiRemoteCamera.html
+++ b/docu/CSK_Module_MultiRemoteCamera.html
@@ -6,7 +6,7 @@
-Documentation - CSK_Module_MultiRemoteCamera 6.2.0
+Documentation - CSK_Module_MultiRemoteCamera 6.3.0