#!/usr/bin/env perl use strict; use Device::SerialPort; use Net::MQTT::Simple; sub chomp_harder($) { my $ret = shift; my $irs = $/; $/ = "\n"; chomp $ret; $/ = "\r"; chomp $ret; $/ = $irs; return $ret; } sub get_line($$) { my ( $port, $mqtt ) = @_; my $ret = ""; while (1) { my ( $count, $byte ) = $port->read(1); $mqtt->tick(); if ( $count > 0 ) { $ret .= $byte; return chomp_harder($ret) if $byte eq "\n"; } else { $ret = chomp_harder($ret); return $ret; } } } my $plc_port = "/dev/ttyS1"; my $plc = new Device::SerialPort($plc_port) || die "can't open $plc_port\n"; $plc->baudrate(38400); $plc->parity("none"); $plc->databits(8); $plc->stopbits(1); $plc->stty_icanon(0); $plc->read_char_time(0); $plc->read_const_time(1000); my $mqtt = Net::MQTT::Simple->new("10.32.139.1"); sub mqtt_msg($$) { my ( $topic, $message ) = @_; $plc->write("MQTT $topic $message\r\n"); } $mqtt->subscribe( 'cmnd/+/var1', \&mqtt_msg ); $mqtt->subscribe( 'cmnd/+/var2', \&mqtt_msg ); $mqtt->subscribe( 'cmnd/+/var3', \&mqtt_msg ); while (1) { my $line = get_line( $plc, $mqtt ); next unless length($line) > 0; if ( $line =~ /MQTT\s+([^\s]+)\s+(.+)/ ) { $mqtt->publish( $1, $2 ); } if ( $line =~ /MQTTR\s+([^\s]+)\s+(.+)/ ) { $mqtt->retain( $1, $2 ); } }