[Модуль] Счетчики Меркурий (mercury)

Разработка дополнительных модулей, подключение различных приложений.

Модератор: immortal

ученик
Сообщения: 230
Зарегистрирован: Чт фев 12, 2015 2:34 pm
Благодарил (а): 36 раз
Поблагодарили: 6 раз

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение ученик » Вт окт 30, 2018 7:23 am

directman66 писал(а):
Пн окт 29, 2018 10:31 pm
Просьба сохранить скрином hex.
В приложении скрины
весь протокол связи соединения со счетчиком меркурий
Вложения
меркурий.zip
(328.79 КБ) 164 скачивания
server i5, OS-Ubuntu Server 16., 1-wire
php 7, AMS,broadlink rm2,rm3 mini.
Fav0rit
Сообщения: 60
Зарегистрирован: Чт мар 19, 2015 10:27 pm
Благодарил (а): 8 раз
Поблагодарили: 22 раза

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение Fav0rit » Пт ноя 02, 2018 10:15 am

Поставил, подключилось, сразу заметил некоторые особенности/ошибки.
1) при добавлении счетчика Меркурий 230 у меня почему-то добавляется два одинаковых счетчика.
2) при нескольких созданиях/удалениях счетчика в модуле, в объектах оказалось целых 5 объектов. Думаю, целесообразно запрашивать серийный номер счетчика автоматически и давать имя в соответствии с ним, тогда команда на создание объекта будет не будет клепать новые счетчики.
3) интеграция через объекты - не самая очевидная, надо хотя бы в модуле об этом написать, а то не сразу понятно как привязать считанные параметры к объектам. По-хорошему, надо бы это сделать по аналогии с другими модулями, где слева параметр и значение, а справа - привязка свойств.
4) со счетчика получаю какие-то заоблачные показания мощности.
СпойлерПоказать
02/11/18 10:59 запущен запрос данных по счетчику 11
Сокет создан.
Пытаемся соединиться с '192.168.7.70' на порту '8000'...
Соединение установлено.
Ia: 0.074 - 0 - 0 IaT:0.074
Pv: 125844.21 - 125844.21 - 0 - 0
Cos: 12583.81 - 12583.81 - 0 - 0
Uv: 218 - 0 - 0
Total: 17225.871
Total T1: 17224.374
Total T2: 1.497
Закрываем сокет...OK.
Я понимаю, что разработка модуля это частная инициатива и не в праве чего-то требовать, поэтому это просто пожелания, с целью сделать модуль лучше. Возможно я и сам через гитхаб внесу свою лепту...
Последний раз редактировалось Fav0rit Пт ноя 02, 2018 10:28 am, всего редактировалось 1 раз.
gnom537
Сообщения: 111
Зарегистрирован: Вт июн 17, 2014 1:06 pm
Откуда: нижний новгород
Благодарил (а): 5 раз
Поблагодарили: 12 раз

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение gnom537 » Пт ноя 02, 2018 10:23 am

Fav0rit писал(а):
Пт ноя 02, 2018 10:15 am
Поставил, подключилось, сразу заметил некоторые особенности/ошибки.
в итоге то данные от счетчика получаете? какой модели счетчик? данные реальны?
Fav0rit
Сообщения: 60
Зарегистрирован: Чт мар 19, 2015 10:27 pm
Благодарил (а): 8 раз
Поблагодарили: 22 раза

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение Fav0rit » Пт ноя 02, 2018 10:32 am

gnom537 писал(а):
Пт ноя 02, 2018 10:23 am
Fav0rit писал(а):
Пт ноя 02, 2018 10:15 am
Поставил, подключилось, сразу заметил некоторые особенности/ошибки.
в итоге то данные от счетчика получаете? какой модели счетчик? данные реальны?
Меркурий 230.
Данные получаю, но правильные только накопленные показания в кВт*ч и напряжение по фазам. Ток, чувствую, на два порядка меньше нормы, а мощность вообще хз...
directman66
Сообщения: 2801
Зарегистрирован: Пн дек 26, 2016 9:51 am
Откуда: Екатеринбург
Благодарил (а): 380 раз
Поблагодарили: 693 раза
Контактная информация:

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение directman66 » Пт ноя 02, 2018 11:51 am

С однофазными пока не тестировал, чуть позже займусь. Пока в приоритете другие задачи и нет опытного образца.
Выкладываю сценарий, по которому забираются данные с 3х фазного счетчика. Если вам удастся его адаптировать под 2х фазный - сообщите, что изменили, внесем правки.

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

//$ot = $this->object_title;
//setTimeOut($ot.'_updateValue','callMethod("'.$ot.'.GetValues");',10);

$address252 = '193.233.6.156';
$service_port252 =' 20252';
$device252 = '0E';

/* Создаём сокет TCP/IP. */
$socket252 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket252,SOL_SOCKET, SO_RCVTIMEO, array("sec"=>5, "usec"=>0));
if ($socket252 === false) {
    echo "Не удалось выполнить socket_create(): причина: " . socket_strerror(socket_last_error()) . "<br>";
} else {
    echo "OK.<br>";
}

echo "Пытаемся соединиться с '$address252' на порту '$service_port252'...";
$result = socket_connect($socket252, $address252, $service_port252);
if ($result === false) {
    echo "Не удалось выполнить socket_connect().\nПричина: ($result) " . socket_strerror(socket_last_error($socket)) . "<br>";
} else {
    echo "OK.<br>";
}
if (!function_exists('send')) {
    function send  ($socket252, $hex = "") {
     echo "Отправляем запрос ".$hex;
  $in = hex2bin($hex);
  echo " ".$in." ";
  socket_write($socket252, $in, strlen($in));
  echo "OK.<br>"; 
   }
 }  
//
//function send($socket252, $hex = "")
//{
//  echo "Отправляем запрос ".$hex;
//  $in = hex2bin($hex);
//  echo " ".$in." ";
//  socket_write($socket252, $in, strlen($in));
//  echo "OK.<br>";
//}

if (!function_exists('read')) {
    function read  ($socket252)
{
   echo "Читаем ответ:\n\n";
   $out = socket_read($socket252, 2048);
   echo bin2hex($out)."<br>";
   return $out;
}
}

//function read($socket252)
//{
////   echo "Читаем ответ:\n\n";
///   $out = socket_read($socket252, 2048);
//   echo bin2hex($out)."<br>";
//   return $out;
//}

if (!function_exists('dd')) {
    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;
}
     
    }

//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;
//}
if (!function_exists('merc_gd')) {
function merc_gd($socket252, $cmd, $factor = 1, $total = 0)
{
	send($socket252, $cmd);
    $result = read($socket252);

	$ret = array();
	
	$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;
}}
if (!function_exists('crc16_modbus')) {
function crc16_modbus($msg)
{
    $data = pack('H*',$msg);
    $crc = 0xFFFF;
    for ($i = 0; $i < strlen($data); $i++)
    {
        $crc ^=ord($data[$i]);

        for ($j = 8; $j !=0; $j--)
        {
            if (($crc & 0x0001) !=0)
            {
                $crc >>= 1;
                $crc ^= 0xA001;
            }
            else $crc >>= 1;
        }
    }   
    return sprintf('%04X', $crc);
}}
if (!function_exists('calcCRC')) {
function calcCRC($device252,$msg)
{
 $mess = $device252.$msg;
 $crc = crc16_modbus($mess);
 return $mess.$crc[2].$crc[3].$crc[0].$crc[1];
}}
 
send($socket252, calcCRC($device252,"0101010101010101"));
read($socket252);

# Сила тока по фазам
# =====================================================
$Ia = merc_gd($socket252,calcCRC($device252,"081621"), 0.001);
$It = $Ia[0] + $Ia[1] + $Ia[2];
echo "Ia: $Ia[0] - $Ia[1] - $Ia[2] IaT:$It<br>";

$classname='Mercury';
$objname=$classname.'_test';
addClassObject($classname,$objname);


if ($Ia[0]) {sg($objname.'.Ia1',$Ia[0]); $sql['Ia1']=$Ia[0];}
if ($Ia[1]) {sg($objname.'.Ia2',$Ia[1]); $sql['Ia2']=$Ia[1];}
if ($Ia[2]) {sg($objname.'.Ia3',$Ia[2]); $sql['Ia3']=$Ia[2];}
if ($It) {sg($objname.'.IaT',$It); $sql['IaT']=$It;}

# Мощность по фазам
# =====================================================
$Pv = merc_gd($socket252,calcCRC($device252,"081600"), 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<br>";
if ($error == "")
{
sg($objname.'.PvT',round($Pv[0],0));
sg($objname.'.Pv1',$Pv[1]);
sg($objname.'.Pv2',$Pv[2]);
sg($objname.'.Pv3',$Pv[3]);

$sql['PvT']=round($Pv[0],0);
$sql['Pv1']=$Pv[1];
$sql['Pv2']=$Pv[2];
$sql['Pv3']=$Pv[3];
}
# Cosf по фазам
# =====================================================
$Cos = merc_gd($socket252,calcCRC($device252,"081630"), 0.001);
echo "Cos: $Cos[0] - $Cos[1] - $Cos[2] - $Cos[3]<br>";
if ($Cos[0]) {sg($objname.'.CosT',$Cos[0]); $sql['CosT']=$Cos[0];}
if ($Cos[0]) {sg($objname.'.Cos1',$Cos[1]); $sql['Cos1']=$Cos[1];}
if ($Cos[0]) {sg($objname.'.Cos2',$Cos[2]); $sql['Cos2']=$Cos[2];}
if ($Cos[0]) {sg($objname.'.Cos3',$Cos[3]); $sql['Cos3']=$Cos[3];}
# Напряжение по фазам
# =====================================================
$Uv = merc_gd($socket252,calcCRC($device252,"081611"), 0.01);
echo "Uv: $Uv[0] - $Uv[1] - $Uv[2]<br>";
if ($Uv[0]) {sg($objname.'.Uv1',round($Uv[0],0));$sql['Uv1']=round($Uv[0],0);}
if ($Uv[0]) {sg($objname.'.Uv2',round($Uv[1],0));$sql['Uv2']=round($Uv[1],0);}
if ($Uv[0]) {sg($objname.'.Uv3',round($Uv[2],0));$sql['Uv3']=round($Uv[2],0);}

# Показания электроэнергии
# =====================================================
$Tot = merc_gd($socket252,calcCRC($device252,"050000"), 0.001, 1);
echo "Total: $Tot[0]<br>";
if ($Tot[0]) {sg($objname.'.Total',round($Tot[0],0)); $sql['Total']=round($Tot[0],0);}
$Tot = merc_gd($socket252,calcCRC($device252,"050001"), 0.001, 1);
echo "Total T1: $Tot[0]<br>";
if ($Tot[0]) {sg($objname.'.Total1',$Tot[0]); $sql['Total1']=$Tot[0];}
$Tot = merc_gd($socket252,calcCRC($device252,"050002"), 0.001, 1);
echo "Total T2: $Tot[0]<br>";
if ($Tot[0]) {sg($objname.'.Total2',$Tot[0]);$sql['Total2']=$Tot[0];}

echo "Закрываем сокет...";
socket_close($socket252);
echo "OK.\n\n";


Последний раз редактировалось directman66 Вт ноя 13, 2018 1:15 pm, всего редактировалось 1 раз.
Если вам помогло данное сообщение, не поленитесь нажать кнопку "спасибо".
CONNECT | Оборудование | Блог | Дополнения | Email | Telegram
Fav0rit
Сообщения: 60
Зарегистрирован: Чт мар 19, 2015 10:27 pm
Благодарил (а): 8 раз
Поблагодарили: 22 раза

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение Fav0rit » Пт ноя 02, 2018 12:19 pm

directman66 писал(а):
Пт ноя 02, 2018 11:51 am
С двухфазными пока не тестировал, чуть позже займусь. Пока в приоритете другие задачи и нет опытного образца.
Выкладываю сценарий, по которому забираются данные с 3х фазного счетчика. Если вам удастся его адаптировать под 2х фазный - сообщите, что изменили, внесем правки.

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

//$ot = $this->object_title;
//setTimeOut($ot.'_updateValue','callMethod("'.$ot.'.GetValues");',10);

$address252 = '193.233.6.156';
$service_port252 =' 20252';
$device252 = '0E';

/* Создаём сокет TCP/IP. */
$socket252 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket252,SOL_SOCKET, SO_RCVTIMEO, array("sec"=>5, "usec"=>0));
if ($socket252 === false) {
    echo "Не удалось выполнить socket_create(): причина: " . socket_strerror(socket_last_error()) . "<br>";
} else {
    echo "OK.<br>";
}

echo "Пытаемся соединиться с '$address252' на порту '$service_port252'...";
$result = socket_connect($socket252, $address252, $service_port252);
if ($result === false) {
    echo "Не удалось выполнить socket_connect().\nПричина: ($result) " . socket_strerror(socket_last_error($socket)) . "<br>";
} else {
    echo "OK.<br>";
}
if (!function_exists('send')) {
    function send  ($socket252, $hex = "") {
     echo "Отправляем запрос ".$hex;
  $in = hex2bin($hex);
  echo " ".$in." ";
  socket_write($socket252, $in, strlen($in));
  echo "OK.<br>"; 
   }
 }  
//
//function send($socket252, $hex = "")
//{
//  echo "Отправляем запрос ".$hex;
//  $in = hex2bin($hex);
//  echo " ".$in." ";
//  socket_write($socket252, $in, strlen($in));
//  echo "OK.<br>";
//}

if (!function_exists('read')) {
    function read  ($socket252)
{
   echo "Читаем ответ:\n\n";
   $out = socket_read($socket252, 2048);
   echo bin2hex($out)."<br>";
   return $out;
}
}

//function read($socket252)
//{
////   echo "Читаем ответ:\n\n";
///   $out = socket_read($socket252, 2048);
//   echo bin2hex($out)."<br>";
//   return $out;
//}

if (!function_exists('dd')) {
    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;
}
     
    }

//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;
//}
if (!function_exists('merc_gd')) {
function merc_gd($socket252, $cmd, $factor = 1, $total = 0)
{
	send($socket252, $cmd);
    $result = read($socket252);

	$ret = array();
	
	$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;
}}
if (!function_exists('crc16_modbus')) {
function crc16_modbus($msg)
{
    $data = pack('H*',$msg);
    $crc = 0xFFFF;
    for ($i = 0; $i < strlen($data); $i++)
    {
        $crc ^=ord($data[$i]);

        for ($j = 8; $j !=0; $j--)
        {
            if (($crc & 0x0001) !=0)
            {
                $crc >>= 1;
                $crc ^= 0xA001;
            }
            else $crc >>= 1;
        }
    }   
    return sprintf('%04X', $crc);
}}
if (!function_exists('calcCRC')) {
function calcCRC($device252,$msg)
{
 $mess = $device252.$msg;
 $crc = crc16_modbus($mess);
 return $mess.$crc[2].$crc[3].$crc[0].$crc[1];
}}
 
send($socket252, calcCRC($device252,"0101010101010101"));
read($socket252);

# Сила тока по фазам
# =====================================================
$Ia = merc_gd($socket252,calcCRC($device252,"081621"), 0.001);
$It = $Ia[0] + $Ia[1] + $Ia[2];
echo "Ia: $Ia[0] - $Ia[1] - $Ia[2] IaT:$It<br>";

$classname='Mercury';
$objname=$classname.'_test';
addClassObject($classname,$objname);


if ($Ia[0]) {sg($objname.'.Ia1',$Ia[0]); $sql['Ia1']=$Ia[0];}
if ($Ia[1]) {sg($objname.'.Ia2',$Ia[1]); $sql['Ia2']=$Ia[1];}
if ($Ia[2]) {sg($objname.'.Ia3',$Ia[2]); $sql['Ia3']=$Ia[2];}
if ($It) {sg($objname.'.IaT',$It); $sql['IaT']=$It;}

# Мощность по фазам
# =====================================================
$Pv = merc_gd($socket252,calcCRC($device252,"081600"), 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<br>";
if ($error == "")
{
sg($objname.'.PvT',round($Pv[0],0));
sg($objname.'.Pv1',$Pv[1]);
sg($objname.'.Pv2',$Pv[2]);
sg($objname.'.Pv3',$Pv[3]);

$sql['PvT']=round($Pv[0],0);
$sql['Pv1']=$Pv[1];
$sql['Pv2']=$Pv[2];
$sql['Pv3']=$Pv[3];
}
# Cosf по фазам
# =====================================================
$Cos = merc_gd($socket252,calcCRC($device252,"081630"), 0.001);
echo "Cos: $Cos[0] - $Cos[1] - $Cos[2] - $Cos[3]<br>";
if ($Cos[0]) {sg($objname.'.CosT',$Cos[0]); $sql['CosT']=$Cos[0];}
if ($Cos[0]) {sg($objname.'.Cos1',$Cos[1]); $sql['Cos1']=$Cos[1];}
if ($Cos[0]) {sg($objname.'.Cos2',$Cos[2]); $sql['Cos2']=$Cos[2];}
if ($Cos[0]) {sg($objname.'.Cos3',$Cos[3]); $sql['Cos3']=$Cos[3];}
# Напряжение по фазам
# =====================================================
$Uv = merc_gd($socket252,calcCRC($device252,"081611"), 0.01);
echo "Uv: $Uv[0] - $Uv[1] - $Uv[2]<br>";
if ($Uv[0]) {sg($objname.'.Uv1',round($Uv[0],0));$sql['Uv1']=round($Uv[0],0);}
if ($Uv[0]) {sg($objname.'.Uv2',round($Uv[1],0));$sql['Uv2']=round($Uv[1],0);}
if ($Uv[0]) {sg($objname.'.Uv3',round($Uv[2],0));$sql['Uv3']=round($Uv[2],0);}

# Показания электроэнергии
# =====================================================
$Tot = merc_gd($socket252,calcCRC($device252,"050000"), 0.001, 1);
echo "Total: $Tot[0]<br>";
if ($Tot[0]) {sg($objname.'.Total',round($Tot[0],0)); $sql['Total']=round($Tot[0],0);}
$Tot = merc_gd($socket252,calcCRC($device252,"050001"), 0.001, 1);
echo "Total T1: $Tot[0]<br>";
if ($Tot[0]) {sg($objname.'.Total1',$Tot[0]); $sql['Total1']=$Tot[0];}
$Tot = merc_gd($socket252,calcCRC($device252,"050002"), 0.001, 1);
echo "Total T2: $Tot[0]<br>";
if ($Tot[0]) {sg($objname.'.Total2',$Tot[0]);$sql['Total2']=$Tot[0];}

echo "Закрываем сокет...";
socket_close($socket252);
echo "OK.\n\n";


Счетчик то трехфазный... Заметил еще что серийный номер определяется неправильно. Мой 07054850, а в программе 754850
directman66
Сообщения: 2801
Зарегистрирован: Пн дек 26, 2016 9:51 am
Откуда: Екатеринбург
Благодарил (а): 380 раз
Поблагодарили: 693 раза
Контактная информация:

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение directman66 » Пт ноя 02, 2018 12:55 pm

Если сможете прокинуть адрес и порт счетчика в интернет, постараюсь посмотреть, как будет возможность.
Если вам помогло данное сообщение, не поленитесь нажать кнопку "спасибо".
CONNECT | Оборудование | Блог | Дополнения | Email | Telegram
gnom537
Сообщения: 111
Зарегистрирован: Вт июн 17, 2014 1:06 pm
Откуда: нижний новгород
Благодарил (а): 5 раз
Поблагодарили: 12 раз

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение gnom537 » Пт ноя 02, 2018 1:47 pm

directman66 я могу сегодня после 20 дать доступ к тайм виверу до 8 утра, может что найдете!
заодно вечером попробую ваш код.( комментариев бы к нему побольше...)
directman66
Сообщения: 2801
Зарегистрирован: Пн дек 26, 2016 9:51 am
Откуда: Екатеринбург
Благодарил (а): 380 раз
Поблагодарили: 693 раза
Контактная информация:

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение directman66 » Пт ноя 02, 2018 1:50 pm

Напишите в телеграм или вацап. Сегодня "пьятница", у семьи планов на вечер громадье, наверное не получится.
Если вам помогло данное сообщение, не поленитесь нажать кнопку "спасибо".
CONNECT | Оборудование | Блог | Дополнения | Email | Telegram
stellhawk
Сообщения: 264
Зарегистрирован: Чт ноя 08, 2018 5:51 am
Благодарил (а): 10 раз
Поблагодарили: 83 раза

Re: [Модуль] Счетчики Меркурий (mercury)

Сообщение stellhawk » Чт ноя 08, 2018 5:53 am

Подскажите а если счетчик подключен через rs485 /dev/ttyUSB0 , то что прописывать?
Ответить