meep
Joined: | Saturday Sep 6th, 2014 |
Location: | |
Posts: | 11 |
Status: |
Offline
|
back to top
|
Well, I managed to get this working on windows with Win32::SerialPort in Perl. (just couldn't hack the above code to work so started afresh).
It's a long way from cab123's original driver in terms of code but owes a lot to his concept, structure and techniques. It's also got a LOT less error checking implemented so is really just a proof of concept at this stage and would require a few more additions to make it more robust.
While this does send and receive between comfort and MQTT, and you can check these messages in Node-Red, I added a Trace function to allow key messages be printed to the console - really helps with debugging.
!/usr/bin/perl
use Net::MQTT::Simple;
use Win32::SerialPort;
use strict;
use warnings;
#hello
print STDERR "\n".localtime()."\nOpening Comfort Communications... \n";
#Set up & open port
my $port = Win32::SerialPort->new("COM5") or die "Failed to open port: $!\n";
print STDERR "Port established: $port \n";
$port->baudrate(9600);
$port->databits(8);
$port->parity("none");
$port->stopbits(1);
$port->handshake("xoff");
$port->write_settings;
#set up mqtt & polling for inbound messages
my $mqtt_hostname = '192.168.1.199';
my $mqtt_to_comfort = "comfort/to";
my $mqtt_from_comfort = "comfort/from";
my $mqtt = Net::MQTT::Simple->new($mqtt_hostname);
$mqtt->subscribe($mqtt_to_comfort,&callback);
#additional control vars
my $serial_stream = ""; #container for serial input from comfort
my $ts = time(); #current time
my $defaultreadspeed = 1; #port read interval
my $trace = 1; #enable debug output to console
#setup complete
print STDERR "Starting to listen...\n";
while (1) { #main loop
if ( time() - $ts > $defaultreadspeed ) { #use $defaultreadspeed to throttle
$ts = time(); #set target time for next loop
$serial_stream = $port->read(200); #read up to 200 bytes from Comfort
if ($serial_stream) { #check if there's data read
doTrace ("received from Comfort: $serial_stream");
#split the data into an array based on STX or EOL
#remove those extraneous characters from the resulting array elements
my @reports = split /(?:\x03|\x0D|\x0A)/, $serial_stream;
for my $rep (@reports) { #loop through each of the returned strings
if (length($rep)){ #only process non-empty strings
doTrace ("sending report to MQTT: $rep");
$mqtt->publish($mqtt_from_comfort => $rep); #send to MQTT
}else{
doTrace("empty string, not sending to MQTT");
}
}
$port->lookclear; #needed to prevent blocking (?)
} #end check if data read
$mqtt->tick(1); #force query MQTT input with 1 second timeout
} #time check
}#while loop
################
##SUBROUTINES##
##############
sub callback { #process inputs from MQTT and send to Comfort
my ($topic, $message) = @_;
doTrace ("got message from MQTT: $message");
$port->lookclear; #needed to prevent blocking (?)
my $str = chr(0x03).$message."\r\n"; #prepend STX char and add CR
$port->write($str); #send to Comfort
doTrace ("sent to Comfort: $str");
}
sub doTrace { #write trace logs to console
my ($traceString) = @_;
if ($trace){ #only implement if enabled
my $timestamp = getLoggingTime(); #get timestamp
print STDERR "$timestamp $traceString \n"; #print to console
}
}
sub getLoggingTime { #compose a decent looking timestamp
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
my $nice_timestamp = sprintf ( "%04d%02d%02d %02d:%02d:%02d",
$year+1900,$mon+1,$mday,$hour,$min,$sec);
return $nice_timestamp;
} |
This can be tested with something like the command below at the command line. Obviously change your own Mosquito server and port details. (note, you must first issue the login (LI) command to Comfort, with a user code, or it will keep returning 'NA' as the response);
mosquito_pub -h 192.168.1.199 -p 1883 -t comfort/to -m "z?" |
Attached is an example of this running. You can see the initial receipt of the "z?" query from MQTT and the response from comfort sent back. Then you can see Comfort reporting activity Input 05 (that's the result of me opening and closing a window with a contact sensor).
NB: For some reason, the forum is stripping backslashes from the code segments above. I've tried to add them back in but if you're trying to run this and it's failing, it mey be due to a missing '\' somewhere.
Attachment: Capture.PNG (Downloaded 115 times) Last edited on Monday Oct 10th, 2016 12:09 pm by meep
|