<?php
namespace Models;

class Scales_php {
	public $f3, $sets, $config, $port, $open=false;
	
	function __construct($f3, $sets, $config) {
		$this->f3=$f3;
		$this->sets=$sets;
        $this->config=$config;
		//$this->config=parse_ini_file($sets['driver'].'/server.config'); // Настройки драйвера
        require_once $sets['driver'].'/Scales.ports.php';
        $this->config['PortType']=strtolower($this->config['PortType']);
        if($this->config['PortType']=='remote') {
            $sets['url']=mb_substr($sets['url'], mb_strrpos($sets['url'], '/')+1);
            $url=explode(':', $sets['url']);
            $host = $url[0];
            $port = $url[1];
            $this->port = new \RemoteScalesPort($host, $port);
        }
        elseif($this->config['PortType']=='socket') {
            $sets['url']=mb_substr($sets['url'], mb_strrpos($sets['url'], '/')+1);
            $url=explode(':', $sets['url']);
            $host = $url[0];
            $port = $url[1];
            $this->port = new \RemoteScalesSocket($host, $port);
        }
        elseif($this->config['PortType']=='ssh') {
            $u=mb_substr($sets['url'], mb_strrpos($sets['url'], '/'));
            $url=explode(':', $u);
            $host = $url[0];
            $port = $url[1];
            $this->port = new \SshScalesComPort($host, $port);
        }
        elseif($this->config['PortType']=='comport') {
			$this->port = new \comportScalesComPort($sets['url']);
		}
        else {
            $this->port = new \LocalScalesComPort($sets['url']);
        }
        
        if(!$this->config['WaitTime']) $this->config['WaitTime']=100000;
        if(!$this->config['Attempts']) $this->config['Attempts']=50;
        if(!$this->config['WeightStatusAttempts']) $this->config['WeightStatusAttempts']=10;
        if(!$this->config['WeightStatusWaitTime']) $this->config['WeightStatusWaitTime']=1;
        if($this->config['AlwaysExec']) {
            $this->always_exec($this->config['AlwaysExec']);
        }
	}

    function always_exec($exec) {
        foreach ($exec as $cmd) {
            if($cmd!='') {
                exec($cmd);
            }
        }
    }

    function prepareArg($num, $bytes) {
        return implode('', str_split(sprintf('%0' . ($bytes * 2) . 'x', $num), 2));
    }

    function port_open() {
        $this->open=$this->port->open();
        if(!$this->open) {
            echo $error_txt='Не удалось подключиться';
            $this->f3->get('logs_model')->save_log($error_txt.' (Весы)', 'error');
            exit();
        };
    }

    function send_command($str, $len) {
        $data=pack('H*', $str);

        if(!$this->open) {
            $this->port_open();
        }

        $res=$this->port->write($data);
        $answer='';
        if($res) {
            $n=0;
            while ($n<$this->config['Attempts']) {
                usleep($this->config['WaitTime']);
                $answer.=$this->port->read($len, 400);
                if(strlen($answer)==$len) {
                    break;
                }
                $n++;
            }
            if(!$answer) {
                echo $error_txt='Не удалось прочитать ответ: '.$str;
                $this->f3->get('logs_model')->save_log($error_txt.' (Весы)', 'error');
                exit();
            }
            return $answer;
        }
        else {
            echo $error_txt='Не удалось отправить команду: '.$str;
            $this->f3->get('logs_model')->save_log($error_txt.' (Весы)', 'error');
            exit();
        }
    }

	function scales_init() {
		//$this->f3->set('SESSION.drivers_init', 1);
	}

    // Узнать вес
    function weight() {
        $res=$this->send_command('05', 1);
        if(unpack('H*', $res)[1]!='06') {
            $error_txt='Весы неготовы';
            $this->f3->get('logs_model')->save_log($error_txt.' (Весы)', 'error');
            return array(
                'success'=>false,
                'txt'=>$error_txt,
            );
        }
        
        $res=$this->send_command('11', 15);
        $sta=mb_substr($res, 2, 1);
        if(mb_strtolower($sta)=='u') {
            $this->config['WeightStatusAttempts']-=1;
            if($this->config['WeightStatusAttempts']>0) {
                sleep($this->config['WeightStatusWaitTime']);
                return $this->weight();
            }
            else {
                $error_txt='Не удалось получить вес. Вес нестабильный.';
                $this->f3->get('logs_model')->save_log($error_txt.' (Весы)', 'error');
                return array(
                    'success'=>false,
                    'txt'=>$error_txt,
                );
            }
        }
        $sign=mb_substr($res, 3, 1);
        if(mb_strtolower($sign)=='f') {
            $error_txt='Весы перегружены';
            $this->f3->get('logs_model')->save_log($error_txt.' (Весы)', 'error');
            return array(
                'success'=>false,
                'txt'=>$error_txt,
            );
        }
        $weight=mb_substr($res, 4, 6);
        if($sign=='-') {
            $weight=-$weight;
        }

        if(is_numeric($weight)) {
            return array(
                'success'=>true,
                'weight'=>$weight
            );
        }
        $error_txt='Не удалось получить вес';
        $this->f3->get('logs_model')->save_log($error_txt.' (Весы)', 'error');
        return array(
            'success'=>false,
            'txt'=>$error_txt,
        );
    }
}
