Вопрос знатокам PHP под Win

Использование системы в различных ситуациях, вопросы программирования сценариев.

Модератор: immortal

Victor_S
Сообщения: 265
Зарегистрирован: Пт дек 26, 2014 1:58 pm
Благодарил (а): 33 раза
Поблагодарили: 24 раза

Вопрос знатокам PHP под Win

Сообщение Victor_S » Пн апр 06, 2015 11:28 am

Пытаюсь подключить электросчетчики к МД по RS485. Все темы на этом и соседнем(ab-log) форумах по данному вопросу перечитал, собственно и скрипты там взяты. Столкнулся с проблемой подключения к виртуальному последовательному порту под Win7 prof 64. Команда exec() по настройке порта отрабатывает(видно по морганию светодиодов на "свистке"), а дальше ни dio_open(), ни fopen() ни в какую не хотят работать...:(
dio_open() никак не хочет понимать, что я хочу открыть порт, а не файл и выдает ошибку открытия файла.
fopen() никаких ошибок не выдает, просто молча висит какое-то время и отваливается по тайм-ауту.
При этом в обоих случаях светодиоды на "свистке" не регистрируют никаких попыток открытия порта, однако после данных команд даже родная прога от счетчиков не хочет соединяться пока не передерну "свисток", выдавая сообщение "порт не открыт".
Возможно есть какие-то хитрости с именем порта под Win7, хотя пытался по всякому. Может какие настройки в конфигурации PHP нужно подкрутить? Может другие библиотеки для работы с портами установить?(находил в сети что-то вроде PHP Serial extension)
В общем, как говорится, "прошу помощи зала...", ибо у самого на данный момент мысли иссякли...:)
Ivan
Сообщения: 1473
Зарегистрирован: Сб окт 12, 2013 11:03 pm
Благодарил (а): 49 раз
Поблагодарили: 327 раз

Re: Вопрос знатокам PHP под Win

Сообщение Ivan » Пн апр 06, 2015 11:35 am

Какой счётчик у вас?

Проблем с открытием не должно быть. Покажите ваш код
Linux, Raspberry PI, MySensors
Connect: http://connect.smartliving.ru/profile/53
Мои проекты: http://smartliving.ru/profile/4
Victor_S
Сообщения: 265
Зарегистрирован: Пт дек 26, 2014 1:58 pm
Благодарил (а): 33 раза
Поблагодарили: 24 раза

Re: Вопрос знатокам PHP под Win

Сообщение Victor_S » Пн апр 06, 2015 11:43 am

Счетчики Меркурий 236, но до соединения не доходит, проблема в открытии порта.
Пробую так:
<?

// BUS Type: RS485 or CAN
define('BUS', 'RS485');

###### WIN32 WORKAROUND

// Helper function
function getmicrotime(){
list($usec, $sec) = explode(' ',microtime());
return ((float)$usec + (float)$sec);
}

// usleep alias function for windows
function msleep($micro_seconds=0) {
$stop = getmicrotime() + ($micro_seconds / 1000);
while (getmicrotime() <= $stop) {
// loop
}
return true;
}

/*
function usleep_win($msec) {
$usec = $msec * 1000;
socket_select($read = NULL, $write = NULL, $sock = array(socket_create (AF_INET, SOCK_RAW, 0)), 0, $usec);
}
*/

function usleep_win($msec) {
usleep($msec * 1000);
}

exec('mode com3: baud=9600 data=8 stop=1 parity=n xon=off');
$fd = dio_open('COM3', O_RDWR);

###### WIN32 WORKAROUND


##### FOR LINUX BOX

//dio_fcntl($fd, F_SETFL, O_SYNC);

/*
dio_tcsetattr($fd, array(
'baud' => 9600,
'bits' => 8,
'stop' => 1,
'parity' => 0
));
*/

##############

function merc_gd($cmd, $factor = 1, $total = 0)
{
global $fd;
global $sleep_time;

usleep_win(50);
flush();
dio_write($fd, $cmd, 6);
usleep_win($sleep_time);
$result = dio_read($fd, 64);

$ret = array();

if ( BUS == "CAN" )
$start_byte = 7;
else
$start_byte = 1;

if ( $total != 1 )
{
for ( $i = 0; $i < 4; $i++ )
{
if ( dechex(ord($result[$start_byte + $i * 3])) >= 40 )
$result[$start_byte + $i * 3] = chr(dechex(ord($result[$start_byte + $i * 3])) - 40);
if ( strlen($result) > $start_byte + 2 + $i * 3 )
$ret[$i] = hexdec(dd($result[$start_byte + $i * 3]).dd($result[$start_byte + $i * 3 + 2]).dd($result[$start_byte + $i * 3 + 1]))*$factor;
}
}
else
$ret[0] = hexdec(dd($result[$start_byte+1]).dd($result[$start_byte]).dd($result[$start_byte+3]).dd($result[$start_byte+2]))*$factor;


return $ret;
}

$sleep_time = 200;

function dd($data = "")
{
$result = "";
$data2 = "";
for ( $j = 0; $j < count($data); $j++ )
{
$data2 = dechex(ord($data[0]));
if ( strlen($data2) == 1 )
$result = "0".$data2;
else
$result .= $data2;

}
return $result;
}

# Инициализация соединения, передача пароля
dio_write($fd, "\x00\x01\x01\x01\x01\x01\x01\x01\x01\x77\x81", 11);
usleep_win($sleep_time);
$result = dio_read($fd, 15);

$n = 0;
$total_cnt = 90;
$total_cnt1 = 1080;
while ( $n == 0 )
{

# Сила тока по фазам
# =====================================================
$Ia = merc_gd("\x00\x08\x16\x21\x4F\x9E", 0.001);
echo "Ia: $Ia[0] - $Ia[1] - $Ia[2]";
$It = $Ia[0] + $Ia[1] + $Ia[2];
# Мощность по фазам
# =====================================================
$Pv = merc_gd("\x00\x08\x16\x00\x8F\x86", 0.01);
if ( round($Pv[0], 2) != round($Pv[1] + $Pv[2] + $Pv[3], 2) )
$error = "error"; else $error = "";
echo "Pv: $Pv[0] - $Pv[1] - $Pv[2] - $Pv[3] $error";
# Cosf по фазам
# =====================================================
$Cos = merc_gd("\x00\x08\x16\x30\x8F\x92", 0.001);
echo "Cos: $Cos[0] - $Cos[1] - $Cos[2] - $Cos[3]";

# Напряжение по фазам
# =====================================================
$Uv = merc_gd("\x00\x08\x16\x11\x4F\x8A", 0.01);
echo "Uv: $Uv[0] - $Uv[1] - $Uv[2]";

$total_cnt++;
if ( $total_cnt >= 90 )
{
// Общее потребление
$Tot = merc_gd("\x00\x05\x00\x00\x10\x25", 0.001, 1);
echo "Total: $Tot[0]";

$Tot = merc_gd("\x00\x05\x00\x01\xD1\xE5", 0.001, 1);
echo "Total T1: $Tot[0]";

$Tot = merc_gd("\x00\x05\x00\x02\x91\xE4", 0.001, 1);
echo "Total T2: $Tot[0]";

// За текущие сутки
$Tot = merc_gd("\x00\x05\x40\x00\x21\xE5", 0.001, 1);
echo "Total cur: $Tot[0]";

// За текущие сутки (Тариф 1)
$Tot = merc_gd("\x00\x05\x40\x01\xE0\x25", 0.001, 1);
echo "Total cur T1: $Tot[0]";

// За текущие сутки (Тариф 2)
$Tot = merc_gd("\x00\x05\x40\x02\xA0\x24", 0.001, 1);
echo "Total cur T2: $Tot[0]";

$total_cnt = 0;
}

$total_cnt1++;
if ( $total_cnt1 >= 1080 )
{
// За предыдущие сутки
$Tot = merc_gd("\x00\x05\x50\x00\x2C\x25", 0.001, 1);
echo "Total prev: $Tot[0]";

// За предыдущие сутки (Тариф 1)
$Tot = merc_gd("\x00\x05\x50\x01\xED\xE5", 0.001, 1);
echo "Total prev T1: $Tot[0]";

// За предыдущие сутки (Тариф 2)
$Tot = merc_gd("\x00\x05\x50\x02\xAD\xE4", 0.001, 1);
echo "Total prev T2: $Tot[0]";

$total_cnt1 = 0;
}

sleep(10);
}

# Завершение соединения
dio_write($fd, "\x00\x02\x80\x71", 4);
usleep_win($sleep_time);
$result = dio_read($fd, 8);
dio_close($fd);

?>


И так:

<?php
exec('mode COM3: baud=9600 data=8 stop=1 parity=n xon=off');
// Несмотря на настройки, порт правильно не откравается, перед запуском скрипта надо запустить родной софт
// причины такого поведения пока не выяснены

$f = fopen("COM3","r+");
$i=0;
$cmd = array(0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x77,0x81); // Команда "Мгновенные значения"
$c="";
for($i=0; $i < count($cmd); $i++){$c .= chr($cmd[$i]);} // Сформировать строку символов для посылки в COM-порт
fwrite($f,$c);
$result=fread($f,15);
echo "1: $result";
fclose($f);
?>
LutsenkoDenis
Сообщения: 521
Зарегистрирован: Вс апр 07, 2013 9:30 pm
Откуда: Moscow
Благодарил (а): 2 раза
Поблагодарили: 58 раз
Контактная информация:

Re: Вопрос знатокам PHP под Win

Сообщение LutsenkoDenis » Пн апр 06, 2015 11:44 am

dio_open (PHP 4 >= 4.2.0, PHP 5 <= 5.0.5)
Какая версия php у тебя?
________________________________________________________
Majordomo (GitHub) на HP Microserver Gen8. OS Debian Stretch
Victor_S
Сообщения: 265
Зарегистрирован: Пт дек 26, 2014 1:58 pm
Благодарил (а): 33 раза
Поблагодарили: 24 раза

Re: Вопрос знатокам PHP под Win

Сообщение Victor_S » Пн апр 06, 2015 11:50 am

php 5.4.30
php_dio.dll 0.0.7
phpinfo() говорит dio support enable
Victor_S
Сообщения: 265
Зарегистрирован: Пт дек 26, 2014 1:58 pm
Благодарил (а): 33 раза
Поблагодарили: 24 раза

Re: Вопрос знатокам PHP под Win

Сообщение Victor_S » Пн апр 06, 2015 11:52 am

Версия php_dio.dll 5.4.20
Victor_S
Сообщения: 265
Зарегистрирован: Пт дек 26, 2014 1:58 pm
Благодарил (а): 33 раза
Поблагодарили: 24 раза

Re: Вопрос знатокам PHP под Win

Сообщение Victor_S » Ср апр 08, 2015 10:38 am

Что-то не густо со знатоками...:)
Впрочем данную проблему я решил, но столкнулся с новой...теперь она более конкретная и не зависит от операционки, просто знаний языка программирования у меня нету, не программист я...:(
Задача в следующем. Есть такой код:
#if (!$this->getProperty('Address')) {$this->setProperty('Address',0x00);}
$address=$this->getProperty('Address');
$addr = dechex((string)$address);

# Инициализация соединения, передача пароля(111111)
$Datam = array($address,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01);
$crcmodbus = CRC_MODBUS($Datam);
$crc = str_split(dechex($crcmodbus), 2);
$cmdInit = '\x'.$addr.'\x01\x01\x01\x01\x01\x01\x01\x01\x'.$crc[1].'\x'.$crc[0];
$this->setProperty('cInit',$cmdInit);


Если вместо:
$address=$this->getProperty('Address');
написать просто:
$address=0x5e;(именно в таком формате, а не просто 5е)
Это шестнадцатеричное представление адреса моего счетчика(94)
То все работает как нужно, т.е. я получаю правильные команды для отправки счетчику по нужному адресу и с правильно посчитанными CRC кодами.
Но вот никак не могу записать такое шестнадцатеричное значение в свойство объекта. А лучше бы в свойстве указать десятеричный адрес, а в переменной $address получить значение вида 0x5e.
Как это можно сделать?
Аватара пользователя
sergejey
Site Admin
Сообщения: 4286
Зарегистрирован: Пн сен 05, 2011 6:48 pm
Откуда: Минск, Беларусь
Благодарил (а): 76 раз
Поблагодарили: 1559 раз
Контактная информация:

Re: Вопрос знатокам PHP под Win

Сообщение sergejey » Ср апр 08, 2015 11:16 am

можно попробовать сделать так
$address=base_convert($this->getProperty('Address'), 16, 10);

Сергей Джейгало, разработчик MajorDoMo
Идеи, ошибки -- за предложениями по исправлению и развитию слежу только здесь!
Профиль Connect -- информация, сотрудничество, услуги
LutsenkoDenis
Сообщения: 521
Зарегистрирован: Вс апр 07, 2013 9:30 pm
Откуда: Moscow
Благодарил (а): 2 раза
Поблагодарили: 58 раз
Контактная информация:

Re: Вопрос знатокам PHP под Win

Сообщение LutsenkoDenis » Ср апр 08, 2015 11:20 am

Victor_S писал(а):Но вот никак не могу записать такое шестнадцатеричное значение в свойство объекта. А лучше бы в свойстве указать десятеричный адрес, а в переменной $address получить значение вида 0x5e.
Как это можно сделать?
0x - это префикс, который как бы говорит тебе и php, что последующее значение за ним - это число в HEX'ах
Те. 0x5e и 5e это одно и тоже.

Т.е. в свойстве ты можешь указывать десятичное значение.
При получении значения в переменную переводим в dec в hex и подставляем префикс к результату 0x.

Пример:

Код: Выделить всё

$addrDec = 94;
$addrHex = "0x5e";
$resHex = "0x" . dechex($addrDec);
$resDex = hexdec($resHex);

echo "Исходные значения: Dec:" . $addrDec . " Hex: " . $addrHex . "<br />";
echo "После конвертации: Dec to Hex " . $resHex . " Конвертируем полученный результат обратно в Dec: " . $resDex;
________________________________________________________
Majordomo (GitHub) на HP Microserver Gen8. OS Debian Stretch
Victor_S
Сообщения: 265
Зарегистрирован: Пт дек 26, 2014 1:58 pm
Благодарил (а): 33 раза
Поблагодарили: 24 раза

Re: Вопрос знатокам PHP под Win

Сообщение Victor_S » Ср апр 08, 2015 12:05 pm

Ребята, все эти вещи я понял и сам, и разумеется перепробовал. Вся фишка в том, что мне нужно в массив $Datam = array($address,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01); подставить не строковое представление, а шестнадцатеричное в конкретном формате, иначе crc считает не правильно.
Ответить