|
<?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); |
@PepeLuis1959
En parte mi idea era realizar un dataloger con Arduino y o bien descargar datos mediante eth o bien que se suban los datos cada tanto a una web.
Por cosas de la vida tengo el proyecto aparcado y tal vez cuando lo retome lo haga mediante una Rasberry o similar ya que además de poder reutilizar el código en PHP que tengo tendría el LAMP incluido para la página de análisis de consumo. Por no decir que podría tener mi propia centralita de VoIP.