patbef-iOS/Befund/Controllers/ScannerController.swift

280 lines
7.9 KiB
Swift

//
// 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
{
self.found(code: "befund://labor?id=DEVELOPMENT")
}
#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
}
}