<?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);
        }
        else {
            $this->port = new \LocalScalesComPort($sets['url']);
        }

        if(!$this->config['WaitTime']) $this->config['WaitTime']=10;
        if(!$this->config['Attempts']) $this->config['Attempts']=1;
        if($this->config['AlwaysExec']) {
            $this->always_exec($this->config['AlwaysExec']);
        }
	}

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

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

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

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

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

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

    // Узнать вес
    function weight() {
        $weight=false;
        // Получаем статус весов
        $pars='0e';
        $res=$this->send_command($pars, 4);
        if(mb_substr($res, -4)=='0d0a') {
            $s1=mb_substr($res, 0, 2);
            $s1=strrev(decbin(hexdec($s1)));
            $s1=str_pad($s1, 8, "0", STR_PAD_RIGHT);
            if((int)mb_substr($s1, 2, 1)==1) {
                $error_txt='Весы перегружены';
                $this->f3->get('logs_model')->save_log($error_txt.' (Весы)');
                return array(
                    'success'=>false,
                    'txt'=>$error_txt,
                );
            }

            if((int)mb_substr($s1, 4, 1)==1) {
                $error_txt='Не удалось получить вес. Вес нестабильный.';
                $this->f3->get('logs_model')->save_log($error_txt.' (Весы)');
                return array(
                    'success'=>false,
                    'txt'=>$error_txt,
                );
            }

            $s2=mb_substr($res, 2, 2);
            $s2=strrev(decbin(hexdec($s2)));
            $s2=str_pad($s2, 2, "0", STR_PAD_RIGHT);
            $k=1000;
            if($s2=='00') {
                $k=0;
            }
            elseif($s2=='01'){
                $k=10;
            }
            elseif($s2=='10'){
                $k=100;
            }
            elseif($s2=='11'){
                $k=1000;
            }

            // Получаем вес
            $pars='0a';

            $res=$this->send_command($pars, 20);
            if(mb_substr($res, -4)=='0d0a') {
                $weight='';
                for($i=10; $i>=0; $i-=2) {
                    $weight.=hexdec(mb_substr($res, $i, 2));
                }
                $weight=(int)$weight;
                if((int)mb_substr($s1, 1, 1)==1) {
                    $weight=-$weight;
                }
            }
        }
        if(is_numeric($weight)) {
            return array(
                'success'=>true,
                'weight'=>round($weight/$k, 3)
            );
        }
        $error_txt='Не удалось получить вес';
        $this->f3->get('logs_model')->save_log($error_txt.' (Весы)');
        return array(
            'success'=>false,
            'txt'=>$error_txt,
            'res'=>$weight
        );
    }
}
