|
<?php |
|
function set_win_port_attr ($port_name = 'com1:', $port_attr = ['baud' => 9600, 'data' => 8, 'stop' => 1, 'parity' => 'n']) { |
|
$mode = 'mode ' . $port_name; |
|
foreach ($port_attr as $attr => $value) { |
|
$mode .= ' ' . $attr . '=' . $value; |
|
} |
|
|
|
exec($mode, $output, $return); |
|
|
|
return $return; |
|
} |
|
|
|
function crc16 ($data) { |
|
$crc = 0xFFFF; |
|
foreach (unpack('C*', $data) as $byte) { |
|
$crc ^= $byte; |
|
for ($j = 8; $j; $j--) { |
|
$crc = ($crc >> 1) ^ (($crc & 0x0001) * 0xA001); |
|
} |
|
} |
|
|
|
return pack('v1', $crc); |
|
} |
|
|
|
$modbus_message_format = [ |
|
'address' => 'C1', |
|
'function' => 'C1', |
|
'start' => 'n1', |
|
'quantity' => 'n1', |
|
//'crc' => 'n1', |
|
]; |
|
|
|
$modbus_message_pack = implode($modbus_message_format); |
|
$modbus_message_unpack = null; |
|
foreach ($modbus_message_format as $name => $format) { |
|
$modbus_message_unpack .= $format . $name . '/'; |
|
} |
|
|
|
$modbus_response_format = [ |
|
'address' => 'C1', |
|
'function' => 'C1', |
|
'count' => 'C1', |
|
'total_energy' => 'N1', |
|
'reserved' => 'N3', |
|
'export_energy' => 'N1', |
|
'import_energy' => 'N1', |
|
'voltage' => 'n1', |
|
'current' => 'n1', |
|
'active_power' => 'n1', |
|
'reactive_power' => 'n1', |
|
'power_factor' => 'n1', |
|
'frecuency' => 'n1', |
|
//'year' => 'C1', |
|
//'month' => 'C1', |
|
//'day' => 'C1', |
|
//'hour' => 'C1', |
|
//'minute' => 'C1', |
|
//'second' => 'C1', |
|
//'comm_addr' => 'C1', |
|
//'comm_baud' => 'C1', |
|
//'trip_energy' => 'N1', |
|
//'trip_time' => 'N1', |
|
//'unknow' => 'n5', |
|
//'month2' => 'C1', |
|
//'day2' => 'C1', |
|
'crc' => 'n1', |
|
]; |
|
|
|
$modbus_response_pack = implode($modbus_response_format); |
|
$modbus_response_unpack = null; |
|
foreach ($modbus_response_format as $name => $format) { |
|
$modbus_response_unpack .= $format . $name . '/'; |
|
} |
|
|
|
$port_name = 'COM3:'; |
|
$port_attr = ['baud' => 9600, 'data' => 8, 'stop' => 1, 'parity' => 'n', 'xon' => 'off']; |
|
set_win_port_attr($port_name, $port_attr); |
|
|
|
$modbus = fopen($port_name, 'rb+'); |
|
|
|
$message = [0x01, 0x03, 0, 18]; |
|
$message = pack($modbus_message_pack, ...$message); |
|
$message .= crc16($message); |
|
|
|
fwrite($modbus, $message); |
|
|
|
$buffer = null; |
|
do { |
|
usleep($buffer ? 5000 : 100000); |
|
$buffer .= fread($modbus, 1); |
|
} while (!feof($modbus)); |
|
|
|
if (crc16(substr($buffer, 0, -2)) != substr($buffer, -2)) { |
|
echo __LINE__, PHP_EOL; |
|
echo bin2hex($buffer), PHP_EOL; |
|
echo bin2hex(substr($buffer, 0, -2)), PHP_EOL; |
|
echo bin2hex(substr($buffer, -2)), PHP_EOL; |
|
die(); |
|
} |
|
|
|
$response = unpack($modbus_response_unpack, $buffer); |
|
|
|
//print_r($response); |
|
|
|
$data_scale = [ |
|
'total_energy' => 1/100, // daWh / 100 => kWh |
|
'export_energy' => 1/100, // daWh / 100 => kWh |
|
'import_energy' => 1/100, // daWh / 100 => kWh |
|
'voltage' => 1/10, // dV / 10 => V |
|
'current' => 1/100, // cA / 100 => A |
|
'active_power' => 1, // W |
|
'reactive_power' => 1, // VA |
|
'power_factor' => 1/1000, |
|
'frecuency' => 1/100, // cHz / 100 => Hz |
|
//'comm_addr' => 1, |
|
//'comm_baud' => 1, // [1 => 9600, 2 => 4800, 3 => 2400, 4 => 1200] |
|
//'trip_energy' => 1/100, // daWh / 100 => kWh |
|
]; |
|
|
|
$data = []; |
|
foreach ($data_scale as $key => $scale) { |
|
$data[$key] = isset($response[$key]) ? $response[$key] * $scale : null; |
|
} |
|
|
|
print_r($data); |
|
|
|
echo "\nok"; |
|
fclose($modbus); |