2024-01-29 16:20:42 +01:00
|
|
|
//
|
|
|
|
// ScannerController.swift
|
|
|
|
// Befund
|
|
|
|
//
|
|
|
|
// Created by Artur Savitskiy on 29.08.22.
|
|
|
|
// Copyright © 2022 MVZ Dr. Stein und Kollegen. All rights reserved.
|
|
|
|
//
|
|
|
|
|
|
|
|
import AVFoundation
|
|
|
|
import UIKit
|
|
|
|
|
|
|
|
class ScannerViewController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
|
|
|
|
var captureSession: AVCaptureSession!
|
|
|
|
var previewLayer: AVCaptureVideoPreviewLayer!
|
|
|
|
|
|
|
|
var scanFailed: Bool = false
|
|
|
|
var laborIsSelected: Bool = false
|
|
|
|
|
|
|
|
private var isBarcodeScan = false
|
|
|
|
|
|
|
|
@IBOutlet weak var btnBack: UIButton!
|
|
|
|
|
|
|
|
enum CameraAutorizationStatus{
|
|
|
|
case None
|
|
|
|
case Autorized
|
|
|
|
case Declined
|
|
|
|
}
|
|
|
|
|
|
|
|
public static func InitScannerController( scanSampleID: Bool) -> ScannerViewController
|
|
|
|
{
|
|
|
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
|
|
|
let scanController = storyboard.instantiateViewController(identifier: "ScannerController") as ScannerViewController
|
|
|
|
|
|
|
|
scanController.isBarcodeScan = scanSampleID
|
|
|
|
|
|
|
|
return scanController
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override func viewDidLoad() {
|
|
|
|
super.viewDidLoad()
|
|
|
|
view.backgroundColor = UIColor.gray
|
|
|
|
}
|
|
|
|
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
|
|
super.viewDidAppear(animated)
|
|
|
|
|
|
|
|
let status = self.checkCameraAutorizationStatus()
|
|
|
|
if ( status == CameraAutorizationStatus.Declined) {
|
|
|
|
failedWithAlert()
|
|
|
|
}
|
|
|
|
else if (status == CameraAutorizationStatus.Autorized)
|
|
|
|
{
|
|
|
|
StartCapture()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private func StartCapture()
|
|
|
|
{
|
|
|
|
if (captureSession == nil)
|
|
|
|
{
|
|
|
|
|
|
|
|
captureSession = AVCaptureSession()
|
|
|
|
|
|
|
|
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else {
|
|
|
|
failed()
|
|
|
|
return }
|
|
|
|
|
|
|
|
let videoInput: AVCaptureDeviceInput
|
|
|
|
|
|
|
|
do {
|
|
|
|
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
|
|
|
|
} catch {
|
|
|
|
failed()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (captureSession.canAddInput(videoInput)) {
|
|
|
|
captureSession.addInput(videoInput)
|
|
|
|
} else {
|
|
|
|
failed()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
let metadataOutput = AVCaptureMetadataOutput()
|
|
|
|
|
|
|
|
if (captureSession.canAddOutput(metadataOutput)) {
|
|
|
|
captureSession.addOutput(metadataOutput)
|
|
|
|
|
|
|
|
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
|
|
|
|
if (isBarcodeScan)
|
|
|
|
{
|
|
|
|
metadataOutput.metadataObjectTypes = [.code128, .code39, .code39Mod43, .code93, .ean13, .ean8, .interleaved2of5, .itf14, .pdf417, .upce]
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
metadataOutput.metadataObjectTypes = [.qr]
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
failed()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
|
|
|
|
previewLayer.frame = view.layer.bounds
|
|
|
|
previewLayer.videoGravity = .resizeAspectFill
|
|
|
|
view.layer.addSublayer(previewLayer)
|
|
|
|
|
|
|
|
btnBack.superview?.bringSubviewToFront(btnBack);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (captureSession?.isRunning == false) {
|
|
|
|
captureSession.startRunning()
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkCameraAutorizationStatus() -> CameraAutorizationStatus
|
|
|
|
{
|
|
|
|
switch AVCaptureDevice.authorizationStatus(for: .video)
|
|
|
|
{
|
|
|
|
case .authorized:
|
|
|
|
return CameraAutorizationStatus.Autorized
|
|
|
|
case .notDetermined:
|
|
|
|
AVCaptureDevice.requestAccess(for: .video) {
|
|
|
|
granted in
|
|
|
|
if granted {
|
|
|
|
DispatchQueue.main.async
|
|
|
|
{
|
|
|
|
self.StartCapture()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DispatchQueue.main.async
|
|
|
|
{
|
|
|
|
self.return2MainWindow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return CameraAutorizationStatus.None
|
|
|
|
case .denied:
|
|
|
|
return CameraAutorizationStatus.Declined
|
|
|
|
case .restricted:
|
|
|
|
return CameraAutorizationStatus.Declined
|
|
|
|
@unknown default:
|
|
|
|
return CameraAutorizationStatus.Declined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func failed()
|
|
|
|
{
|
|
|
|
scanFailed = true
|
|
|
|
captureSession = nil
|
|
|
|
failedWithAlert()
|
|
|
|
}
|
|
|
|
|
|
|
|
func failedWithAlert() {
|
|
|
|
let ac = UIAlertController(title: Core.Lang.Get(key: "LBL_SCAN_NOT_SUPPORTED"), message: Core.Lang.Get(key: "MSG_SCAN_NOT_SUPPORTED"), preferredStyle: .alert)
|
|
|
|
ac.addAction(UIAlertAction(title: "OK", style: .default, handler: failedWithAlertOk))
|
|
|
|
let settingsAction = UIAlertAction(title: "Einstellungen", style: .default, handler: OpenSettings)
|
|
|
|
ac.addAction(settingsAction)
|
|
|
|
self.present(ac, animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
func OpenSettings(alert: UIAlertAction!)
|
|
|
|
{
|
|
|
|
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else
|
|
|
|
{
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UIApplication.shared.canOpenURL(settingsUrl)){
|
|
|
|
UIApplication.shared.open(settingsUrl)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func failedWithAlertOk(alert: UIAlertAction!) {
|
|
|
|
#if DEBUG
|
|
|
|
if (isBarcodeScan)
|
|
|
|
{
|
|
|
|
self.foundBarcode(code: "123456789ABCDE")
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-06-03 12:05:19 +02:00
|
|
|
self.found(code: "befund://labor?id=DEVELOPMENT")
|
2024-01-29 16:20:42 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
if (!laborIsSelected)
|
|
|
|
{
|
|
|
|
self.return2MainWindow()
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
override func viewWillDisappear(_ animated: Bool) {
|
|
|
|
super.viewWillDisappear(animated)
|
|
|
|
|
|
|
|
if (captureSession?.isRunning == true) {
|
|
|
|
captureSession.stopRunning()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
|
|
|
|
captureSession.stopRunning()
|
|
|
|
|
|
|
|
if let metadataObject = metadataObjects.first {
|
|
|
|
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
|
|
|
|
guard let stringValue = readableObject.stringValue else { return }
|
|
|
|
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
|
|
|
|
if (isBarcodeScan)
|
|
|
|
{
|
|
|
|
foundBarcode(code: stringValue)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
found(code: stringValue)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
dismiss(animated: true)
|
|
|
|
}
|
|
|
|
|
|
|
|
func found(code: String) {
|
|
|
|
if(code.count>0)
|
|
|
|
{
|
|
|
|
let posIndex = code.range(of: "id=")!.lowerBound
|
|
|
|
let index = code.distance(from: code.startIndex, to: posIndex)
|
|
|
|
let substr = code.dropFirst(index)
|
|
|
|
let labID = substr.replacingOccurrences(of: "id=", with: "")
|
|
|
|
let labor = Core.Models.Labor.GetLaborByName(id: labID)
|
|
|
|
if (labor.id.count>0)
|
|
|
|
{
|
|
|
|
self.SelectLabor(labor: labor)
|
|
|
|
self.return2MainWindow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func foundBarcode(code: String) {
|
|
|
|
if(code.count>0)
|
|
|
|
{
|
|
|
|
ViewController.currentlySelectedBarcode = code
|
|
|
|
self.return2MainWindow()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func SelectLabor(labor: Core.Models.Labor)
|
|
|
|
{
|
|
|
|
var settings = Core.Models.Settings.loadFromFile(atPath: Core.System.SettingsPath())
|
|
|
|
if (settings == nil)
|
|
|
|
{
|
|
|
|
settings = Core.Models.Settings()
|
|
|
|
}
|
|
|
|
settings!.labor = labor
|
|
|
|
laborIsSelected = settings!.save(atPath: Core.System.SettingsPath())
|
|
|
|
}
|
|
|
|
|
|
|
|
@IBAction func goBack(_ sender: Any)
|
|
|
|
{
|
|
|
|
self.return2MainWindow()
|
|
|
|
}
|
|
|
|
|
|
|
|
private func return2MainWindow()
|
|
|
|
{
|
|
|
|
self.view.endEditing(true)
|
|
|
|
self.dismiss(animated: true, completion: nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
override var prefersStatusBarHidden: Bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
|
|
|
|
return .portrait
|
|
|
|
}
|
|
|
|
}
|