View single post by meep
 Posted: Monday Oct 10th, 2016 02:39 am
 PM  Quote  Reply  Full Topic 
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

 Close Window